コード例 #1
0
 protected virtual void AnnotateFile(
     AnalysisServices services,
     RepoFile file,
     XmlSourceFileBuilder binder,
     XmlDocumentSyntax document)
 {
 }
コード例 #2
0
 protected override void AnnotateFile(
     AnalysisServices services,
     RepoFile file,
     XmlSourceFileBuilder binder,
     XmlDocumentSyntax document)
 {
     Analyze(services, file, binder, document);
 }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
            }
        }
コード例 #5
0
        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);
                }
            }
        }
コード例 #6
0
        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);
                }
            }
        }