Exemplo n.º 1
0
        public void IncrementalParsingIsSameAsFullParsing_MiddleEdits()
        {
            var lines  = Xml.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            var middle = string.Join(Environment.NewLine, lines.Skip(2).Take(lines.Length - 3));
            var delta  = lines[0].Length + lines[1].Length + 2 * Environment.NewLine.Length;

            XmlDocumentSyntax previousDocument = null;

            for (int i = 1; i <= middle.Length; i++)
            {
                var currentText =
                    lines[0] + Environment.NewLine
                    + lines[1] + Environment.NewLine
                    + middle.Substring(0, i) + Environment.NewLine
                    + lines.Last();
                var full        = Parser.ParseText(currentText);
                var incremental = Parser.ParseIncremental(
                    currentText,
                    new[] { new TextChangeRange(new TextSpan(delta + i - 1, 0), 1) },
                    previousDocument
                    );
                AssertSameNodes(full, incremental);
                previousDocument = incremental;
            }
        }
Exemplo n.º 2
0
 protected virtual void AnnotateFile(
     AnalysisServices services,
     RepoFile file,
     XmlSourceFileBuilder binder,
     XmlDocumentSyntax document)
 {
 }
        public void CanCompleteAttribute(string testFileName, int line, int column, string expectedElementName, PaddingType expectedPadding)
        {
            Position testPosition = new Position(line, column);

            string            testXml   = LoadTestFile("TestFiles", testFileName + ".xml");
            TextPositions     positions = new TextPositions(testXml);
            XmlDocumentSyntax document  = Parser.ParseText(testXml);

            XmlLocator  locator  = new XmlLocator(document, positions);
            XmlLocation location = locator.Inspect(testPosition);

            Assert.NotNull(location);

            XSPath elementPath = XSPath.Parse(expectedElementName);

            XSElement   element;
            XSAttribute replaceAttribute;
            PaddingType needsPadding;

            Assert.True(
                location.CanCompleteAttribute(out element, out replaceAttribute, out needsPadding, onElementWithPath: elementPath),
                "CanCompleteAttribute"
                );
            Assert.NotNull(element);
            Assert.Null(replaceAttribute);
            Assert.Equal(expectedPadding, needsPadding);
        }
        public void InEmptyElementName(string testFileName, int line, int column, string expectedElementName)
        {
            Position testPosition = new Position(line, column);

            string            testXml   = LoadTestFile("TestFiles", testFileName + ".xml");
            TextPositions     positions = new TextPositions(testXml);
            XmlDocumentSyntax document  = Parser.ParseText(testXml);

            XmlLocator  locator = new XmlLocator(document, positions);
            XmlLocation result  = locator.Inspect(testPosition);

            Assert.NotNull(result);
            Assert.Equal(XSNodeKind.Element, result.Node.Kind);
            Assert.True(result.IsElement(), "IsElement");

            XSElement element = (XSElement)result.Node;

            Assert.Equal(expectedElementName, element.Name);

            Assert.True(result.IsEmptyElement(), "IsEmptyElement");
            Assert.True(result.IsName(), "IsName");

            Assert.False(result.IsElementContent(), "IsElementContent");

            // TODO: Verify Parent, PreviousSibling, and NextSibling.
        }
