From 136a02424f9d4365c779fde920581adad710fb0e Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Wed, 17 Apr 2024 01:48:56 -0400 Subject: [PATCH] Support Go To Definition on properties/items For properties/items, there isn't a definition per se, but searching for places where they are written/assigned seems like a reasonable interpretation that makes F12 more useful. Partial fix for #163 --- .../Navigation/MSBuildNavigationService.cs | 59 ++++++++++++++++++- .../Language/MSBuildNavigation.cs | 8 +++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/MonoDevelop.MSBuild.Editor/Navigation/MSBuildNavigationService.cs b/MonoDevelop.MSBuild.Editor/Navigation/MSBuildNavigationService.cs index 3b986787..3ce4074d 100644 --- a/MonoDevelop.MSBuild.Editor/Navigation/MSBuildNavigationService.cs +++ b/MonoDevelop.MSBuild.Editor/Navigation/MSBuildNavigationService.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +#nullable enable annotations + using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -109,6 +111,16 @@ public bool Navigate (MSBuildNavigationResult result, ITextBuffer buffer) return true; } + if (result.Kind == MSBuildReferenceKind.Item) { + FindItemWrites (result.Name, buffer).LogTaskExceptionsAndForget (logger); + return true; + } + + if (result.Kind == MSBuildReferenceKind.Property) { + FindPropertyWrites (result.Name, buffer).LogTaskExceptionsAndForget (logger); + return true; + } + if (result.Paths != null) { if (result.Paths.Length == 1) { EditorHost.OpenFile (result.Paths[0], 0); @@ -263,6 +275,46 @@ async Task FindTargetDefinitions (string targetName, ITextBuffer buffer) await searchCtx.OnCompletedAsync (); } + async Task FindPropertyWrites (string propertyName, ITextBuffer buffer) + { + var searchCtx = Presenter.StartSearch ($"Property '{propertyName}' writes", propertyName, true); + + try { + await FindReferences ( + searchCtx, + (doc, text, logger, reporter) => new MSBuildPropertyReferenceCollector (doc, text, logger, propertyName, reporter), + buffer, + result => result.Usage switch { + ReferenceUsage.Declaration or ReferenceUsage.Write => true, + _ => false + }); + } catch (Exception ex) when (!(ex is OperationCanceledException && searchCtx.CancellationToken.IsCancellationRequested)) { + var logger = LoggerService.GetLogger (buffer); + LogErrorFindReferences (logger, ex); + } + await searchCtx.OnCompletedAsync (); + } + + async Task FindItemWrites (string itemName, ITextBuffer buffer) + { + var searchCtx = Presenter.StartSearch ($"Item '{itemName}' item", itemName, true); + + try { + await FindReferences ( + searchCtx, + (doc, text, logger, reporter) => new MSBuildItemReferenceCollector (doc, text, logger, itemName, reporter), + buffer, + result => result.Usage switch { + ReferenceUsage.Declaration or ReferenceUsage.Write => true, + _ => false + }); + } catch (Exception ex) when (!(ex is OperationCanceledException && searchCtx.CancellationToken.IsCancellationRequested)) { + var logger = LoggerService.GetLogger (buffer); + LogErrorFindReferences (logger, ex); + } + await searchCtx.OnCompletedAsync (); + } + delegate MSBuildReferenceCollector ReferenceCollectorFactory (MSBuildDocument doc, ITextSource textSource, ILogger logger, FindReferencesReporter reportResult); /// @@ -271,7 +323,8 @@ async Task FindTargetDefinitions (string targetName, ITextBuffer buffer) async Task FindReferences ( FindReferencesContext searchCtx, ReferenceCollectorFactory collectorFactory, - ITextBuffer buffer) + ITextBuffer buffer, + Func? resultFilter = null) { var openDocuments = EditorHost.GetOpenDocuments (); @@ -314,6 +367,10 @@ await ParallelAsync.ForEach (jobs, Environment.ProcessorCount, async (job, token void ReportResult (FindReferencesResult result) { + if (resultFilter is not null && resultFilter (result) == false) { + return; + } + var line = job.TextSource.Snapshot.GetLineFromPosition (result.Offset); var col = result.Offset - line.Start.Position; var lineText = line.GetText (); diff --git a/MonoDevelop.MSBuild/Language/MSBuildNavigation.cs b/MonoDevelop.MSBuild/Language/MSBuildNavigation.cs index d99a2ed1..42606cc0 100644 --- a/MonoDevelop.MSBuild/Language/MSBuildNavigation.cs +++ b/MonoDevelop.MSBuild/Language/MSBuildNavigation.cs @@ -88,6 +88,14 @@ IEnumerable GetAnnotatedPaths () } } + if (rr.ReferenceKind == MSBuildReferenceKind.Item) { + return new MSBuildNavigationResult (MSBuildReferenceKind.Item, rr.GetItemReference (), rr.ReferenceOffset, rr.ReferenceLength); + } + + if (rr.ReferenceKind == MSBuildReferenceKind.Property) { + return new MSBuildNavigationResult (MSBuildReferenceKind.Property, rr.GetPropertyReference (), rr.ReferenceOffset, rr.ReferenceLength); + } + if (rr.ReferenceKind == MSBuildReferenceKind.Target) { return new MSBuildNavigationResult (MSBuildReferenceKind.Target, rr.GetTargetReference (), rr.ReferenceOffset, rr.ReferenceLength); }