Skip to content

Commit

Permalink
Optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
DerekZiemba committed Jan 18, 2019
1 parent 7462a60 commit a83863e
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 149 deletions.
16 changes: 8 additions & 8 deletions ZMBA.SyntaxColorizer.VS2017/app.config
Original file line number Diff line number Diff line change
Expand Up @@ -28,35 +28,35 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.9.0.0" newVersion="2.9.0.0" />
<bindingRedirect oldVersion="0.0.0.0-2.10.0.0" newVersion="2.9.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.9.0.0" newVersion="2.9.0.0" />
<bindingRedirect oldVersion="0.0.0.0-2.10.0.0" newVersion="2.9.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.Workspaces" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.10.0.0" newVersion="2.10.0.0" />
<bindingRedirect oldVersion="0.0.0.0-2.10.0.0" newVersion="2.9.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp.Workspaces" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.10.0.0" newVersion="2.10.0.0" />
<bindingRedirect oldVersion="0.0.0.0-2.10.0.0" newVersion="2.9.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.EditorFeatures.Text" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.9.0.0" newVersion="2.9.0.0" />
<bindingRedirect oldVersion="0.0.0.0-2.10.0.0" newVersion="2.9.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.Workspaces.Desktop" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.10.0.0" newVersion="2.10.0.0" />
<bindingRedirect oldVersion="0.0.0.0-2.10.0.0" newVersion="2.9.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.VisualBasic" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.10.0.0" newVersion="2.10.0.0" />
<bindingRedirect oldVersion="0.0.0.0-2.10.0.0" newVersion="2.9.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.VisualBasic.Workspaces" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.10.0.0" newVersion="2.10.0.0" />
<bindingRedirect oldVersion="0.0.0.0-2.10.0.0" newVersion="2.9.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.VisualStudio.Threading" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
Expand Down
145 changes: 64 additions & 81 deletions ZMBA.SyntaxColorizer/src/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.Composition;
using System.Runtime.CompilerServices;
using System.Threading;
Expand All @@ -17,106 +18,88 @@
using Microsoft.VisualStudio.Text.Tagging;
using Microsoft.VisualStudio.Utilities;
using Roslyn.Utilities;

using VB = Microsoft.CodeAnalysis.VisualBasic;
using CS = Microsoft.CodeAnalysis.CSharp;
using VBKind = Microsoft.CodeAnalysis.VisualBasic.SyntaxKind;
using CSKind = Microsoft.CodeAnalysis.CSharp.SyntaxKind;