Exemplo n.º 5
0
        void NodeRange(string testFileName, int index, int startLine, int startColumn, int endLine, int endColumn)
        {
            string            testXml      = LoadTestFile("TestFiles", testFileName + ".xml");
            TextPositions     xmlPositions = new TextPositions(testXml);
            XmlDocumentSyntax xmlDocument  = Parser.ParseText(testXml);

            List <XSNode> nodes = xmlDocument.GetSemanticModel(xmlPositions);

            Assert.NotNull(nodes);
            Assert.InRange(index, 0, nodes.Count - 1);

            XSNode node = nodes[index];

            Assert.NotNull(node);

            TestOutput.WriteLine("Node {0} at {1} is {2}.",
                                 index,
                                 node.Range,
                                 node.Kind
                                 );

            Range expectedRange = new Range(
                start: new Position(startLine, startColumn),
                end: new Position(endLine, endColumn)
                );

            Assert.Equal(expectedRange, node.Range);
        }
        public void InsideElement1(string testFileName, int line, int column)
        {
            // TODO: Change this test to use XmlLocator.

            Position testPosition = new Position(line, column);

            string            testXml     = LoadTestFile("TestFiles", testFileName + ".xml");
            TextPositions     positions   = new TextPositions(testXml);
            XmlDocumentSyntax xmlDocument = Parser.ParseText(testXml);

            int        absolutePosition = positions.GetAbsolutePosition(testPosition) - 1; // To find out if we can insert an element, make sure we find the node at the position ONE BEFORE the insertion point!
            SyntaxNode foundNode        = xmlDocument.FindNode(absolutePosition,
                                                               descendIntoChildren: node => true
                                                               );

            Assert.NotNull(foundNode);
            Assert.IsAssignableFrom <SyntaxList>(foundNode);
            SyntaxList list = (SyntaxList)foundNode;

            Range listSpan = list.Span.ToNative(positions);

            Assert.True(
                listSpan.Contains(testPosition),
                "List's span must contain the test position."
                );
        }
Exemplo n.º 7
0
        public void InvalidElementRange(string testFileName, int nodeIndex, string elementName, int startLine, int startColumn, int endLine, int endColumn)
        {
            string            testXml      = LoadTestFile("TestFiles", testFileName + ".xml");
            TextPositions     xmlPositions = new TextPositions(testXml);
            XmlDocumentSyntax xmlDocument  = Parser.ParseText(testXml);

            List <XSNode> nodes = xmlDocument.GetSemanticModel(xmlPositions);

            Assert.NotNull(nodes);

            XSNode targetNode = nodes[nodeIndex];

            Assert.NotNull(targetNode);

            Assert.IsAssignableFrom <XSElement>(targetNode);
            XSElement targetElement = (XSElement)targetNode;

            Assert.Equal(elementName, targetElement.Name);
            Assert.False(targetElement.IsValid, "IsValid");

            Range expectedRange = new Range(
                start: new Position(startLine, startColumn),
                end: new Position(endLine, endColumn)
                );

            Assert.Equal(expectedRange, targetElement.Range);
        }
Exemplo n.º 8
0
        public static XmlDocumentSyntax Analyze(BoundSourceFileBuilder binder)
        {
            var text = binder.SourceFile.Content;
            XmlDocumentSyntax parsedXml = Parser.ParseText(text);

            Classify(binder, parsedXml);
            return(parsedXml);
        }
Exemplo n.º 9
0
 protected override void AnnotateFile(
     AnalysisServices services,
     RepoFile file,
     XmlSourceFileBuilder binder,
     XmlDocumentSyntax document)
 {
     Analyze(services, file, binder, document);
 }
Exemplo n.º 10
0
        void NodeCount(string testFileName, int expectedNodeCount)
        {
            string            testXml      = LoadTestFile("TestFiles", testFileName + ".xml");
            TextPositions     xmlPositions = new TextPositions(testXml);
            XmlDocumentSyntax xmlDocument  = Parser.ParseText(testXml);

            List <XSNode> nodes = xmlDocument.GetSemanticModel(xmlPositions);

            Assert.NotNull(nodes);
            Assert.Equal(expectedNodeCount, nodes.Count);
        }
Exemplo n.º 11
0
        private static void Classify(BoundSourceFileBuilder binder, XmlDocumentSyntax parsedXml)
        {
            ClassifierVisitor.Visit(parsedXml, 0, parsedXml.FullWidth, (start, length, node, classification) =>
            {
                var leadingTriviaWidth  = node.GetLeadingTriviaWidth();
                var trailingTriviaWidth = node.GetTrailingTriviaWidth();
                start  += leadingTriviaWidth;
                length -= (leadingTriviaWidth + trailingTriviaWidth);

                binder.AnnotateClassification(start, length, ClassificationTypeNamesLookup[(int)classification]);
            });
        }
