/// <summary> /// Gets the symbols for this section. /// </summary> /// <param name="messageHandler">The message handler.</param> /// <returns>Collection of symbols for this section.</returns> internal SymbolCollection GetSymbols(IMessageHandler messageHandler) { if (null == this.symbols) { this.symbols = new SymbolCollection(); foreach (Table table in this.tables) { foreach (Row row in table.Rows) { Symbol symbol = row.Symbol; if (null != symbol) { try { this.symbols.Add(symbol); } catch (ArgumentException) { Symbol existingSymbol = this.symbols[symbol.Name]; messageHandler.OnMessage(WixErrors.DuplicateSymbol(existingSymbol.Row.SourceLineNumbers, existingSymbol.Name)); if (null != symbol.Row.SourceLineNumbers) { messageHandler.OnMessage(WixErrors.DuplicateSymbol2(symbol.Row.SourceLineNumbers)); } } } } } } return(this.symbols); }
public void Execute() { // Do a quick check if there are any possibly conflicting symbols that don't come from tables that allow // overriding. Hopefully the symbols with possible conflicts list is usually very short list (empty should // be the most common). If we find any matches, we'll do a more costly check to see if the possible conflicting // symbols are in sections we actually referenced. From the resulting set, show an error for each duplicate // (aka: conflicting) symbol. This should catch any rows with colliding primary keys (since symbols are based // on the primary keys of rows). List <Symbol> illegalDuplicates = possibleConflicts.Where(s => "WixAction" != s.Row.Table.Name && "WixVariable" != s.Row.Table.Name).ToList(); if (0 < illegalDuplicates.Count) { HashSet <Section> referencedSections = new HashSet <Section>(resolvedSections); foreach (Symbol referencedDuplicateSymbol in illegalDuplicates.Where(s => referencedSections.Contains(s.Section))) { List <Symbol> actuallyReferencedDuplicateSymbols = referencedDuplicateSymbol.PossiblyConflictingSymbols.Where(s => referencedSections.Contains(s.Section)).ToList(); if (actuallyReferencedDuplicateSymbols.Any()) { Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol(referencedDuplicateSymbol.Row.SourceLineNumbers, referencedDuplicateSymbol.Name)); foreach (Symbol duplicate in actuallyReferencedDuplicateSymbols) { Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol2(duplicate.Row.SourceLineNumbers)); } } } } }
public void ProtectedDuplicatesInSameFileCauseLinkError() { XDocument doc = XDocument.Parse("<Wix xmlns='http://wixtoolset.org/schemas/v4/wxs'><Product Id='*' Language='1033' Manufacturer='WixTests' Name='ProtectedDuplicatesInSameFileCauseLinkError' Version='1.0.0' UpgradeCode='12345678-1234-1234-1234-1234567890AB'><DirectoryRef Id='ProtectedDirectory'/></Product>" + "<Fragment><DirectoryRef Id='TARGETDIR'><Directory Id='protected ProtectedDirectory' Name='conflict1'/></DirectoryRef></Fragment>" + "<Fragment><DirectoryRef Id='TARGETDIR'><Directory Id='protected ProtectedDirectory' Name='conflict2'/></DirectoryRef></Fragment>" + "<Fragment><Directory Id='TARGETDIR' Name='SourceDir' /></Fragment></Wix>"); XDocument src = new Preprocessor().Process(doc.CreateReader(), new Dictionary <string, string>()); Compiler compiler = new Compiler(); Linker linker = new Linker(); Intermediate intermediate = compiler.Compile(src); WixException e = Assert.Throws <WixException>(() => linker.Link(intermediate.Sections, OutputType.Product)); Assert.Equal(WixErrors.DuplicateSymbol(null, null).Id, e.Error.Id); }
/// <summary> /// Gets the symbols for this section. /// </summary> /// <param name="messageHandler">The message handler.</param> /// <returns>Collection of symbols for this section.</returns> internal SymbolCollection GetSymbols(IMessageHandler messageHandler) { if (null == this.symbols) { this.symbols = new SymbolCollection(); // add a symbol for this section if (null != this.id) { this.symbols.Add(new Symbol(this, this.type.ToString(), this.id)); } else { Debug.Assert(SectionType.Fragment == this.type, "Only Fragment sections can have a null Id."); } foreach (Table table in this.tables) { foreach (Row row in table.Rows) { Symbol symbol = row.Symbol; if (null != symbol) { try { this.symbols.Add(symbol); } catch (ArgumentException) { Symbol existingSymbol = this.symbols[symbol.Name]; messageHandler.OnMessage(WixErrors.DuplicateSymbol(existingSymbol.Row.SourceLineNumbers, existingSymbol.Name)); messageHandler.OnMessage(WixErrors.DuplicateSymbol2(symbol.Row.SourceLineNumbers)); } } } } } return(this.symbols); }
/// <summary> /// Recursive helper function to resolve all references of passed in section. /// </summary> /// <param name="section">Section with references to resolve.</param> /// <remarks>Note: recursive function.</remarks> private void RecursivelyResolveReferences(Section section) { // If we already resolved this section, move on to the next. if (!this.resolvedSections.Add(section)) { return; } // Process all of the references contained in this section using the collection of // symbols provided. Then recursively call this method to process the // located symbol's section. All in all this is a very simple depth-first // search of the references per-section. Table wixSimpleReferenceTable; if (section.Tables.TryGetTable("WixSimpleReference", out wixSimpleReferenceTable)) { foreach (WixSimpleReferenceRow wixSimpleReferenceRow in wixSimpleReferenceTable.Rows) { Debug.Assert(wixSimpleReferenceRow.Section == section); // If we're building a Merge Module, ignore all references to the Media table // because Merge Modules don't have Media tables. if (this.BuildingMergeModule && "Media" == wixSimpleReferenceRow.TableName) { continue; } Symbol symbol; if (!this.symbols.TryGetValue(wixSimpleReferenceRow.SymbolicName, out symbol)) { Messaging.Instance.OnMessage(WixErrors.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName)); } else // see if the symbol (and any of its duplicates) are appropriately accessible. { IList <Symbol> accessible = DetermineAccessibleSymbols(section, symbol); if (!accessible.Any()) { Messaging.Instance.OnMessage(WixErrors.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName, symbol.Access)); } else if (1 == accessible.Count) { Symbol accessibleSymbol = accessible[0]; this.referencedSymbols.Add(accessibleSymbol); if (null != accessibleSymbol.Section) { RecursivelyResolveReferences(accessibleSymbol.Section); } } else // display errors for the duplicate symbols. { Symbol accessibleSymbol = accessible[0]; string referencingSourceLineNumber = wixSimpleReferenceRow.SourceLineNumbers.ToString(); if (String.IsNullOrEmpty(referencingSourceLineNumber)) { Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol(accessibleSymbol.Row.SourceLineNumbers, accessibleSymbol.Name)); } else { Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol(accessibleSymbol.Row.SourceLineNumbers, accessibleSymbol.Name, referencingSourceLineNumber)); } foreach (Symbol accessibleDuplicate in accessible.Skip(1)) { Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol2(accessibleDuplicate.Row.SourceLineNumbers)); } } } } } }
/// <summary> /// Gets the symbol for a reference. /// </summary> /// <param name="wixSimpleReferenceRow">Simple references to resolve.</param> /// <param name="messageHandler">Message handler to report errors through.</param> /// <returns>Symbol if it was found or null if the symbol was not specified.</returns> internal Symbol GetSymbolForSimpleReference(WixSimpleReferenceRow wixSimpleReferenceRow, IMessageHandler messageHandler) { Symbol symbol = null; try { symbol = this[wixSimpleReferenceRow.SymbolicName]; } catch (DuplicateSymbolsException e) { Hashtable uniqueSourceLineNumbers = new Hashtable(); Symbol[] duplicateSymbols = e.GetDuplicateSymbols(); Debug.Assert(1 < duplicateSymbols.Length); // index the row source line numbers to determine how many are unique foreach (Symbol duplicateSymbol in duplicateSymbols) { if (null != duplicateSymbol.Row && null != duplicateSymbol.Row.SourceLineNumbers) { uniqueSourceLineNumbers[duplicateSymbol.Row.SourceLineNumbers] = null; } } // if only 1 unique source line number was found, switch to the section source line numbers // (sections use the file name of the intermediate, library, or extension they came from) if (1 >= uniqueSourceLineNumbers.Count) { uniqueSourceLineNumbers.Clear(); foreach (Symbol duplicateSymbol in duplicateSymbols) { if (null != duplicateSymbol.Section.SourceLineNumbers) { uniqueSourceLineNumbers[duplicateSymbol.Section.SourceLineNumbers] = null; } } } // display errors for the unique source line numbers bool displayedFirstError = false; foreach (SourceLineNumberCollection sourceLineNumbers in uniqueSourceLineNumbers.Keys) { if (!displayedFirstError) { messageHandler.OnMessage(WixErrors.DuplicateSymbol(sourceLineNumbers, duplicateSymbols[0].Name)); displayedFirstError = true; } else { messageHandler.OnMessage(WixErrors.DuplicateSymbol2(sourceLineNumbers)); } } // display an error, even if no source line information was found if (!displayedFirstError) { messageHandler.OnMessage(WixErrors.DuplicateSymbol(null, duplicateSymbols[0].Name)); } } return(symbol); }