예제 #1
0
        public override CompletionStartData InitializeCompletion(CompletionTrigger trigger, SnapshotPoint triggerLocation, CancellationToken token)
        {
            //we don't care need a real document here we're doing very basic resolution for triggering
            var spine = GetSpineParser(triggerLocation);
            var rr    = MSBuildResolver.Resolve(spine, triggerLocation.Snapshot.GetTextSource(), MSBuildRootDocument.Empty, null);

            if (rr?.LanguageElement != null)
            {
                if (ExpressionCompletion.IsPossibleExpressionCompletionContext(spine))
                {
                    string expression   = GetAttributeOrElementValueToCaret(spine, triggerLocation);
                    var    triggerState = ExpressionCompletion.GetTriggerState(
                        expression,
                        trigger.Character,
                        rr.IsCondition(),
                        out int triggerLength,
                        out ExpressionNode triggerExpression,
                        out var listKind,
                        out IReadOnlyList <ExpressionNode> comparandVariables
                        );
                    if (triggerState != ExpressionCompletion.TriggerState.None)
                    {
                        return(new CompletionStartData(CompletionParticipation.ProvidesItems, new SnapshotSpan(triggerLocation.Snapshot, triggerLocation.Position - triggerLength, triggerLength)));
                    }
                }
            }

            return(base.InitializeCompletion(trigger, triggerLocation, token));
        }
예제 #2
0
        public override CompletionStartData InitializeCompletion(CompletionTrigger trigger, SnapshotPoint triggerLocation, CancellationToken token)
        {
            //we don't care need a real document here we're doing very basic resolution for triggering
            var spine = XmlParser.GetSpineParser(triggerLocation);
            var rr    = MSBuildResolver.Resolve(spine.Clone(), triggerLocation.Snapshot.GetTextSource(), MSBuildRootDocument.Empty, null, token);

            if (rr?.ElementSyntax != null)
            {
                var reason = ConvertReason(trigger.Reason, trigger.Character);
                if (reason.HasValue && IsPossibleExpressionCompletionContext(spine))
                {
                    string expression   = spine.GetIncompleteValue(triggerLocation.Snapshot);
                    var    triggerState = GetTriggerState(
                        expression,
                        reason.Value,
                        trigger.Character,
                        rr.IsCondition(),
                        out int triggerLength,
                        out ExpressionNode _,
                        out var _,
                        out IReadOnlyList <ExpressionNode> _
                        );
                    if (triggerState != TriggerState.None)
                    {
                        return(new CompletionStartData(CompletionParticipation.ProvidesItems, new SnapshotSpan(triggerLocation.Snapshot, triggerLocation.Position - triggerLength, triggerLength)));
                    }
                }
            }

            return(base.InitializeCompletion(trigger, triggerLocation, token));
        }
        List <(int offset, MSBuildResolveResult result)> Resolve(string doc)
        {
            var functionTypeProvider = new RoslynFunctionTypeProvider(null);

            return(MSBuildTestHelpers
                   .SelectAtMarkers(doc, "hello.csproj", (state) => MSBuildResolver.Resolve(state.parser.Clone(), state.textSource, state.doc, functionTypeProvider))
                   .ToList());
        }
예제 #4
0
        internal MSBuildResolveResult ResolveCurrentLocation()
        {
            var doc = GetDocument();

            if (Tracker == null || doc == null)
            {
                return(null);
            }
            Tracker.UpdateEngine();
            return(MSBuildResolver.Resolve(Tracker.Engine, Editor.CreateDocumentSnapshot(), doc));
        }
        public async Task <QuickInfoItem> GetQuickInfoItemAsync(IAsyncQuickInfoSession session, CancellationToken cancellationToken)
        {
            var snapshot = textBuffer.CurrentSnapshot;

            var result = await parser.GetOrProcessAsync(snapshot, cancellationToken);

            var doc = result?.MSBuildDocument;

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

            var trigger = session.GetTriggerPoint(textBuffer);
            var offset  = trigger.GetPosition(snapshot);

            var spine = parser.XmlParser.GetSpineParser(new SnapshotPoint(snapshot, offset));

            var annotations = MSBuildNavigation.GetAnnotationsAtOffset <NavigationAnnotation> (doc, offset)?.ToList();

            if (annotations != null && annotations.Count > 0)
            {
                return(CreateQuickInfo(snapshot, annotations));
            }

            //FIXME: can we avoid awaiting this unless we actually need to resolve a function? need to propagate async downwards
            await provider.FunctionTypeProvider.EnsureInitialized(cancellationToken);

            var rr = MSBuildResolver.Resolve(
                spine, snapshot.GetTextSource(), doc, provider.FunctionTypeProvider, cancellationToken
                );

            if (rr != null)
            {
                if (rr.ReferenceKind == MSBuildReferenceKind.NuGetID)
                {
                    return(await CreateNuGetQuickInfo(snapshot, doc, rr, cancellationToken));
                }
                var info = rr.GetResolvedReference(doc, provider.FunctionTypeProvider);
                if (info != null)
                {
                    var element = await provider.DisplayElementFactory.GetInfoTooltipElement(
                        session.TextView.TextBuffer, doc, info, rr, cancellationToken
                        );

                    return(new QuickInfoItem(
                               snapshot.CreateTrackingSpan(rr.ReferenceOffset, rr.ReferenceLength, SpanTrackingMode.EdgeInclusive),
                               element));
                }
            }
            return(null);
        }