Exemplo n.º 12
0
        public void IncrementalParsingIsSameAsFullParsing()
        {
            XmlDocumentSyntax previousDocument = null;

            for (int i = 1; i <= Xml.Length; i++)
            {
                var currentText = Xml.Substring(0, i);
                var full        = Parser.ParseText(currentText);
                var incremental = Parser.ParseIncremental(
                    currentText,
                    new[] { new TextChangeRange(new TextSpan(currentText.Length - 1, 0), 1) },
                    previousDocument
                    );
                AssertSameNodes(full, incremental);
                previousDocument = incremental;
            }
        }
Exemplo n.º 13
0
        public void IncrementalParsingIsSameAsFullParsing_MultipleConcurrentEdits()
        {
            int[] FindAllIndexes(string str, string needle)
            {
                var result        = new List <int>();
                var foundIndex    = 0;
                var startSearchAt = 0;

                while ((foundIndex = str.IndexOf(needle, startSearchAt)) != -1)
                {
                    result.Add(foundIndex);
                    startSearchAt = foundIndex + needle.Length;
                }
                return(result.ToArray());
            }

            const string      AttributeName    = "sameLengthAttributeName";
            var               attrIndexes      = FindAllIndexes(Xml2, AttributeName);
            XmlDocumentSyntax previousDocument = null;

            for (int i = 1; i <= AttributeName.Length; i++)
            {
                var currentText = Xml2;
                var changes     = new List <TextChangeRange>();
                // Reconstruct the intermediary attributes
                for (int j = attrIndexes.Length - 1; j >= 0; j--)
                {
                    currentText = currentText.Remove(attrIndexes[j], AttributeName.Length);
                    currentText = currentText.Insert(attrIndexes[j], AttributeName.Substring(0, i));
                    changes.Add(new TextChangeRange(new TextSpan(attrIndexes[j] + i - 1 - j * (AttributeName.Length - i), 0), 1));
                }
                changes.Reverse();

                // All changes should map to the same letter
                Assert.All(changes, c => Assert.Equal(currentText[c.Span.Start], currentText[changes[0].Span.Start]));

                var full        = Parser.ParseText(currentText);
                var incremental = Parser.ParseIncremental(
                    currentText,
                    changes.ToArray(),
                    previousDocument
                    );
                AssertSameNodes(full, incremental);
                previousDocument = incremental;
            }
        }
Exemplo n.º 14
0
        void NodeKind(string testFileName, int index, XSNodeKind nodeKind)
        {
            string            testXml      = LoadTestFile("TestFiles", testFileName + ".xml");
            TextPositions     xmlPositions = new TextPositions(testXml);
            XmlDocumentSyntax xmlDocument  = Parser.ParseText(testXml);

            List <XSNode> nodes = xmlDocument.GetSemanticModel(xmlPositions);

            Assert.NotNull(nodes);
            Assert.InRange(index, 0, nodes.Count - 1);

            XSNode node = nodes[index];

            Assert.NotNull(node);

            Assert.Equal(nodeKind, node.Kind);
        }
        public void CanCompleteElement(string testFileName, int line, int column)
        {
            Position testPosition = new Position(line, column);

            string            testXml   = LoadTestFile("TestFiles", testFileName + ".xml");
            TextPositions     positions = new TextPositions(testXml);
            XmlDocumentSyntax document  = Parser.ParseText(testXml);

            XmlLocator  locator  = new XmlLocator(document, positions);
            XmlLocation location = locator.Inspect(testPosition);

            Assert.NotNull(location);

            XSElement replacingElement;

            Assert.True(location.CanCompleteElement(out replacingElement), "CanCompleteElement");
            Assert.NotNull(replacingElement);
        }
