Skip to content

Commit

Permalink
Break out parsing of file naming attributes.
Browse files Browse the repository at this point in the history
  • Loading branch information
barnson authored and robmen committed Dec 29, 2024
1 parent 720708f commit a4fb0e4
Showing 1 changed file with 90 additions and 84 deletions.
174 changes: 90 additions & 84 deletions src/wix/WixToolset.Core/Compiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5070,30 +5070,100 @@ private void ParseExtensionElement(XElement node, string componentId, YesNoType
}
}

private void ParseFileNamingAttributes(XElement node, string sourcePath, string directoryId, bool isNakedFile, out Identifier id, out string name, out string shortName, out string source)
{
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
name = null;
id = null;
shortName = null;
source = sourcePath; // assume we'll use the parents as the source for this file
var sourceSet = false;

foreach (var attrib in node.Attributes())
{
if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
{
switch (attrib.Name.LocalName)
{
case "Id":
id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
break;
case "Name":
name = this.Core.GetAttributeLongFilename(sourceLineNumbers, attrib, false);
break;
case "ShortName":
shortName = this.Core.GetAttributeShortFilename(sourceLineNumbers, attrib, false);
break;
case "Source":
source = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
sourceSet = true;
break;
}
}
}

if (sourceSet && !source.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) && null == name)
{
name = Path.GetFileName(source);
if (!this.Core.IsValidLongFilename(name, false))
{
this.Core.Write(ErrorMessages.IllegalLongFilename(sourceLineNumbers, node.Name.LocalName, "Source", name));
}
}

if (name == null)
{
if (shortName == null)
{
this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name"));
}
else
{
name = shortName;
shortName = null;
}
}

if (String.IsNullOrEmpty(source))
{
source = name;
}
else if (source.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)) // if source relies on parent directories, append the file name
{
source = Path.Combine(source, name);
}

if (null == id && !isNakedFile)
{
id = this.Core.CreateIdentifier("fil", directoryId, name);
}
}