namespace ZMBA.SyntaxColorizer {

internal static class Extensions {
internal static class Extensions {

[Flags]
public enum SubstrOptions {
Default = 0,
/// <summary> Whether the sequence is included in the returned substring </summary>
IncludeSeq = 1 << 0,
/// <summary> OrdinalIgnoreCase </summary>
IgnoreCase = 1 << 1,
/// <summary> If operation fails, return the original input string. </summary>
RetInput = 1 << 2
}

public static string SubstrAfterLast(this string input, string seq, SubstrOptions opts = SubstrOptions.Default) {
if (input?.Length > 0 && seq?.Length > 0) {
int index = input.LastIndexOf(seq, (opts & SubstrOptions.IgnoreCase) > 0 ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
if (index >= 0) {
if ((opts & SubstrOptions.IncludeSeq) == 0) { index += seq.Length; }
return input.Substring(index);
}
}
return (opts & SubstrOptions.RetInput) > 0 ? input : null;
private static ImmutableArray<ISymbol> GetMembersByName<T> (this T symbol, string name) where T: INamedTypeSymbol {
if(name != null && name.Length > 1) {
int index = name.LastIndexOf('.');
if(index >= 0) {
name = name.Substring(index);
}
return symbol.GetMembers(name);
}
return ImmutableArray<ISymbol>.Empty;
}


internal static SyntaxNode FindOuterMostNode(this SyntaxNode rootNode, TextSpan span, bool bTrivia) {
SyntaxNode node = rootNode.FindToken(span.Start, bTrivia).Parent;
SyntaxNode parent;
while (node != null && (parent = node.Parent) != null) {
TextSpan nodespan = node.FullSpan;
if (span.Start < nodespan.Start || nodespan.End < span.End || parent != rootNode && nodespan.Length == parent.FullSpan.Length) {
node = parent;
} else {
break;
}
}
switch (node.RawKind) {
case (int)VBKind.SimpleArgument: node = ((VB.Syntax.SimpleArgumentSyntax)node).Expression; break;
case (int)CSKind.Argument: node = ((CS.Syntax.ArgumentSyntax)node).Expression; break;
case (int)CSKind.AttributeArgument: node = ((CS.Syntax.AttributeArgumentSyntax)node).Expression; break;
}
return node;
internal static SyntaxNode FindOuterMostNode (this SyntaxNode rootNode, TextSpan span, bool bTrivia) {
SyntaxNode node = rootNode.FindToken(span.Start, bTrivia).Parent;
SyntaxNode parent;
while(node != null && (parent = node.Parent) != null) {
TextSpan nodespan = node.FullSpan;
if(span.Start < nodespan.Start || nodespan.End < span.End || parent != rootNode && nodespan.Length == parent.FullSpan.Length) {
node = parent;
} else {
break;
}
}
switch(node.RawKind) {
case (int)VBKind.SimpleArgument: node = ((VB.Syntax.SimpleArgumentSyntax)node).Expression; break;
case (int)CSKind.Argument: node = ((CS.Syntax.ArgumentSyntax)node).Expression; break;
case (int)CSKind.AttributeArgument: node = ((CS.Syntax.AttributeArgumentSyntax)node).Expression; break;
}
return node;
}

internal static bool MethodImplementsInterface<T> (this T symbol) where T: IMethodSymbol {
if(symbol.ExplicitInterfaceImplementations.Length > 0) { return true; }

internal static bool ImplementsInterface(this IMethodSymbol symbol) {
if (symbol.ExplicitInterfaceImplementations.Length > 0) {
return true;
}
var type = symbol.ContainingType;
var interfaces = type.Interfaces;
for (var i = 0; i < interfaces.Length; i++) {
var mems = interfaces[i].GetMembers(symbol.Name.SubstrAfterLast(".", SubstrOptions.RetInput));
for (var j = 0; j < mems.Length; j++) {
IMethodSymbol member = mems[j] as IMethodSymbol;
if (member != null && symbol.ReturnType == member.ReturnType) {
if (symbol.Parameters.Length == member.Parameters.Length) {
var impl = type.FindImplementationForInterfaceMember(member);
if (impl != null && impl.Equals(symbol)) {
return true;
}
}
}
ImmutableArray<INamedTypeSymbol> interfaces = symbol.ContainingType.Interfaces;
for(var i = 0; i < interfaces.Length; i++) {
ImmutableArray<ISymbol> mems = interfaces[i].GetMembersByName(symbol.Name);
for (var j = 0; j < mems.Length; j++) {
if(mems[j] is IMethodSymbol member && symbol.ReturnType == member.ReturnType) {
if(symbol.Parameters.Length == member.Parameters.Length) {
var impl = symbol.ContainingType.FindImplementationForInterfaceMember(member);
if(impl != null && impl.Equals(symbol)) {
return true;
}
}
}
return false;
}
}
}
return false;
}


internal static bool ImplementsInterface(this IPropertySymbol symbol) {
if (symbol.ExplicitInterfaceImplementations.Length > 0) {
return true;
}
var type = symbol.ContainingType;
var interfaces = type.Interfaces;
for (var i = 0; i < interfaces.Length; i++) {
var mems = interfaces[i].GetMembers(symbol.Name.SubstrAfterLast(".", SubstrOptions.RetInput));
for (var j = 0; j < mems.Length; j++) {
IPropertySymbol member = mems[j] as IPropertySymbol;
if (member != null && symbol.Type == member.Type) {
if (symbol.Parameters.Length == member.Parameters.Length) {
var impl = type.FindImplementationForInterfaceMember(member);
if (impl != null && impl.Equals(symbol)) {
return true;
}
}
}
internal static bool PropertyImplementsInterface<T> (this T symbol) where T: IPropertySymbol {
if(symbol.ExplicitInterfaceImplementations.Length > 0) { return true; }

ImmutableArray<INamedTypeSymbol> interfaces = symbol.ContainingType.Interfaces;
for(var i = 0; i < interfaces.Length; i++) {
ImmutableArray<ISymbol> mems = interfaces[i].GetMembersByName(symbol.Name);
for(var j = 0; j < mems.Length; j++) {
if(mems[j] is IPropertySymbol member && symbol.Type == member.Type) {
if(symbol.Parameters.Length == member.Parameters.Length) {
var impl = symbol.ContainingType.FindImplementationForInterfaceMember(member);
if(impl != null && impl.Equals(symbol)) {
return true;
}
}
}
return false;
}
}
}


}
return false;
}
}

}
125 changes: 65 additions & 60 deletions ZMBA.SyntaxColorizer/src/VBCSTagClassifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ internal class VBCSTagClassifier : ITagger<ClassificationTag> {

private readonly FormattingTags Tags;
private ClassifierContext CachedContext;
private static readonly List<ITagSpan<ClassificationTag>> EmptyTagSpansList = new List<ITagSpan<ClassificationTag>>(0);
private static readonly List<TagSpan<ClassificationTag>> EmptyTagSpansList = new List<TagSpan<ClassificationTag>>(0);

internal VBCSTagClassifier(IClassificationTypeRegistryService registry, ITextBuffer buffer) {
this.Tags = new FormattingTags(registry);
Expand Down Expand Up @@ -195,67 +195,72 @@ private void ClassifyIdentifier(ClassifierContext ctx, TextSpan txt) {
}
ctx.AssociateTagWithText(Tags.Identifier, txt);
}
private void ClassifyIdentifier_Field(ClassifierContext ctx, TextSpan txt, SyntaxNode node, IFieldSymbol symbol) {
if(symbol.ContainingType.TypeKind == TypeKind.Enum) {
ctx.AssociateTagWithText(Tags.EnumMember, txt);
} else {
if(symbol.IsConst) {
ctx.AssociateTagWithText(Tags.IdentifierConst, txt);
} else {
ctx.AssociateTagWithText(Tags.IdentifierField, txt);
}
}
}
private void ClassifyIdentifier_Property(ClassifierContext ctx, TextSpan txt, SyntaxNode node, IPropertySymbol symbol) {
if(symbol.ImplementsInterface()) {
ctx.AssociateTagWithText(Tags.IdentifierPropertyInterfaceImplementation, txt);
} else {
ctx.AssociateTagWithText(Tags.IdentifierProperty, txt);
}
}

private void ClassifyIdentifier_Field<T> (ClassifierContext ctx, TextSpan txt, SyntaxNode node, T symbol) where T: IFieldSymbol {
if(symbol.ContainingType.TypeKind == TypeKind.Enum) {
ctx.AssociateTagWithText(Tags.EnumMember, txt);
} else {
if(symbol.IsConst) {
ctx.AssociateTagWithText(Tags.IdentifierConst, txt);
} else {
ctx.AssociateTagWithText(Tags.IdentifierField, txt);
}
}
}

private void ClassifyIdentifier_Method(ClassifierContext ctx, TextSpan txt, SyntaxNode node, IMethodSymbol symbol) {
switch(node.Parent.RawKind) {
case (int)VBKind.Attribute:
case (int)CSKind.Attribute:
case (int)VBKind.QualifiedName when node.Parent.Parent.RawKind == (int)VBKind.Attribute:
case (int)CSKind.QualifiedName when node.Parent.Parent.RawKind == (int)CSKind.Attribute:
ctx.AssociateTagWithText(Tags.IdentifierAttribute, txt);
break;
default:
if(symbol.MethodKind == MethodKind.Constructor || symbol.MethodKind == MethodKind.StaticConstructor) {
ctx.AssociateTagWithText(Tags.MethodConstructor, txt);
} else if(symbol.MethodKind == MethodKind.UserDefinedOperator) {
ctx.AssociateTagWithText(Tags.MethodUserDefinedOperator, txt);
} else if(symbol.IsExtensionMethod) {
ctx.AssociateTagWithText(Tags.MethodExtension, txt);
} else if(symbol.IsStatic) {
ctx.AssociateTagWithText(Tags.MethodStatic, txt);
} else if(symbol.IsVirtual || symbol.IsOverride) {
ctx.AssociateTagWithText(Tags.MethodVirtual, txt);
} else if(symbol.ImplementsInterface()) {
ctx.AssociateTagWithText(Tags.MethodInterfaceImplementation, txt);
} else {
ctx.AssociateTagWithText(Tags.Method, txt);
}
break;
}
}
private void ClassifyIdentifier_NamedType(ClassifierContext ctx, TextSpan txt, SyntaxNode node, INamedTypeSymbol symbol) {
if(symbol.SpecialType != SpecialType.None) {
ctx.AssociateTagWithText(Tags.Type, txt);
} else {
ctx.AssociateTagWithText(Tags.TypeClass, txt);
}
}
private void ClassifyIdentifier_Local(ClassifierContext ctx, TextSpan txt, SyntaxNode node, ILocalSymbol symbol) {
if(symbol.IsConst) {
ctx.AssociateTagWithText(Tags.IdentifierConst, txt);
} else {
ctx.AssociateTagWithText(Tags.Variable, txt);
}
}
private void ClassifyIdentifier_Property<T> (ClassifierContext ctx, TextSpan txt, SyntaxNode node, T symbol) where T: IPropertySymbol {
if(symbol.PropertyImplementsInterface()) {
ctx.AssociateTagWithText(Tags.IdentifierPropertyInterfaceImplementation, txt);
} else {
ctx.AssociateTagWithText(Tags.IdentifierProperty, txt);
}
}


private void ClassifyIdentifier_Method<T> (ClassifierContext ctx, TextSpan txt, SyntaxNode node, T symbol) where T: IMethodSymbol {
switch(node.Parent.RawKind) {
case (int)VBKind.Attribute:
case (int)CSKind.Attribute:
case (int)VBKind.QualifiedName when node.Parent.Parent.RawKind == (int)VBKind.Attribute:
case (int)CSKind.QualifiedName when node.Parent.Parent.RawKind == (int)CSKind.Attribute:
ctx.AssociateTagWithText(Tags.IdentifierAttribute, txt);
break;
default:
if(symbol.MethodKind == MethodKind.Constructor || symbol.MethodKind == MethodKind.StaticConstructor) {
ctx.AssociateTagWithText(Tags.MethodConstructor, txt);
} else if(symbol.MethodKind == MethodKind.UserDefinedOperator) {
ctx.AssociateTagWithText(Tags.MethodUserDefinedOperator, txt);
} else if(symbol.IsExtensionMethod) {
ctx.AssociateTagWithText(Tags.MethodExtension, txt);
} else if(symbol.IsStatic) {
ctx.AssociateTagWithText(Tags.MethodStatic, txt);
} else if(symbol.IsVirtual || symbol.IsOverride) {
ctx.AssociateTagWithText(Tags.MethodVirtual, txt);
} else if(symbol.MethodImplementsInterface()) {
ctx.AssociateTagWithText(Tags.MethodInterfaceImplementation, txt);
} else {
ctx.AssociateTagWithText(Tags.Method, txt);
}

break;
}
}

private void ClassifyIdentifier_NamedType<T> (ClassifierContext ctx, TextSpan txt, SyntaxNode node, T symbol) where T: INamedTypeSymbol {
if(symbol.SpecialType != SpecialType.None) {
ctx.AssociateTagWithText(Tags.Type, txt);
} else {
ctx.AssociateTagWithText(Tags.TypeClass, txt);
}
}

private void ClassifyIdentifier_Local<T> (ClassifierContext ctx, TextSpan txt, SyntaxNode node, T symbol) where T: ILocalSymbol {
if(symbol.IsConst) {
ctx.AssociateTagWithText(Tags.IdentifierConst, txt);
} else {
ctx.AssociateTagWithText(Tags.Variable, txt);
}
}


}
Expand Down

0 comments on commit a83863e

Please sign in to comment.