Example #1
0
        public static IEnumerable <BaseInfo> GetCompletionInfos(
            MSBuildResolveResult rr,
            TriggerState trigger, MSBuildValueKind kind,
            ExpressionNode triggerExpression, int triggerLength,
            MSBuildRootDocument doc)
        {
            switch (trigger)
            {
            case TriggerState.Value:
                return(MSBuildCompletionExtensions.GetValueCompletions(kind, doc, rr));

            case TriggerState.Item:
                return(doc.GetItems());

            case TriggerState.Metadata:
                return(doc.GetMetadata(null, true));

            case TriggerState.Property:
                return(doc.GetProperties(true));

            case TriggerState.MetadataOrItem:
                return(((IEnumerable <BaseInfo>)doc.GetItems()).Concat(doc.GetMetadata(null, true)));

            case TriggerState.DirectorySeparator:
                return(MSBuildCompletionExtensions.GetFilenameCompletions(kind, doc, triggerExpression, triggerLength));;

            case TriggerState.MethodName:
                return(FunctionCompletion.GetMethodNameCompletions(triggerExpression));
            }
            throw new InvalidOperationException();
        }
Example #2
0
        public static MSBuildNavigationResult GetNavigation(
            MSBuildRootDocument doc, DocumentLocation location, MSBuildResolveResult rr)
        {
            if (rr == null)
            {
                return(null);
            }

            //HACK: we should really use the ITextSource directly, but since the XML parser positions are
            //currently line/col, we need a TextDocument to convert to offsets
            var textDocument = doc.Text as IReadonlyTextDocument
                               ?? TextEditorFactory.CreateNewReadonlyDocument(
                doc.Text, doc.Filename, MSBuildTextEditorExtension.MSBuildMimeType
                );

            var annotations     = GetAnnotationsAtLocation <NavigationAnnotation> (doc, location);
            var firstAnnotation = annotations.FirstOrDefault();

            if (firstAnnotation != null)
            {
                var beginOffset = textDocument.LocationToOffset(firstAnnotation.Region.Begin);
                var endOffset   = textDocument.LocationToOffset(firstAnnotation.Region.End);
                return(new MSBuildNavigationResult(
                           annotations.Select(a => a.Path).ToArray(), beginOffset, endOffset - beginOffset + 1
                           ));
            }

            if (rr.ReferenceKind == MSBuildReferenceKind.Target)
            {
                return(new MSBuildNavigationResult(
                           MSBuildReferenceKind.Target, (string)rr.Reference, rr.ReferenceOffset, rr.ReferenceLength
                           ));
            }

            if (rr.ReferenceKind == MSBuildReferenceKind.FileOrFolder)
            {
                return(new MSBuildNavigationResult(
                           (string[])rr.Reference, rr.ReferenceOffset, rr.ReferenceLength
                           ));
            }

            if (rr.ReferenceKind == MSBuildReferenceKind.Task)
            {
                var task = doc.GetTask((string)rr.Reference);
                if (task.DeclaredInFile != null)
                {
                    return(new MSBuildNavigationResult(
                               MSBuildReferenceKind.Task, (string)rr.Reference, rr.ReferenceOffset, rr.ReferenceLength,
                               task.DeclaredInFile, task.DeclaredAtLocation
                               ));
                }
            }

            return(null);
        }
Example #3
0
        public static bool CanNavigate(MSBuildRootDocument doc, DocumentLocation location, MSBuildResolveResult rr)
        {
            if (rr == null)
            {
                return(false);
            }

            var annotations = GetAnnotationsAtLocation <NavigationAnnotation> (doc, location);

            if (annotations != null && annotations.Any())
            {
                return(true);
            }

            if (rr.ReferenceKind == MSBuildReferenceKind.Target)
            {
                return(true);
            }

            if (rr.ReferenceKind == MSBuildReferenceKind.FileOrFolder)
            {
                return(true);
            }

            return(false);
        }
Example #4
0
 public static bool IsCondition(this MSBuildResolveResult rr)
 {
     return(rr.LanguageAttribute != null && rr.LanguageAttribute.ValueKind == MSBuildValueKind.Condition);
 }
        public static MSBuildResolveResult Resolve(
            XmlParser parser, IReadonlyTextDocument document, MSBuildDocument context)
        {
            int offset = parser.Position;

            //clones and connects nodes to their parents
            parser = parser.GetTreeParser();

            var nodePath = parser.Nodes.ToList();

            nodePath.Reverse();

            //capture incomplete names, attributes and element values
            int i = offset;

            if (parser.CurrentState is XmlRootState && parser.Nodes.Peek() is XElement unclosedEl)
            {
                while (i < document.Length && InRootOrClosingTagState() && !unclosedEl.IsClosed)
                {
                    parser.Push(document.GetCharAt(i++));
                }
            }
            else
            {
                while (i < document.Length && InNameOrAttributeState())
                {
                    parser.Push(document.GetCharAt(i++));
                }
            }

            //if nodes are incomplete, they won't get connected
            //HACK: the only way to reconnect them is reflection
            if (nodePath.Count > 1)
            {
                for (int idx = 1; idx < nodePath.Count; idx++)
                {
                    var node = nodePath [idx];
                    if (node.Parent == null)
                    {
                        var parent = nodePath [idx - 1];
                        ParentProp.SetValue(node, parent);
                    }
                }
            }

            //need to look up element by walking how the path, since at each level, if the parent has special children,
            //then that gives us information to identify the type of its children
            MSBuildLanguageElement   languageElement   = null;
            MSBuildLanguageAttribute languageAttribute = null;
            XElement   el  = null;
            XAttribute att = null;

            foreach (var node in nodePath)
            {
                if (node is XAttribute xatt && xatt.Name.Prefix == null)
                {
                    att = xatt;
                    languageAttribute = languageElement?.GetAttribute(att.Name.Name);
                    break;
                }

                //if children of parent is known to be arbitrary data, don't go into it
                if (languageElement != null && languageElement.ValueKind == MSBuildValueKind.Data)
                {
                    break;
                }

                //code completion is forgiving, all we care about best guess resolve for deepest child
                if (node is XElement xel && xel.Name.Prefix == null)
                {
                    el = xel;
                    languageElement = MSBuildLanguageElement.Get(el.Name.Name, languageElement);
                    if (languageElement != null)
                    {
                        continue;
                    }
                }

                languageElement = null;
            }

            if (languageElement == null)
            {
                return(null);
            }

            var rr = new MSBuildResolveResult {
                LanguageElement   = languageElement,
                LanguageAttribute = languageAttribute,
                XElement          = el,
                XAttribute        = att
            };

            var rv = new MSBuildResolveVisitor(offset, rr);

            rv.Run(el, languageElement, document.FileName, document, context);

            return(rr);

            bool InNameOrAttributeState() =>
            parser.CurrentState is XmlNameState ||
            parser.CurrentState is XmlAttributeState ||
            parser.CurrentState is XmlAttributeValueState;

            bool InRootOrClosingTagState() =>
            parser.CurrentState is XmlRootState ||
            parser.CurrentState is XmlNameState ||
            parser.CurrentState is XmlClosingTagState;
        }
 public MSBuildResolveVisitor(int offset, MSBuildResolveResult rr)
 {
     this.offset = offset;
     this.rr     = rr;
 }