Skip to content

Commit

Permalink
+ Added Find Symbol Named command to C# Smart Bar
Browse files Browse the repository at this point in the history
  • Loading branch information
wmjordan committed Dec 17, 2018
1 parent 050415a commit cbc9f63
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 15 deletions.
54 changes: 51 additions & 3 deletions Codist/Helpers/CodeAnalysisHelper.Symbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,12 @@ public static async Task<List<ISymbol>> FindExtensionMethodsAsync(this ITypeSymb
/// <summary>
/// Finds symbol declarations matching <paramref name="symbolName"/> within given <paramref name="project"/>.
/// </summary>
public static async Task<IEnumerable<ISymbol>> FindDeclarationsAsync(Project project, string symbolName, int resultLimit, SymbolFilter filter = SymbolFilter.All, CancellationToken token = default) {
var symbols = new SortedSet<ISymbol>(Comparer<ISymbol>.Create((x, y) => x.Name.Length - y.Name.Length));
public static async Task<IEnumerable<ISymbol>> FindDeclarationsAsync(this Project project, string symbolName, int resultLimit, bool fullMatch, bool matchCase, SymbolFilter filter = SymbolFilter.All, CancellationToken token = default) {
var symbols = new SortedSet<ISymbol>(CreateSymbolComparer());
int maxNameLength = 0;
foreach (var symbol in await Microsoft.CodeAnalysis.FindSymbols.SymbolFinder.FindSourceDeclarationsAsync(project, name => name.IndexOf(symbolName, StringComparison.OrdinalIgnoreCase) != -1, token)) {
var predicate = CreateNameFilter(symbolName, fullMatch, matchCase);

foreach (var symbol in await Microsoft.CodeAnalysis.FindSymbols.SymbolFinder.FindSourceDeclarationsAsync(project, predicate, token)) {
if (symbols.Count < resultLimit) {
symbols.Add(symbol);
}
Expand All @@ -161,6 +163,52 @@ public static async Task<IEnumerable<ISymbol>> FindDeclarationsAsync(Project pro
}
return symbols;
}

static Comparer<ISymbol> CreateSymbolComparer() {
return Comparer<ISymbol>.Create((x, y) => {
var l = x.Name.Length - y.Name.Length;
return l != 0 ? l : x.GetHashCode() - y.GetHashCode();
});
}

public static IEnumerable<ISymbol> FindDeclarationMatchName(this Compilation compilation, string symbolName, bool fullMatch, bool matchCase, CancellationToken cancellationToken = default) {
var filter = CreateNameFilter(symbolName, fullMatch, matchCase);
foreach (var type in compilation.GlobalNamespace.GetAllTypes(cancellationToken)) {
if (type.IsAccessible() && filter(type.Name)) {
yield return type;
}
if (cancellationToken.IsCancellationRequested) {
break;
}
foreach (var member in type.GetMembers()) {
if (member.Kind != SymbolKind.NamedType
&& member.CanBeReferencedByName
&& member.IsAccessible()
&& filter(member.Name)) {
yield return member;
}
}
}
}

static Func<string, bool> CreateNameFilter(string symbolName, bool fullMatch, bool matchCase) {
if (fullMatch) {
if (matchCase) {
return name => name == symbolName;
}
else {
return name => String.Equals(name, symbolName, StringComparison.OrdinalIgnoreCase);
}
}
else {
if (matchCase) {
return name => name.IndexOf(symbolName, StringComparison.Ordinal) != -1;
}
else {
return name => name.IndexOf(symbolName, StringComparison.OrdinalIgnoreCase) != -1;
}
}
}
#endregion

#region Assembly and namespace
Expand Down
2 changes: 1 addition & 1 deletion Codist/Helpers/CodeAnalysisHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public static Document GetDocument(this Workspace workspace, SnapshotSpan span)
: solution.WithDocumentText(docId, sourceText, PreservationMode.PreserveIdentity).GetDocument(docId);
}

public static IEnumerable<Document> GetRelatedDocuments(this Project project) {
public static IEnumerable<Document> GetRelatedProjectDocuments(this Project project) {
var projects = GetRelatedProjects(project);
foreach (var proj in projects) {
foreach (var doc in proj.Documents) {
Expand Down
40 changes: 29 additions & 11 deletions Codist/SmartBars/CSharpSmartBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ void AddContextualCommands(CancellationToken cancellationToken) {
if (node is IdentifierNameSyntax) {
AddEditorCommand(MyToolBar, KnownImageIds.GoToDefinition, "Edit.GoToDefinition", "Go to definition\nRight click: Peek definition", "Edit.PeekDefinition");
}
AddCommands(MyToolBar, KnownImageIds.ReferencedDimension, "Analyze references...", GetReferenceCommandsAsync);
AddCommands(MyToolBar, KnownImageIds.ReferencedDimension, "Analyze symbol...", GetReferenceCommandsAsync);
if (Classifiers.SymbolMarkManager.CanBookmark(_Symbol)) {
AddCommands(MyToolBar, KnownImageIds.FlagGroup, "Mark symbol...", null, GetMarkerCommands);
}
Expand Down Expand Up @@ -283,7 +283,7 @@ void SetSymbolMark(CommandContext context) {

void FindCallers(CommandContext context, MenuItem menuItem, ISymbol source) {
var doc = _Context.Document;
var docs = System.Collections.Immutable.ImmutableHashSet.CreateRange(doc.Project.GetRelatedDocuments());
var docs = System.Collections.Immutable.ImmutableHashSet.CreateRange(doc.Project.GetRelatedProjectDocuments());
SymbolCallerInfo[] callers;
switch (source.Kind) {
case SymbolKind.Method:
Expand Down Expand Up @@ -430,7 +430,7 @@ void FindOverrides(CommandContext context, MenuItem menuItem, ISymbol symbol) {
}

void FindReferences(CommandContext context, MenuItem menuItem, ISymbol source) {
var refs = ThreadHelper.JoinableTaskFactory.Run(() => SymbolFinder.FindReferencesAsync(source, _Context.Document.Project.Solution, System.Collections.Immutable.ImmutableHashSet.CreateRange(_Context.Document.Project.GetRelatedDocuments()), context.CancellationToken)).ToArray();
var refs = ThreadHelper.JoinableTaskFactory.Run(() => SymbolFinder.FindReferencesAsync(source, _Context.Document.Project.Solution, System.Collections.Immutable.ImmutableHashSet.CreateRange(_Context.Document.Project.GetRelatedProjectDocuments()), context.CancellationToken)).ToArray();
Array.Sort(refs, (a, b) => {
int s;
return 0 != (s = a.Definition.ContainingType.Name.CompareTo(b.Definition.ContainingType.Name)) ? s :
Expand All @@ -456,6 +456,11 @@ void FindReferences(CommandContext context, MenuItem menuItem, ISymbol source) {
}
}

void FindSymbolWithName(CommandContext ctx, MenuItem menuItem, ISymbol source) {
var result = _Context.SemanticModel.Compilation.FindDeclarationMatchName(source.Name, Keyboard.Modifiers == ModifierKeys.Control, true, ctx.CancellationToken);
SortAndGroupSymbolByClass(menuItem, new List<ISymbol>(result));
}

CommandItem[] GetDebugCommands(CommandContext ctx) {
return new CommandItem[] {
new CommandItem(KnownImageIds.Watch, "Add Watch", c => TextEditorHelper.ExecuteEditorCommand("Debug.AddWatch")),
Expand Down Expand Up @@ -563,6 +568,7 @@ async Task<IEnumerable<CommandItem>> GetReferenceCommandsAsync(CommandContext ct
break;
}
//r.Add(CreateCommandMenu("Find references...", KnownImageIds.ReferencedDimension, symbol, "No reference found", FindReferences));
r.Add(CreateCommandMenu("Find Symbol Named " + symbol.Name + "...", KnownImageIds.FindSymbol, symbol, "No symbol was found", FindSymbolWithName));
r.Add(new CommandItem(KnownImageIds.ReferencedDimension, "Find All References", _ => TextEditorHelper.ExecuteEditorCommand("Edit.FindAllReferences")));
r.Add(new CommandItem(KnownImageIds.ListMembers, "Go to Member", _ => TextEditorHelper.ExecuteEditorCommand("Edit.GoToMember")));
r.Add(new CommandItem(KnownImageIds.Type, "Go to Type", _ => TextEditorHelper.ExecuteEditorCommand("Edit.GoToType")));
Expand Down Expand Up @@ -668,9 +674,17 @@ void SortAndGroupSymbolByClass(MenuItem menuItem, List<ISymbol> members) {
INamedTypeSymbol typeSymbol = null;
foreach (var member in members) {
if (typeSymbol == null || typeSymbol != member.ContainingType) {
typeSymbol = member.ContainingType;
subMenu = new SymbolMenuItem(this, typeSymbol, null);
menuItem.Items.Add(subMenu);
typeSymbol = member.ContainingType ?? member as INamedTypeSymbol;
if (typeSymbol != null) {
subMenu = new SymbolMenuItem(this, typeSymbol, typeSymbol.Locations);
menuItem.Items.Add(subMenu);
if (typeSymbol == member) {
continue;
}
}
else {
continue;
}
}
subMenu.Items.Add(new SymbolMenuItem(this, member, member.Locations));
}
Expand All @@ -679,12 +693,15 @@ void SortAndGroupSymbolByClass(MenuItem menuItem, List<ISymbol> members) {

static int CompareSymbol(ISymbol a, ISymbol b) {
var s = b.ContainingAssembly.GetSourceType().CompareTo(a.ContainingAssembly.GetSourceType());
INamedTypeSymbol ta, tb;
return s != 0 ? s
: (s = (tb = b.ContainingType).DeclaredAccessibility.CompareTo((ta = a.ContainingType).DeclaredAccessibility)) != 0 ? s
if (s != 0) {
return s;
}
INamedTypeSymbol ta = a.ContainingType, tb = b.ContainingType;
var ct = ta != null && tb != null;
return ct && (s = tb.DeclaredAccessibility.CompareTo(ta.DeclaredAccessibility)) != 0 ? s
: (s = b.DeclaredAccessibility.CompareTo(a.DeclaredAccessibility)) != 0 ? s
: (s = ta.Name.CompareTo(tb.Name)) != 0 ? s
: (s = ta.GetHashCode().CompareTo(tb.GetHashCode())) != 0 ? s
: ct && (s = ta.Name.CompareTo(tb.Name)) != 0 ? s
: ct && (s = ta.GetHashCode().CompareTo(tb.GetHashCode())) != 0 ? s
: (s = a.Name.CompareTo(b.Name)) != 0 ? s
: 0;
}
Expand Down Expand Up @@ -734,6 +751,7 @@ void GotoLocation(object sender, RoutedEventArgs args) {
if (loc != null) {
var p = loc.GetLineSpan();
CodistPackage.DTE.OpenFile(loc.SourceTree.FilePath, p.StartLinePosition.Line + 1, p.StartLinePosition.Character + 1);
args.Handled = true;
}
}

Expand Down

0 comments on commit cbc9f63

Please sign in to comment.