/// <summary>
/// Parses a File element's attributes.
/// </summary>
/// <param name="node">File element to parse.</param>
/// <param name="componentId">Parent's component id.</param>
/// <param name="directoryId">Ancestor's directory id.</param>
/// <param name="diskId">Disk id inherited from parent component.</param>
/// <param name="id">Already-parsed or defaulted id.</param>
/// <param name="name">Already-parsed or defaulted name.</param>
/// <param name="shortName">Already-parsed short name.</param>
/// <param name="sourcePath">Default source path of parent directory.</param>
/// <param name="possibleKeyPath">This will be set with the possible keyPath for the parent component.</param>
/// <param name="componentGuid">Component GUID (including `*`).</param>
/// <param name="isNakedFile">Whether the File element being parsed is outside a Component element.</param>
/// <param name="fileSymbol">Outgoing file symbol containing parsed attributes.</param>
/// <param name="assemblySymbol">Outgoing assembly symbol containing parsed attributes.</param>
/// <returns>Yes if this element was marked as the parent component's key path, No if explicitly marked as not being a key path, or NotSet otherwise.</returns>
private YesNoType ParseFileElementAttributes(XElement node, string componentId, string directoryId, int diskId, string sourcePath, out Identifier possibleKeyPath, string componentGuid, bool isNakedFile, out FileSymbol fileSymbol, out AssemblySymbol assemblySymbol)
private YesNoType ParseFileElementOtherAttributes(XElement node, string componentId, string directoryId, int diskId, Identifier id, string name, string shortName, string sourcePath, out Identifier possibleKeyPath, string componentGuid, bool isNakedFile, out FileSymbol fileSymbol, out AssemblySymbol assemblySymbol)
{
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
Identifier id = null;
var assemblyType = AssemblyType.NotAnAssembly;
string assemblyApplication = null;
string assemblyManifest = null;
string bindPath = null;

//int bits = MsiInterop.MsidbFileAttributesVital;
var readOnly = false;
var checksum = false;
bool? compressed = null;
Expand All @@ -5107,7 +5177,6 @@ private YesNoType ParseFileElementAttributes(XElement node, string componentId,
string defaultVersion = null;
string fontTitle = null;
var keyPath = YesNoType.NotSet;
string name = null;
var patchGroup = CompilerConstants.IntegerNotSet;
var patchIgnore = false;
var patchIncludeWholeFile = false;
Expand All @@ -5121,9 +5190,6 @@ private YesNoType ParseFileElementAttributes(XElement node, string componentId,

string procArch = null;
int? selfRegCost = null;
string shortName = null;
var source = sourcePath; // assume we'll use the parents as the source for this file
var sourceSet = false;

fileSymbol = null;
assemblySymbol = null;
Expand All @@ -5134,6 +5200,13 @@ private YesNoType ParseFileElementAttributes(XElement node, string componentId,
{
switch (attrib.Name.LocalName)
{
case "Id":
case "Name":
case "ShortName":
case "Source":
// Handled in ParseFileNamingAttributes
break;

case "Bitness":
case "Condition":
case "Directory":
Expand All @@ -5144,9 +5217,6 @@ private YesNoType ParseFileElementAttributes(XElement node, string componentId,
this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, attrib.Name.LocalName));
}
break;
case "Id":
id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
break;
case "Assembly":
var assemblyValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
switch (assemblyValue)
Expand Down Expand Up @@ -5225,9 +5295,6 @@ private YesNoType ParseFileElementAttributes(XElement node, string componentId,
case "KeyPath":
keyPath = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
break;
case "Name":
name = this.Core.GetAttributeLongFilename(sourceLineNumbers, attrib, false);
break;
case "PatchGroup":
patchGroup = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int32.MaxValue);
break;
Expand Down Expand Up @@ -5273,13 +5340,6 @@ private YesNoType ParseFileElementAttributes(XElement node, string componentId,
case "SelfRegCost":
selfRegCost = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue);
break;
case "ShortName":
shortName = this.Core.GetAttributeShortFilename(sourceLineNumbers, attrib, false);
break;
case "Source":
source = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
sourceSet = true;
break;
case "System":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
Expand Down Expand Up @@ -5326,33 +5386,6 @@ private YesNoType ParseFileElementAttributes(XElement node, string componentId,
}
}

if (sourceSet && !source.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) && null == name)
{
name = Path.GetFileName(source);
if (!this.Core.IsValidLongFilename(name, false))
{
this.Core.Write(ErrorMessages.IllegalLongFilename(sourceLineNumbers, node.Name.LocalName, "Source", name));
}
}

if (name == null)
{
if (shortName == null)
{
this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name"));
}
else
{
name = shortName;
shortName = null;
}
}

if (null == id && !isNakedFile)
{
id = this.Core.CreateIdentifier("fil", directoryId, name);
}

if (null != defaultVersion && null != companionFile)
{
this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "DefaultVersion", "CompanionFile", companionFile));
Expand Down Expand Up @@ -5400,15 +5433,6 @@ private YesNoType ParseFileElementAttributes(XElement node, string componentId,
patchAttributes |= PatchAttributeType.AllowIgnoreOnError;
}

if (String.IsNullOrEmpty(source))
{
source = name;
}
else if (source.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)) // if source relies on parent directories, append the file name
{
source = Path.Combine(source, name);
}

