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)); }
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()); }
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); }
// 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); }
// 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()); }