private static void AddDebugSourceDocumentsForChecksumDirectives( PEModuleBuilder moduleBeingBuilt, SyntaxTree tree, DiagnosticBag diagnostics) { var checksumDirectives = tree.GetRoot().GetDirectives(d => d.Kind == SyntaxKind.PragmaChecksumDirectiveTrivia && !d.ContainsDiagnostics); foreach (var directive in checksumDirectives) { var checkSumDirective = (PragmaChecksumDirectiveTriviaSyntax)directive; var path = checkSumDirective.File.ValueText; var checkSumText = checkSumDirective.Bytes.ValueText; var normalizedPath = moduleBeingBuilt.NormalizeDebugDocumentPath(path, basePath: tree.FilePath); var existingDoc = moduleBeingBuilt.TryGetDebugDocumentForNormalizedPath(normalizedPath); // duplicate checksum pragmas are valid as long as values match // if we have seen this document already, check for matching values. if (existingDoc != null) { // pragma matches a file path on an actual tree. // Dev12 compiler just ignores the pragma in this case which means that // checksum of the actual tree always wins and no warning is given. // We will continue doing the same. if (existingDoc.IsComputedChecksum) { continue; } if (CheckSumMatches(checkSumText, existingDoc.SourceHash)) { var guid = Guid.Parse(checkSumDirective.Guid.ValueText); if (guid == existingDoc.SourceHashKind) { // all parts match, nothing to do continue; } } // did not match to an existing document // produce a warning and ignore the pragma diagnostics.Add(ErrorCode.WRN_ConflictingChecksum, new SourceLocation(checkSumDirective), path); } else { var newDocument = new Cci.DebugSourceDocument( normalizedPath, Cci.DebugSourceDocument.CorSymLanguageTypeCSharp, MakeCheckSumBytes(checkSumDirective.Bytes.ValueText), Guid.Parse(checkSumDirective.Guid.ValueText)); moduleBeingBuilt.AddDebugDocument(newDocument); } } }
// TODO: consider unifying with VB private bool StartSourceChecksumCalculation(PEModuleBuilder moduleBeingBuilt, DiagnosticBag diagnostics) { // Check that all syntax trees are debuggable: bool allTreesDebuggable = true; foreach (var tree in this.syntaxTrees) { if (!string.IsNullOrEmpty(tree.FilePath) && tree.GetText().Encoding == null) { diagnostics.Add(ErrorCode.ERR_EncodinglessSyntaxTree, tree.GetRoot().GetLocation()); allTreesDebuggable = false; } } if (!allTreesDebuggable) { return false; } // Add debug documents for all trees with distinct paths. foreach (var tree in this.syntaxTrees) { if (!string.IsNullOrEmpty(tree.FilePath)) { // compilation does not guarantee that all trees will have distinct paths. // Do not attempt adding a document for a particular path if we already added one. string normalizedPath = moduleBeingBuilt.NormalizeDebugDocumentPath(tree.FilePath, basePath: null); var existingDoc = moduleBeingBuilt.TryGetDebugDocumentForNormalizedPath(normalizedPath); if (existingDoc == null) { moduleBeingBuilt.AddDebugDocument(MakeDebugSourceDocumentForTree(normalizedPath, tree)); } } } // Add debug documents for all pragmas. // If there are clashes with already processed directives, report warnings. // If there are clashes with debug documents that came from actual trees, ignore the pragma. foreach (var tree in this.syntaxTrees) { AddDebugSourceDocumentsForChecksumDirectives(moduleBeingBuilt, tree, diagnostics); } return true; }