var attributes = FileSymbolAttributes.None;
attributes |= readOnly ? FileSymbolAttributes.ReadOnly : 0;
attributes |= hidden ? FileSymbolAttributes.Hidden : 0;
Expand All @@ -5430,7 +5454,7 @@ private YesNoType ParseFileElementAttributes(XElement node, string componentId,

DirectoryRef = directoryId,
DiskId = (CompilerConstants.IntegerNotSet == diskId) ? null : (int?)diskId,
Source = new IntermediateFieldPathValue { Path = source },
Source = new IntermediateFieldPathValue { Path = sourcePath },

FontTitle = fontTitle,
SelfRegCost = selfRegCost,
Expand Down Expand Up @@ -5577,7 +5601,9 @@ private void ParseFileElementChildren(XElement node, FileSymbol fileSymbol, YesN
/// <returns>Yes if this element was marked as the parent component's key path, No if explicitly marked as not being a key path, or NotSet otherwise.</returns>
private YesNoType ParseFileElement(XElement node, string componentId, string directoryId, int diskId, string sourcePath, out Identifier possibleKeyPath, bool win64Component, string componentGuid)
{
var keyPath = this.ParseFileElementAttributes(node, componentId, directoryId, diskId, sourcePath, out possibleKeyPath, componentGuid, isNakedFile: false, out var fileSymbol, out var assemblySymbol);
this.ParseFileNamingAttributes(node, sourcePath, directoryId, isNakedFile: false, out var id, out var name, out var shortName, out var source);

var keyPath = this.ParseFileElementOtherAttributes(node, componentId, directoryId, diskId, id, name, shortName, source, out possibleKeyPath, componentGuid, isNakedFile: false, out var fileSymbol, out var assemblySymbol);

if (!this.Core.EncounteredError)
{
Expand Down Expand Up @@ -5659,35 +5685,15 @@ private void ParseNakedFileElement(XElement node, ComplexReferenceParentType par

directoryId = this.HandleSubdirectory(sourceLineNumbers, node, directoryId, subdirectory, "Directory", "Subdirectory");

var keyPath = this.ParseFileElementAttributes(node, "@WixTemporaryComponentId", directoryId, diskId: CompilerConstants.IntegerNotSet, sourcePath, out var _, componentGuid: "*", isNakedFile: true, out var fileSymbol, out var assemblySymbol);
this.ParseFileNamingAttributes(node, sourcePath, directoryId, isNakedFile: true, out var id, out var name, out var shortName, out var source);

// Now that we have all the data we need to generate a good id, do
// so and create a file and component symbol with the right data.
var id = fileSymbol.Id ?? this.Core.CreateIdentifier("nkf", directoryId, fileSymbol.Name, condition, win64.ToString());

this.Core.AddSymbol(new FileSymbol(sourceLineNumbers, id)
{
ComponentRef = id.Id,
Name = fileSymbol.Name,
ShortName = fileSymbol.ShortName,
FileSize = fileSymbol.FileSize,
Version = fileSymbol.Version,
Language = fileSymbol.Language,
Attributes = fileSymbol.Attributes,
DirectoryRef = fileSymbol.DirectoryRef,
DiskId = fileSymbol.DiskId,
Source = fileSymbol.Source,
FontTitle = fileSymbol.FontTitle,
SelfRegCost = fileSymbol.SelfRegCost,
BindPath = fileSymbol.BindPath,
PatchGroup = fileSymbol.PatchGroup,
PatchAttributes = fileSymbol.PatchAttributes,
RetainLengths = fileSymbol.RetainLengths,
IgnoreOffsets = fileSymbol.IgnoreOffsets,
IgnoreLengths = fileSymbol.IgnoreLengths,
RetainOffsets = fileSymbol.RetainOffsets,
SymbolPaths = fileSymbol.SymbolPaths,
});
id = id ?? this.Core.CreateIdentifier("nkf", directoryId, name, condition, win64.ToString());

var keyPath = this.ParseFileElementOtherAttributes(node, id.Id, directoryId, diskId: CompilerConstants.IntegerNotSet, id, name, shortName, source, out var _, componentGuid: "*", isNakedFile: true, fileSymbol: out var fileSymbol, assemblySymbol: out var assemblySymbol);

this.Core.AddSymbol(fileSymbol);

this.Core.AddSymbol(new ComponentSymbol(sourceLineNumbers, id)
{
Expand Down

0 comments on commit a4fb0e4

Please sign in to comment.