Exemplo n.º 16
0
        private IEnumerable <Diagnostic> ValidateTemplatedValues(XmlDocumentSyntax syntaxTree, TextPositions textPositions)
        {
            foreach (var node in syntaxTree.DescendantNodesAndSelf().OfType <XmlTextSyntax>())
            {
                if (!TemplatedValues.Any(x => node.Value.Contains(x, StringComparison.OrdinalIgnoreCase)))
                {
                    continue;
                }

                var range = textPositions.GetRange(node.Start, node.End);

                yield return(new Diagnostic {
                    Message = "Templated value which should be removed",
                    Severity = DiagnosticSeverity.Error,
                    Range = range
                });
            }
        }
        internal static string ParseChallenge(string xml)
        {
            XmlDocumentSyntax root = Parser.ParseText(xml);

            string base64Info = string.Empty;

            foreach (IXmlElement node in root.Elements)
            {
                if (node.Name == "challenge")
                {
                    base64Info = node.Value;
                }
            }

            byte[] uniqDataB = new byte[1024];
            uniqDataB = Convert.FromBase64String(base64Info);

            return(Encoding.Default.GetString(uniqDataB));
        }
Exemplo n.º 18
0
        /// <summary>
        ///     Parse the syntax model to derive a semantic model.
        /// </summary>
        /// <param name="document">
        ///     The <see cref="XmlDocumentSyntax"/> to parse.
        /// </param>
        /// <param name="xmlPositions">
        ///     The lookup for document positions.
        /// </param>
        /// <returns>
        ///     A list of <see cref="XSNode"/>s, sorted by <see cref="XSNode.Range"/>.
        /// </returns>
        public static List <XSNode> GetSemanticModel(this XmlDocumentSyntax document, TextPositions xmlPositions)
        {
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            if (xmlPositions == null)
            {
                throw new ArgumentNullException(nameof(xmlPositions));
            }

            XSParserVisitor parserVisitor = new XSParserVisitor(xmlPositions);

            parserVisitor.Visit(document);
            parserVisitor.FinaliseModel();

            return(parserVisitor.DiscoveredNodes);
        }
Exemplo n.º 19
0
            /// <summary>
            ///     Visit an <see cref="XmlDocumentSyntax"/>.
            /// </summary>
            /// <param name="document">
            ///     The <see cref="XmlDocumentSyntax"/>.
            /// </param>
            /// <returns>
            ///     The <see cref="XmlDocumentSyntax"/> (unchanged).
            /// </returns>
            public override SyntaxNode VisitXmlDocument(XmlDocumentSyntax document)
            {
                XmlElementSyntaxBase root = document.Root as XmlElementSyntaxBase;

                if (root == null)
                {
                    return(document);
                }

                if (root is XmlElementSyntax rootElement && rootElement.StartTag == null)
                {
                    root = rootElement.Elements.FirstOrDefault() as XmlElementSyntaxBase;
                }

                if (root != null)
                {
                    Visit(root);
                }

                return(document);
            }
        public void InAttributeValue(string testFileName, int line, int column, string expectedAttributeName)
        {
            Position testPosition = new Position(line, column);

            string            testXml   = LoadTestFile("TestFiles", testFileName + ".xml");
            TextPositions     positions = new TextPositions(testXml);
            XmlDocumentSyntax document  = Parser.ParseText(testXml);

            XmlLocator  locator = new XmlLocator(document, positions);
            XmlLocation result  = locator.Inspect(testPosition);

            Assert.NotNull(result);

            XSAttribute attribute;

            Assert.True(result.IsAttribute(out attribute), "IsAttribute");
            Assert.True(result.IsAttributeValue(), "IsAttributeValue");

            Assert.Equal(expectedAttributeName, attribute.Name);

            // TODO: Verify Parent, PreviousSibling, and NextSibling.
        }
