protected virtual void AnnotateFile( AnalysisServices services, RepoFile file, XmlSourceFileBuilder binder, XmlDocumentSyntax document) { }
protected override void AnnotateFile( AnalysisServices services, RepoFile file, XmlSourceFileBuilder binder, XmlDocumentSyntax document) { Analyze(services, file, binder, document); }
public static XmlSourceFileBuilder CreateAnnotatedSourceBuilder(this XElement sourceElement, SourceFileInfo info, string projectId) { var sourceFile = new SourceFile() { Content = sourceElement.ToString(), Info = info }; var binder = new XmlSourceFileBuilder(sourceFile, projectId); var elementList = sourceElement.DescendantsAndSelf().ToList(); var sortedElementList = binder.SortedElementList; Debug.Assert(elementList.Count == sortedElementList.Count); List <XmlAttributeSyntax> attributeSyntaxBuffer = new List <XmlAttributeSyntax>(); List <XAttribute> attributeBuffer = new List <XAttribute>(); for (int i = 0; i < elementList.Count; i++) { var element = elementList[i]; var syntaxElement = sortedElementList[i].Value; foreach (var annotation in element.Annotations <XmlSemanticAnnotation>()) { int start = 0; int length = 0; if (annotation.AppliesToName) { var nameNode = syntaxElement.NameNode(); start = nameNode.Start; length = nameNode.FullWidth - nameNode.GetTrailingTriviaWidth(); } else { var valueNode = syntaxElement.ValueNode(); start = valueNode.Start; length = valueNode.FullWidth; } if (annotation.References != null) { binder.AnnotateReferences(start, length, annotation.References); } else { binder.AnnotateDefinition(start, length, annotation.Definition); } } attributeSyntaxBuffer.Clear(); attributeBuffer.Clear(); attributeSyntaxBuffer.AddRange(syntaxElement.AsSyntaxElement.Attributes); attributeBuffer.AddRange(element.Attributes()); Debug.Assert(attributeSyntaxBuffer.Count == attributeBuffer.Count); for (int j = 0; j < attributeSyntaxBuffer.Count; j++) { var attribute = attributeBuffer[j]; var attributeSyntax = attributeSyntaxBuffer[j]; foreach (var annotation in attribute.Annotations <XmlSemanticAnnotation>()) { int start = 0; int length = 0; if (annotation.AppliesToName) { var nameNode = attributeSyntax.NameNode; start = nameNode.Start; length = nameNode.FullWidth - nameNode.GetTrailingTriviaWidth(); } else { var valueNode = attributeSyntax?.ValueNode.As <XmlStringSyntax>()?.TextTokens.Node; if (valueNode != null) { start = valueNode.Start; length = valueNode.FullWidth; } } if (length != 0) { if (annotation.References != null) { binder.AnnotateReferences(start, length, annotation.References); } else { binder.AnnotateDefinition(start, length, annotation.Definition); } } } } } return(binder); }
public void Analyze( AnalysisServices services, RepoFile file, XmlSourceFileBuilder binder, XmlDocumentSyntax document) { IXmlElement root = document.Root; // corrupt or invalid or empty XML if (root == null) { return; } if (root.Name == null && root.Elements.Count() == 1) { root = root.Elements.First(); } if (root.Name != "Project") { return; } ExpressionProcessor targetListProcessor = ProcessSemicolonSeparatedTargetList; AnalyzeEvaluation(services, file, binder, document); AnalyzePropertiesAndItems(binder, root); AnalyzeChoose(binder, root); foreach (var element in root.Elements("UsingTask")) { binder.AddReferences(element.Attribute("Condition").GetAttributeValueExpressionSpans()); var taskName = element["TaskName"]; if (taskName != null) { string shortName = taskName; string containerName = null; int lastDot = taskName.LastIndexOf("."); if (lastDot > -1) { containerName = taskName.Substring(0, lastDot); shortName = taskName.Substring(lastDot + 1); } binder.AddAttributeValueDefinition(element.Attribute("TaskName"), new DefinitionSymbol() { DisplayName = taskName, ShortName = shortName, ContainerQualifiedName = containerName, Id = GetTaskSymbolId(shortName), Kind = nameof(SymbolKinds.MSBuildTask), ProjectId = MSBuildExtensions.MSBuildProjectId, ReferenceKind = nameof(ReferenceKind.Definition), }); } foreach (var outputElement in element.Elements("Output")) { foreach (var attribute in outputElement.AsSyntaxElement.Attributes) { if (attribute.Name == "ItemName") { binder.AddAttributeValueReferences(attribute, CreateItemReference(attribute.Value)); } else if (attribute.Name == "PropertyName") { binder.AddAttributeValueReferences(attribute, CreatePropertyReference(attribute.Value)); } } } } foreach (var import in root.Elements("Import")) { AnalyzeImport(binder, import); } foreach (var importGroup in root.Elements("ImportGroup")) { binder.AddReferences(importGroup.Attribute("Condition").GetAttributeValueExpressionSpans()); foreach (var import in importGroup.Elements("Import")) { AnalyzeImport(binder, import); } } foreach (var target in root.Elements("Target")) { var targetName = target["Name"]; binder.AddAttributeValueDefinition(target.Attribute("Name"), CreateTargetDefinition(targetName)); binder.AddReferences(target.Attribute("Condition").GetAttributeValueExpressionSpans()); binder.AddReferences(target.Attribute("DependsOnTargets").GetAttributeValueExpressionSpans(targetListProcessor)); binder.AddReferences(target.Attribute("Inputs").GetAttributeValueExpressionSpans()); binder.AddReferences(target.Attribute("Outputs").GetAttributeValueExpressionSpans()); binder.AddReferences(target.Attribute("BeforeTargets").GetAttributeValueExpressionSpans(targetListProcessor)); binder.AddReferences(target.Attribute("AfterTargets").GetAttributeValueExpressionSpans(targetListProcessor)); foreach (var taskElement in target.Elements.Where(el => el.Name != "PropertyGroup" && el.Name != "ItemGroup")) { binder.AddElementNameReferences(taskElement, new ReferenceSymbol() { Id = GetTaskSymbolId(taskElement.Name), Kind = nameof(SymbolKinds.MSBuildTask), ProjectId = MSBuildExtensions.MSBuildProjectId, ReferenceKind = nameof(ReferenceKind.Reference), }); // NOTE: Also parses condition attribute foreach (var taskParameterAttribute in taskElement.AsSyntaxElement.Attributes) { binder.AddReferences(taskParameterAttribute.GetAttributeValueExpressionSpans()); } foreach (var output in taskElement.Elements("Output")) { binder.AddReferences(output.Attribute("Condition").GetAttributeValueExpressionSpans()); var propertyNameAttribute = output.Attribute("PropertyName"); if (propertyNameAttribute != null) { binder.AddAttributeValueReferences(propertyNameAttribute, CreatePropertyReference(propertyNameAttribute.Value)); } var itemNameAttribute = output.Attribute("ItemName"); if (itemNameAttribute != null) { binder.AddAttributeValueReferences(itemNameAttribute, CreateItemReference(itemNameAttribute.Value)); } } } AnalyzePropertiesAndItems(binder, target); } }
private void AnalyzeEvaluation( AnalysisServices services, RepoFile file, XmlSourceFileBuilder binder, XmlDocumentSyntax document) { var repo = file.PrimaryProject.Repo; using (var scope = GetProjectCollectionScope()) { try { Project project = new Project(file.FilePath, null, null, scope.Collection, ProjectLoadSettings.IgnoreMissingImports | ProjectLoadSettings.RecordDuplicateButNotCircularImports); foreach (var item in project.ItemsIgnoringCondition) { if (item.IsImported || item.Xml?.IncludeLocation == null) { continue; } RepoFile otherRepoFile = null; try { var fullPath = item.GetMetadataValue("FullPath"); otherRepoFile = repo.TryGetFile(fullPath); } catch { } if (otherRepoFile == null) { continue; } var location = item.Xml.IncludeLocation; var itemIncludeAttribute = binder .TryGetElement(location.Line - 1, location.Column - 1)? .Attribute("Include"); binder.AddAttributeNameReferences(itemIncludeAttribute, BoundSourceFileBuilder.CreateFileReferenceSymbol( otherRepoFile.LogicalPath, otherRepoFile.PrimaryProject.ProjectId)); } foreach (var import in project.ImportsIncludingDuplicates) { if (import.IsImported || import.ImportingElement == null) { continue; } var fullPath = import.ImportedProject.FullPath; RepoFile otherRepoFile = repo.TryGetFile(fullPath); if (otherRepoFile == null && fullPath != null) { if (!AddImports) { continue; } lock (MSBuildSharedProject) { otherRepoFile = MSBuildSharedProject.AddFile(fullPath); } otherRepoFile.IsSingleton = true; otherRepoFile.Analyze(); } var location = import.ImportingElement.ProjectLocation; var importProjectAttribute = binder .TryGetElement(location.Line - 1, location.Column - 1)? .Attribute("Project"); binder.AddAttributeNameReferences(importProjectAttribute, BoundSourceFileBuilder.CreateFileReferenceSymbol( otherRepoFile.LogicalPath, otherRepoFile.PrimaryProject.ProjectId)); } } catch (Exception ex) { services.Logger.LogExceptionError($"Analyzing MSBuild file evaluation: {file.FilePath}", ex); } } }
private void AnalyzeEvaluation( AnalysisServices services, RepoFile file, XmlSourceFileBuilder binder, XmlDocumentSyntax document) { var repo = file.PrimaryProject.Repo; using (var scope = GetProjectCollectionScope()) { try { Project project = new Project(file.FilePath, null, "Current", scope.Collection, ProjectLoadSettings.IgnoreMissingImports | ProjectLoadSettings.RecordDuplicateButNotCircularImports); foreach (var item in project.ItemsIgnoringCondition) { if (item.IsImported || item.Xml?.IncludeLocation == null) { continue; } RepoFile otherRepoFile = null; try { var fullPath = item.GetMetadataValue("FullPath"); otherRepoFile = repo.TryGetFile(fullPath); } catch { } if (otherRepoFile == null) { continue; } var location = item.Xml.IncludeLocation; var itemIncludeAttribute = binder .TryGetElement(location.Line - 1, location.Column - 1)? .Attribute("Include"); binder.AddAttributeNameReferences(itemIncludeAttribute, BoundSourceFileBuilder.CreateFileReferenceSymbol( otherRepoFile.LogicalPath, otherRepoFile.PrimaryProject.ProjectId)); } foreach (var import in project.ImportsIncludingDuplicates) { if (import.IsImported || import.ImportingElement == null) { continue; } var fullPath = import.ImportedProject.FullPath; RepoFile otherRepoFile = repo.TryGetFile(fullPath); if (otherRepoFile == null && fullPath != null) { if (!AddImports) { continue; } lock (MSBuildSharedProject) { otherRepoFile = MSBuildSharedProject.AddFile(fullPath); // The file is marked with explicit in this lock so we can // use that to know whether another thread has added the file already // and we can skip redundant analysis here if (otherRepoFile.HasExplicitAnalyzer) { continue; } otherRepoFile.Analyzer = this; otherRepoFile.HasExplicitAnalyzer = true; Placeholder.NotImplemented("Normalize imports to remove any references to repo specific files. Check if project is MSBuildSharedProject in order to determine if normalization is needed"); } otherRepoFile.Analyze(); } var location = import.ImportingElement.ProjectLocation; var importProjectAttribute = binder .TryGetElement(location.Line - 1, location.Column - 1)? .Attribute("Project"); binder.AddAttributeNameReferences(importProjectAttribute, BoundSourceFileBuilder.CreateFileReferenceSymbol( otherRepoFile.LogicalPath, otherRepoFile.PrimaryProject.ProjectId)); } } catch (Exception ex) { services.Logger.LogExceptionError($"Analyzing MSBuild file evaluation: {file.FilePath}", ex); } } }