예제 #6
0
        // this is primarily used to pass info from GetCompletionContextAsync to GetDocumentationAsync
        // but also reuses the values calculated for expression completion in GetCompletionContextAsync
        // if it's determined not be be expression completion but actually ends up
        // in GetElementCompletionsAsync or GetAttributeCompletionsAsync
        async Task <MSBuildCompletionSessionContext> GetSessionContext(IAsyncCompletionSession session, SnapshotPoint triggerLocation, CancellationToken token)
        {
            if (session.Properties.TryGetProperty <MSBuildCompletionSessionContext> (typeof(MSBuildCompletionSessionContext), out var context))
            {
                return(context);
            }
            var parser      = GetParser();
            var parseResult = await parser.GetOrParseAsync((ITextSnapshot2)triggerLocation.Snapshot, token);

            var doc   = parseResult.MSBuildDocument ?? MSBuildRootDocument.Empty;
            var spine = parser.GetSpineParser(triggerLocation);
            var rr    = MSBuildResolver.Resolve(GetSpineParser(triggerLocation), triggerLocation.Snapshot.GetTextSource(), doc, provider.FunctionTypeProvider);

            context = new MSBuildCompletionSessionContext {
                doc = doc, rr = rr, spine = spine
            };
            session.Properties.AddProperty(typeof(MSBuildCompletionSessionContext), context);
            return(context);
        }
예제 #7
0
        // this is primarily used to pass info from GetCompletionContextAsync to GetDocumentationAsync
        // but also reuses the values calculated for expression completion in GetCompletionContextAsync
        // if it's determined not be be expression completion but actually ends up
        // in GetElementCompletionsAsync or GetAttributeCompletionsAsync
        async Task <MSBuildCompletionSessionContext> GetSessionContext(IAsyncCompletionSession session, SnapshotPoint triggerLocation, CancellationToken token)
        {
            if (session.Properties.TryGetProperty <MSBuildCompletionSessionContext> (typeof(MSBuildCompletionSessionContext), out var context))
            {
                return(context);
            }

            MSBuildParseResult parseResult = parser.LastOutput ?? await parser.GetOrProcessAsync(triggerLocation.Snapshot, token);

            var doc   = parseResult.MSBuildDocument ?? MSBuildRootDocument.Empty;
            var spine = XmlParser.GetSpineParser(triggerLocation);
            // clone the spine because the resolver alters it
            var rr = MSBuildResolver.Resolve(spine.Clone(), triggerLocation.Snapshot.GetTextSource(), doc, provider.FunctionTypeProvider, token);

            context = new MSBuildCompletionSessionContext {
                doc = doc, rr = rr, spine = spine
            };
            session.Properties.AddProperty(typeof(MSBuildCompletionSessionContext), context);
            return(context);
        }
        GetHighlightsAsync(SnapshotPoint caretLocation, CancellationToken token)
        {
            var snapshot    = caretLocation.Snapshot;
            var spineParser = parser.XmlParser.GetSpineParser(caretLocation);
            var textSource  = snapshot.GetTextSource();
            var doc         = parser.LastOutput?.MSBuildDocument;

            if (doc == null)
            {
                return(Empty);
            }

            var rr = MSBuildResolver.Resolve(spineParser, textSource, doc, provider.FunctionTypeProvider, token);

            if (!MSBuildReferenceCollector.CanCreate(rr))
            {
                return(Empty);
            }

            var parseResult = await parser.GetOrProcessAsync(snapshot, token).ConfigureAwait(false);

            doc = parseResult?.MSBuildDocument;
            if (doc == null)
            {
                return(Empty);
            }

            var references = new List <(ReferenceUsage usage, SnapshotSpan span)> ();
            var collector  = MSBuildReferenceCollector.Create(
                rr, provider.FunctionTypeProvider,
                r => references.Add((r.Usage, new SnapshotSpan(snapshot, r.Offset, r.Length))));

            await Task.Run(() => collector.Run(doc, token: token), token);

            return(
                new SnapshotSpan(caretLocation.Snapshot, rr.ReferenceOffset, rr.ReferenceLength),
                references.ToImmutableArray());
        }
        /// <summary>
        /// Gets a resolved reference from the document. The schema may be stale, in which case it returns false.
        /// </summary>
        public bool GetResolvedReference(ITextBuffer buffer, SnapshotPoint position, out MSBuildRootDocument doc, out MSBuildResolveResult rr)
        {
            // grab the field into a local to make this thread safe
            var cached = this.cached;

            // if the cached result is up to date, return it
            if (cached.Position == position)
            {
                doc = cached.Doc;
                rr  = cached.Result;
                return(true);
            }

            var parser     = ParserProvider.GetParser(buffer);
            var lastResult = parser.LastOutput;

            // if it's still at the same position and the last result is the same stale version, there's no point trying again
            if (cached.Position == position && lastResult.MSBuildDocument == cached.Doc)
            {
                doc = cached.Doc;
                rr  = cached.Result;
                return(false);
            }

            // actually do the work
            cached.Doc    = doc = lastResult.MSBuildDocument;
            cached.Result = rr = MSBuildResolver.Resolve(
                parser.XmlParser.GetSpineParser(position),
                position.Snapshot.GetTextSource(),
                doc, FunctionTypeProvider);
            cached.Position = position;

            this.cached = cached;

            return(lastResult.Snapshot == position.Snapshot);
        }
 List <(int offset, MSBuildResolveResult result)> Resolve(string doc)
 {
     return(MSBuildTestHelpers
            .SelectAtMarkers(doc, "hello.csproj", (state) => MSBuildResolver.Resolve(state.parser, state.textDoc, state.doc))
            .ToList());
 }