Exemplo n.º 21
0
        void ElementAttributesRange(string testFileName, string elementName, int startLine, int startColumn, int endLine, int endColumn)
        {
            string            testXml      = LoadTestFile("TestFiles", testFileName + ".xml");
            TextPositions     xmlPositions = new TextPositions(testXml);
            XmlDocumentSyntax xmlDocument  = Parser.ParseText(testXml);

            List <XSNode> nodes = xmlDocument.GetSemanticModel(xmlPositions);

            Assert.NotNull(nodes);

            XSNode targetNode = nodes.Find(node => node.Name == elementName);

            Assert.NotNull(targetNode);

            Assert.IsAssignableFrom <XSElement>(targetNode);
            XSElement targetElement = (XSElement)targetNode;

            Range expectedRange = new Range(
                start: new Position(startLine, startColumn),
                end: new Position(endLine, endColumn)
                );

            Assert.Equal(expectedRange, targetElement.AttributesRange);
        }
        public void IsExpression_Success(string testFileName, int line, int column, ExpressionKind expectedExpressionKind)
        {
            Position testPosition = new Position(line, column);

            string            testXml   = LoadTestFile("TestFiles", testFileName + ".xml");
            TextPositions     positions = new TextPositions(testXml);
            XmlDocumentSyntax document  = Parser.ParseText(testXml);

            XmlLocator  locator  = new XmlLocator(document, positions);
            XmlLocation location = locator.Inspect(testPosition);

            Assert.NotNull(location);

            ExpressionNode actualExpression;
            Range          actualExpressionRange;

            Assert.True(
                location.IsExpression(out actualExpression, out actualExpressionRange),
                "IsExpression"
                );
            Assert.NotNull(actualExpression);

            Assert.Equal(expectedExpressionKind, actualExpression.Kind);
        }
        public void CanCompleteElementInParentWithRelativePath(string testFileName, int line, int column, string expectedParent)
        {
            Position testPosition = new Position(line, column);

            string            testXml   = LoadTestFile("TestFiles", testFileName + ".xml");
            TextPositions     positions = new TextPositions(testXml);
            XmlDocumentSyntax document  = Parser.ParseText(testXml);

            XmlLocator  locator  = new XmlLocator(document, positions);
            XmlLocation location = locator.Inspect(testPosition);

            Assert.NotNull(location);

            XSPath expectedParentPath = XSPath.Parse(expectedParent);

            XSElement replaceElement;

            Assert.True(
                location.CanCompleteElement(out replaceElement, parentPath: expectedParentPath),
                "CanCompleteElement"
                );
            Assert.NotNull(replaceElement);
            Assert.Equal(expectedParent, replaceElement.ParentElement?.Name);
        }
        /// <summary>
        ///     Create a new <see cref="XmlLocator"/>.
        /// </summary>
        /// <param name="document">
        ///     The underlying XML document.
        /// </param>
        /// <param name="documentPositions">
        ///     The position-lookup for the underlying XML document text.
        /// </param>
        public XmlLocator(XmlDocumentSyntax document, TextPositions documentPositions)
        {
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            if (documentPositions == null)
            {
                throw new ArgumentNullException(nameof(documentPositions));
            }

            _documentPositions = documentPositions;

            List <XSNode> allNodes = document.GetSemanticModel(_documentPositions);

            foreach (XSNode node in allNodes)
            {
                _nodeRanges.Add(node.Range);
                _nodesByStartPosition.Add(node.Range.Start, node);
            }

            _nodeRanges.Sort();
        }
Exemplo n.º 25
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);
                }
            }
        }
Exemplo n.º 26
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);
                }
            }
        }
Exemplo n.º 27
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);
            }
        }
Exemplo n.º 28
0
        /// <summary>
        /// Returns the URL of the file that contains the definition of the item at the current position
        /// </summary>
        /// <param name="filePath">Current file</param>
        /// <param name="sourceText">Text in the current file</param>
        /// <param name="position">Position of item that is to be resolved</param>
        /// <returns></returns>
        public List <Definition> ResolveDefinition(string filePath, string sourceText, int position)
        {
            Verify.NotDisposed(this);
            List <Definition> definitions = new List <Definition>();

            if (_project != null)
            {
                XmlDocumentSyntax root       = Parser.ParseText(sourceText);
                SyntaxNode        syntaxNode = SyntaxLocator.FindNode(root, position);

                // Resolves Definition for properties e.g. $(foo)
                if (syntaxNode.Kind == SyntaxKind.XmlTextLiteralToken && Utilities.IsProperty(sourceText.Substring(syntaxNode.Span.Start, syntaxNode.FullWidth), position - syntaxNode.Span.Start, out string propertyName))
                {
                    foreach (ProjectProperty property in _project.Properties)
                    {
                        if (property.Name == propertyName)
                        {
                            ProjectProperty currentProperty = property;

                            while (currentProperty.Predecessor != null)
                            {
                                if (currentProperty.Xml?.Location != null)
                                {
                                    ElementLocation location = currentProperty.Xml.Location;
                                    definitions.Add(new Definition(location.File, Path.GetFileNameWithoutExtension(_project.Xml.Location.File), currentProperty.Name + " Definitions", currentProperty.EvaluatedValue, location.Line, location.Column));
                                }

                                currentProperty = currentProperty.Predecessor;
                            }

                            if (currentProperty.Xml?.Location != null)
                            {
                                ElementLocation lastLocation = currentProperty.Xml.Location;
                                definitions.Add(new Definition(lastLocation.File, Path.GetFileNameWithoutExtension(_project.Xml.Location.File), currentProperty.Name + " Definitions", currentProperty.EvaluatedValue, lastLocation.Line, lastLocation.Column));
                            }

                            break;
                        }
                    }
                }

                // Resolves Definition for regular imports
                else if (syntaxNode.ParentElement != null && syntaxNode.ParentElement.Name.Equals(SyntaxNames.Import))
                {
                    while (syntaxNode.Parent.ParentElement == syntaxNode.ParentElement)
                    {
                        syntaxNode = syntaxNode.Parent;
                    }

                    int nodeStart = syntaxNode.Parent.Span.Start;
                    int col       = nodeStart - Utilities.GetStartOfLine(sourceText, nodeStart) + 1;
                    int line      = Utilities.GetLine(sourceText, nodeStart) + 1;

                    foreach (ResolvedImport import in _project.Imports)
                    {
                        ElementLocation location = import.ImportingElement.Location;

                        if (location.File == filePath && col == location.Column && line == location.Line)
                        {
                            definitions.Add(new Definition(import.ImportedProject.FullPath, Path.GetFileNameWithoutExtension(_project.Xml.Location.File), "Imported Files", Path.GetFileName(import.ImportedProject.FullPath)));
                        }
                    }
                }

                // Resolves Definition for the project's sdk
                else if (syntaxNode.ParentElement != null && syntaxNode.ParentElement.Name.Equals(SyntaxNames.Project))
                {
                    bool foundSdk = false;

                    for (int i = 0; i < 3; i++)
                    {
                        if (sourceText.Substring(syntaxNode.Start, 3).Equals(SyntaxNames.Sdk))
                        {
                            foundSdk = true;
                            break;
                        }

                        syntaxNode = syntaxNode.Parent;
                    }

                    if (foundSdk)
                    {
                        foreach (ResolvedImport import in _project.Imports)
                        {
                            ElementLocation location = import.ImportingElement.Location;

                            if (location.File == filePath && 0 == location.Column && 0 == location.Line)
                            {
                                definitions.Add(new Definition(import.ImportedProject.FullPath, Path.GetFileNameWithoutExtension(_project.Xml.Location.File), "Sdk Imports", Path.GetFileName(import.ImportedProject.FullPath)));
                            }
                        }
                    }
                }
            }

            return(definitions);
        }