提交 97edbdd5 编写于 作者: C CyrusNajmabadi

Allocate less while performing classification.

上级 0af79988
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editor.UnitTests.Classification;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
......@@ -16,7 +15,7 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Classification
{
public abstract class AbstractCSharpClassifierTests : AbstractClassifierTests
{
internal abstract Task<IEnumerable<ClassifiedSpan>> GetClassificationSpansAsync(string code, TextSpan textSpan, CSharpParseOptions options);
internal abstract Task<ImmutableArray<ClassifiedSpan>> GetClassificationSpansAsync(string code, TextSpan textSpan, CSharpParseOptions options);
protected string GetText(Tuple<string, string> tuple)
{
......
......@@ -2,13 +2,16 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Editor.Implementation.Classification;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Extensions;
using Microsoft.CodeAnalysis.Notification;
......@@ -22,14 +25,12 @@
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Classification
{
public partial class SemanticClassifierTests : AbstractCSharpClassifierTests
{
internal override async Task<IEnumerable<ClassifiedSpan>> GetClassificationSpansAsync(string code, TextSpan textSpan, CSharpParseOptions options)
internal override async Task<ImmutableArray<ClassifiedSpan>> GetClassificationSpansAsync(string code, TextSpan textSpan, CSharpParseOptions options)
{
using (var workspace = TestWorkspace.CreateCSharp(code, options))
{
......@@ -41,13 +42,13 @@ internal override async Task<IEnumerable<ClassifiedSpan>> GetClassificationSpans
var classifiers = service.GetDefaultSyntaxClassifiers();
var extensionManager = workspace.Services.GetService<IExtensionManager>();
var results = new List<ClassifiedSpan>();
var results = ArrayBuilder<ClassifiedSpan>.GetInstance();
await service.AddSemanticClassificationsAsync(document, textSpan,
extensionManager.CreateNodeExtensionGetter(classifiers, c => c.SyntaxNodeTypes),
extensionManager.CreateTokenExtensionGetter(classifiers, c => c.SyntaxTokenKinds),
results, CancellationToken.None);
return results;
return results.ToImmutableAndFree();
}
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
......@@ -17,7 +17,7 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Classification
{
public partial class SyntacticClassifierTests : AbstractCSharpClassifierTests
{
internal override async Task<IEnumerable<ClassifiedSpan>> GetClassificationSpansAsync(string code, TextSpan textSpan, CSharpParseOptions options)
internal override async Task<ImmutableArray<ClassifiedSpan>> GetClassificationSpansAsync(string code, TextSpan textSpan, CSharpParseOptions options)
{
using (var workspace = TestWorkspace.CreateCSharp(code, parseOptions: options))
{
......@@ -26,10 +26,10 @@ internal override async Task<IEnumerable<ClassifiedSpan>> GetClassificationSpans
var tree = await document.GetSyntaxTreeAsync();
var service = document.GetLanguageService<ISyntaxClassificationService>();
var result = new List<ClassifiedSpan>();
var result = ArrayBuilder<ClassifiedSpan>.GetInstance();
service.AddSyntacticClassifications(tree, textSpan, result, CancellationToken.None);
return result;
return result.ToImmutableAndFree();
}
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
......@@ -18,7 +19,7 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Classification
{
public partial class TotalClassifierTests : AbstractCSharpClassifierTests
{
internal override async Task<IEnumerable<ClassifiedSpan>> GetClassificationSpansAsync(
internal override async Task<ImmutableArray<ClassifiedSpan>> GetClassificationSpansAsync(
string code, TextSpan textSpan, CSharpParseOptions options)
{
using (var workspace = TestWorkspace.CreateCSharp(code, options))
......@@ -31,8 +32,8 @@ public partial class TotalClassifierTests : AbstractCSharpClassifierTests
var classifiers = service.GetDefaultSyntaxClassifiers();
var extensionManager = workspace.Services.GetService<IExtensionManager>();
var semanticClassifications = new List<ClassifiedSpan>();
var syntacticClassifications = new List<ClassifiedSpan>();
var semanticClassifications = ArrayBuilder<ClassifiedSpan>.GetInstance();
var syntacticClassifications = ArrayBuilder<ClassifiedSpan>.GetInstance();
await service.AddSemanticClassificationsAsync(document, textSpan,
extensionManager.CreateNodeExtensionGetter(classifiers, c => c.SyntaxNodeTypes),
extensionManager.CreateTokenExtensionGetter(classifiers, c => c.SyntaxTokenKinds),
......@@ -52,7 +53,9 @@ public partial class TotalClassifierTests : AbstractCSharpClassifierTests
where !classificationsSpans.Contains(t.TextSpan)
select t);
return allClassifications;
syntacticClassifications.Free();
semanticClassifications.Free();
return allClassifications.ToImmutableArray();
}
}
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports Microsoft.CodeAnalysis.Classification
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Classification
Imports Microsoft.CodeAnalysis.Text
......@@ -64,7 +65,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Classification
Return ClassificationBuilder.VBXmlEntityReference(value)
End Function
Friend MustOverride Function GetClassificationSpansAsync(code As String, textSpan As TextSpan) As Task(Of IEnumerable(Of ClassifiedSpan))
Friend MustOverride Function GetClassificationSpansAsync(code As String, textSpan As TextSpan) As Task(Of ImmutableArray(Of ClassifiedSpan))
Protected Function GetText(tuple As Tuple(Of String, String)) As String
Return "(" & tuple.Item1 & ", " & tuple.Item2 & ")"
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.Classification
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions
......@@ -11,7 +12,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Classification
Public Class SemanticClassifierTests
Inherits AbstractVisualBasicClassifierTests
Friend Overrides Async Function GetClassificationSpansAsync(code As String, textSpan As TextSpan) As Tasks.Task(Of IEnumerable(Of ClassifiedSpan))
Friend Overrides Async Function GetClassificationSpansAsync(code As String, textSpan As TextSpan) As Task(Of ImmutableArray(Of ClassifiedSpan))
Using workspace = TestWorkspace.CreateVisualBasic(code)
Dim document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id)
......@@ -19,7 +20,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Classification
Dim tree = Await document.GetSyntaxTreeAsync()
Dim result = New List(Of ClassifiedSpan)
Dim result = ArrayBuilder(Of ClassifiedSpan).GetInstance()
Dim classifiers = service.GetDefaultSyntaxClassifiers()
Dim extensionManager = workspace.Services.GetService(Of IExtensionManager)
......@@ -28,7 +29,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Classification
extensionManager.CreateTokenExtensionGetter(classifiers, Function(c) c.SyntaxTokenKinds),
result, CancellationToken.None)
Return result
Return result.ToImmutableAndFree()
End Using
End Function
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.Classification
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
......@@ -9,16 +10,16 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Classification
Public Class SyntacticClassifierTests
Inherits AbstractVisualBasicClassifierTests
Friend Overrides Async Function GetClassificationSpansAsync(code As String, textSpan As TextSpan) As Tasks.Task(Of IEnumerable(Of ClassifiedSpan))
Friend Overrides Async Function GetClassificationSpansAsync(code As String, textSpan As TextSpan) As Task(Of ImmutableArray(Of ClassifiedSpan))
Using Workspace = TestWorkspace.CreateVisualBasic(code)
Dim document = Workspace.CurrentSolution.Projects.First().Documents.First()
Dim tree = Await document.GetSyntaxTreeAsync()
Dim service = document.GetLanguageService(Of ISyntaxClassificationService)()
Dim result = New List(Of ClassifiedSpan)
Dim result = ArrayBuilder(Of ClassifiedSpan).GetInstance
service.AddSyntacticClassifications(tree, textSpan, result, CancellationToken.None)
Return result
Return result.ToImmutableAndFree()
End Using
End Function
......
......@@ -13,7 +13,12 @@ namespace Microsoft.CodeAnalysis.CSharp.Classification
internal class CSharpEditorClassificationService : AbstractClassificationService
{
public override void AddLexicalClassifications(SourceText text, TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken)
=> ClassificationHelpers.AddLexicalClassifications(text, textSpan, result, cancellationToken);
{
var temp = ArrayBuilder<ClassifiedSpan>.GetInstance();
ClassificationHelpers.AddLexicalClassifications(text, textSpan, temp, cancellationToken);
AddRange(temp, result);
temp.Free();
}
public override ClassifiedSpan AdjustStaleClassification(SourceText text, ClassifiedSpan classifiedSpan)
=> ClassificationHelpers.AdjustStaleClassification(text, classifiedSpan);
......
......@@ -287,7 +287,7 @@ private static bool IsActualContextualKeyword(SyntaxToken token)
return false;
}
internal static void AddLexicalClassifications(SourceText text, TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken)
internal static void AddLexicalClassifications(SourceText text, TextSpan textSpan, ArrayBuilder<ClassifiedSpan> result, CancellationToken cancellationToken)
{
var text2 = text.ToString(textSpan);
var tokens = SyntaxFactory.ParseTokens(text2, initialTokenPosition: textSpan.Start);
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.Classification.Classifiers;
......@@ -15,34 +15,20 @@ protected AbstractSyntaxClassifier()
}
protected string GetClassificationForType(ITypeSymbol type)
{
return type.GetClassification();
}
=> type.GetClassification();
public virtual IEnumerable<ClassifiedSpan> ClassifyNode(SyntaxNode syntax, SemanticModel semanticModel, CancellationToken cancellationToken)
public virtual void AddClassifications(SyntaxNode syntax, SemanticModel semanticModel, ArrayBuilder<ClassifiedSpan> result, CancellationToken cancellationToken)
{
return null;
}
public virtual IEnumerable<ClassifiedSpan> ClassifyToken(SyntaxToken syntax, SemanticModel semanticModel, CancellationToken cancellationToken)
public virtual void AddClassifications(SyntaxToken syntax, SemanticModel semanticModel, ArrayBuilder<ClassifiedSpan> result, CancellationToken cancellationToken)
{
return null;
}
public virtual IEnumerable<Type> SyntaxNodeTypes
{
get
{
return null;
}
}
public virtual ImmutableArray<Type> SyntaxNodeTypes
=> ImmutableArray<Type>.Empty;
public virtual IEnumerable<int> SyntaxTokenKinds
{
get
{
return null;
}
}
public virtual ImmutableArray<int> SyntaxTokenKinds
=> ImmutableArray<int>.Empty;
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Threading;
......@@ -15,31 +14,22 @@ namespace Microsoft.CodeAnalysis.CSharp.Classification
[ExportLanguageService(typeof(ISyntaxClassificationService), LanguageNames.CSharp), Shared]
internal class CSharpSyntaxClassificationService : AbstractSyntaxClassificationService
{
private readonly IEnumerable<ISyntaxClassifier> s_defaultSyntaxClassifiers =
private readonly ImmutableArray<ISyntaxClassifier> s_defaultSyntaxClassifiers =
ImmutableArray.Create<ISyntaxClassifier>(
new NameSyntaxClassifier(),
new SyntaxTokenClassifier(),
new UsingDirectiveSyntaxClassifier());
public override IEnumerable<ISyntaxClassifier> GetDefaultSyntaxClassifiers()
{
return s_defaultSyntaxClassifiers;
}
public override ImmutableArray<ISyntaxClassifier> GetDefaultSyntaxClassifiers()
=> s_defaultSyntaxClassifiers;
public override void AddLexicalClassifications(SourceText text, TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken)
{
ClassificationHelpers.AddLexicalClassifications(text, textSpan, result, cancellationToken);
}
public override void AddLexicalClassifications(SourceText text, TextSpan textSpan, ArrayBuilder<ClassifiedSpan> result, CancellationToken cancellationToken)
=> ClassificationHelpers.AddLexicalClassifications(text, textSpan, result, cancellationToken);
public override void AddSyntacticClassifications(SyntaxTree syntaxTree, TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken)
{
var root = syntaxTree.GetRoot(cancellationToken);
Worker.CollectClassifiedSpans(root, textSpan, result, cancellationToken);
}
public override void AddSyntacticClassifications(SyntaxTree syntaxTree, TextSpan textSpan, ArrayBuilder<ClassifiedSpan> result, CancellationToken cancellationToken)
=> Worker.CollectClassifiedSpans(syntaxTree.GetRoot(cancellationToken), textSpan, result, cancellationToken);
public override ClassifiedSpan FixClassification(SourceText rawText, ClassifiedSpan classifiedSpan)
{
return ClassificationHelpers.AdjustStaleClassification(rawText, classifiedSpan);
}
=> ClassificationHelpers.AdjustStaleClassification(rawText, classifiedSpan);
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Shared.Extensions;
......@@ -15,47 +15,37 @@ namespace Microsoft.CodeAnalysis.CSharp.Classification.Classifiers
{
internal class NameSyntaxClassifier : AbstractSyntaxClassifier
{
public override IEnumerable<ClassifiedSpan> ClassifyNode(
public override void AddClassifications(
SyntaxNode syntax,
SemanticModel semanticModel,
ArrayBuilder<ClassifiedSpan> result,
CancellationToken cancellationToken)
{
var name = syntax as NameSyntax;
if (name != null)
{
return ClassifyTypeSyntax(name, semanticModel, cancellationToken);
ClassifyTypeSyntax(name, semanticModel, result, cancellationToken);
}
return null;
}
public override IEnumerable<Type> SyntaxNodeTypes
{
get
{
yield return typeof(NameSyntax);
}
}
public override ImmutableArray<Type> SyntaxNodeTypes { get; } = ImmutableArray.Create(typeof(NameSyntax));
private IEnumerable<ClassifiedSpan> ClassifyTypeSyntax(
private void ClassifyTypeSyntax(
NameSyntax name,
SemanticModel semanticModel,
ArrayBuilder<ClassifiedSpan> result,
CancellationToken cancellationToken)
{
if (!IsNamespaceName(name))
{
var symbolInfo = semanticModel.GetSymbolInfo(name, cancellationToken);
if (TryClassifySymbol(name, symbolInfo, semanticModel, cancellationToken, out var result) ||
TryClassifyFromIdentifier(name, symbolInfo, out result) ||
TryClassifyValueIdentifier(name, symbolInfo, out result) ||
TryClassifyNameOfIdentifier(name, symbolInfo, out result))
{
return result;
}
var _ =
TryClassifySymbol(name, symbolInfo, semanticModel, result, cancellationToken) ||
TryClassifyFromIdentifier(name, symbolInfo, result) ||
TryClassifyValueIdentifier(name, symbolInfo, result) ||
TryClassifyNameOfIdentifier(name, symbolInfo, result);
}
return null;
}
private static bool IsNamespaceName(NameSyntax name)
......@@ -72,12 +62,12 @@ private static bool IsNamespaceName(NameSyntax name)
NameSyntax name,
SymbolInfo symbolInfo,
SemanticModel semanticModel,
CancellationToken cancellationToken,
out IEnumerable<ClassifiedSpan> result)
ArrayBuilder<ClassifiedSpan> result,
CancellationToken cancellationToken)
{
if (symbolInfo.CandidateReason == CandidateReason.Ambiguous)
{
return TryClassifyAmbiguousSymbol(name, symbolInfo, semanticModel, cancellationToken, out result);
return TryClassifyAmbiguousSymbol(name, symbolInfo, semanticModel, result, cancellationToken);
}
// Only classify if we get one good symbol back, or if it bound to a constructor symbol with
......@@ -85,11 +75,10 @@ private static bool IsNamespaceName(NameSyntax name)
var symbol = TryGetSymbol(name, symbolInfo, semanticModel);
if (TryClassifySymbol(name, symbol, semanticModel, cancellationToken, out var classifiedSpan))
{
result = SpecializedCollections.SingletonEnumerable(classifiedSpan);
result.Add(classifiedSpan);
return true;
}
result = null;
return false;
}
......@@ -97,27 +86,33 @@ private static bool IsNamespaceName(NameSyntax name)
NameSyntax name,
SymbolInfo symbolInfo,
SemanticModel semanticModel,
CancellationToken cancellationToken,
out IEnumerable<ClassifiedSpan> result)
ArrayBuilder<ClassifiedSpan> result,
CancellationToken cancellationToken)
{
// If everything classifies the same way, then just pick that classification.
var set = new HashSet<ClassifiedSpan>();
foreach (var symbol in symbolInfo.CandidateSymbols)
var set = PooledHashSet<ClassifiedSpan>.GetInstance();
try
{
if (TryClassifySymbol(name, symbol, semanticModel, cancellationToken, out var classifiedSpan))
foreach (var symbol in symbolInfo.CandidateSymbols)
{
set.Add(classifiedSpan);
if (TryClassifySymbol(name, symbol, semanticModel, cancellationToken, out var classifiedSpan))
{
set.Add(classifiedSpan);
}
}
}
if (set.Count == 1)
if (set.Count == 1)
{
result.Add(set.First());
return true;
}
return false;
}
finally
{
result = SpecializedCollections.SingletonEnumerable(set.First());
return true;
set.Free();
}
result = null;
return false;
}
private bool TryClassifySymbol(
......@@ -244,7 +239,7 @@ private static ISymbol TryGetSymbol(NameSyntax name, SymbolInfo symbolInfo, Sema
private bool TryClassifyFromIdentifier(
NameSyntax name,
SymbolInfo symbolInfo,
out IEnumerable<ClassifiedSpan> result)
ArrayBuilder<ClassifiedSpan> result)
{
// Okay - it wasn't a type. If the syntax matches "var q = from" or "q = from", and from
// doesn't bind to anything then optimistically color from as a keyword.
......@@ -256,34 +251,31 @@ private static ISymbol TryGetSymbol(NameSyntax name, SymbolInfo symbolInfo, Sema
var token = identifierName.Identifier;
if (identifierName.IsRightSideOfAnyAssignExpression() || identifierName.IsVariableDeclaratorValue())
{
result = SpecializedCollections.SingletonEnumerable(
new ClassifiedSpan(token.Span, ClassificationTypeNames.Keyword));
result.Add(new ClassifiedSpan(token.Span, ClassificationTypeNames.Keyword));
return true;
}
}
result = null;
return false;
}
private bool TryClassifyValueIdentifier(
NameSyntax name,
SymbolInfo symbolInfo,
out IEnumerable<ClassifiedSpan> result)
ArrayBuilder<ClassifiedSpan> result)
{
var identifierName = name as IdentifierNameSyntax;
if (symbolInfo.Symbol.IsImplicitValueParameter())
{
result = SpecializedCollections.SingletonEnumerable(
new ClassifiedSpan(identifierName.Identifier.Span, ClassificationTypeNames.Keyword));
result.Add(new ClassifiedSpan(identifierName.Identifier.Span, ClassificationTypeNames.Keyword));
return true;
}
result = null;
return false;
}
private bool TryClassifyNameOfIdentifier(NameSyntax name, SymbolInfo symbolInfo, out IEnumerable<ClassifiedSpan> result)
private bool TryClassifyNameOfIdentifier(
NameSyntax name, SymbolInfo symbolInfo, ArrayBuilder<ClassifiedSpan> result)
{
var identifierName = name as IdentifierNameSyntax;
if (identifierName != null &&
......@@ -291,11 +283,10 @@ private bool TryClassifyNameOfIdentifier(NameSyntax name, SymbolInfo symbolInfo,
symbolInfo.Symbol == null &&
!symbolInfo.CandidateSymbols.Any())
{
result = SpecializedCollections.SingletonEnumerable(new ClassifiedSpan(identifierName.Identifier.Span, ClassificationTypeNames.Keyword));
result.Add(new ClassifiedSpan(identifierName.Identifier.Span, ClassificationTypeNames.Keyword));
return true;
}
result = null;
return false;
}
......
......@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Classification;
......@@ -14,19 +15,14 @@ namespace Microsoft.CodeAnalysis.CSharp.Classification.Classifiers
{
internal class SyntaxTokenClassifier : AbstractSyntaxClassifier
{
public override IEnumerable<int> SyntaxTokenKinds
{
get
{
yield return (int)SyntaxKind.LessThanToken;
}
}
public override ImmutableArray<int> SyntaxTokenKinds { get; } = ImmutableArray.Create((int)SyntaxKind.LessThanToken);
private static readonly Func<ITypeSymbol, bool> s_shouldInclude = t => t.TypeKind != TypeKind.Error && t.GetArity() > 0;
public override IEnumerable<ClassifiedSpan> ClassifyToken(
public override void AddClassifications(
SyntaxToken lessThanToken,
SemanticModel semanticModel,
ArrayBuilder<ClassifiedSpan> result,
CancellationToken cancellationToken)
{
var syntaxTree = semanticModel.SyntaxTree;
......@@ -44,13 +40,10 @@ public override IEnumerable<int> SyntaxTokenKinds
var types = semanticModel.LookupTypeRegardlessOfArity(identifier, cancellationToken);
if (types.Any(s_shouldInclude))
{
return SpecializedCollections.SingletonEnumerable(
new ClassifiedSpan(identifier.Span, GetClassificationForType(types.First())));
result.Add(new ClassifiedSpan(identifier.Span, GetClassificationForType(types.First())));
}
}
}
return null;
}
private bool CouldBeGenericType(SyntaxToken identifier)
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Classification.Classifiers
{
internal class UsingDirectiveSyntaxClassifier : AbstractSyntaxClassifier
{
public override IEnumerable<ClassifiedSpan> ClassifyNode(
public override void AddClassifications(
SyntaxNode syntax,
SemanticModel semanticModel,
ArrayBuilder<ClassifiedSpan> result,
CancellationToken cancellationToken)
{
if (syntax is UsingDirectiveSyntax usingDirective)
{
return ClassifyUsingDirectiveSyntax(usingDirective, semanticModel, cancellationToken);
ClassifyUsingDirectiveSyntax(usingDirective, semanticModel, result, cancellationToken);
}
return null;
}
public override IEnumerable<Type> SyntaxNodeTypes
{
get
{
yield return typeof(UsingDirectiveSyntax);
}
}
public override ImmutableArray<Type> SyntaxNodeTypes { get; } = ImmutableArray.Create(typeof(UsingDirectiveSyntax));
private IEnumerable<ClassifiedSpan> ClassifyUsingDirectiveSyntax(
private void ClassifyUsingDirectiveSyntax(
UsingDirectiveSyntax usingDirective,
SemanticModel semanticModel,
ArrayBuilder<ClassifiedSpan> result,
CancellationToken cancellationToken)
{
// For using aliases, we bind the target on the right of the equals and use that
......@@ -48,12 +41,10 @@ public override IEnumerable<Type> SyntaxNodeTypes
if (classification != null)
{
var token = usingDirective.Alias.Name;
return SpecializedCollections.SingletonEnumerable(new ClassifiedSpan(token.Span, classification));
result.Add(new ClassifiedSpan(token.Span, classification));
}
}
}
return null;
}
}
}
}
\ No newline at end of file
......@@ -17,10 +17,10 @@ namespace Microsoft.CodeAnalysis.CSharp.Classification
internal partial class Worker
{
private readonly TextSpan _textSpan;
private readonly List<ClassifiedSpan> _result;
private readonly ArrayBuilder<ClassifiedSpan> _result;
private readonly CancellationToken _cancellationToken;
private Worker(TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken)
private Worker(TextSpan textSpan, ArrayBuilder<ClassifiedSpan> result, CancellationToken cancellationToken)
{
_result = result;
_textSpan = textSpan;
......@@ -28,7 +28,7 @@ private Worker(TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken
}
internal static void CollectClassifiedSpans(
IEnumerable<SyntaxToken> tokens, TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken)
IEnumerable<SyntaxToken> tokens, TextSpan textSpan, ArrayBuilder<ClassifiedSpan> result, CancellationToken cancellationToken)
{
var worker = new Worker(textSpan, result, cancellationToken);
foreach (var tk in tokens)
......@@ -37,8 +37,8 @@ private Worker(TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken
}
}
internal static void CollectClassifiedSpans(SyntaxNode
node, TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken)
internal static void CollectClassifiedSpans(
SyntaxNode node, TextSpan textSpan, ArrayBuilder<ClassifiedSpan> result, CancellationToken cancellationToken)
{
var worker = new Worker(textSpan, result, cancellationToken);
worker.ClassifyNode(node);
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
......@@ -14,7 +15,7 @@ internal abstract class AbstractClassificationService : IClassificationService
public abstract void AddLexicalClassifications(SourceText text, TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken);
public abstract ClassifiedSpan AdjustStaleClassification(SourceText text, ClassifiedSpan classifiedSpan);
public Task AddSemanticClassificationsAsync(Document document, TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken)
public async Task AddSemanticClassificationsAsync(Document document, TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken)
{
var classificationService = document.GetLanguageService<ISyntaxClassificationService>();
......@@ -24,7 +25,10 @@ public Task AddSemanticClassificationsAsync(Document document, TextSpan textSpan
var getNodeClassifiers = extensionManager.CreateNodeExtensionGetter(classifiers, c => c.SyntaxNodeTypes);
var getTokenClassifiers = extensionManager.CreateTokenExtensionGetter(classifiers, c => c.SyntaxTokenKinds);
return classificationService.AddSemanticClassificationsAsync(document, textSpan, getNodeClassifiers, getTokenClassifiers, result, cancellationToken);
var temp = ArrayBuilder<ClassifiedSpan>.GetInstance();
await classificationService.AddSemanticClassificationsAsync(document, textSpan, getNodeClassifiers, getTokenClassifiers, temp, cancellationToken).ConfigureAwait(false);
AddRange(temp, result);
temp.Free();
}
public async Task AddSyntacticClassificationsAsync(Document document, TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken)
......@@ -32,7 +36,18 @@ public async Task AddSyntacticClassificationsAsync(Document document, TextSpan t
var classificationService = document.GetLanguageService<ISyntaxClassificationService>();
var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
classificationService.AddSyntacticClassifications(syntaxTree, textSpan, result, cancellationToken);
var temp = ArrayBuilder<ClassifiedSpan>.GetInstance();
classificationService.AddSyntacticClassifications(syntaxTree, textSpan, temp, cancellationToken);
AddRange(temp, result);
temp.Free();
}
protected void AddRange(ArrayBuilder<ClassifiedSpan> temp, List<ClassifiedSpan> result)
{
foreach (var span in temp)
{
result.Add(span);
}
}
}
}
\ No newline at end of file
......@@ -37,20 +37,27 @@ public static class Classifier
var getNodeClassifiers = extensionManager.CreateNodeExtensionGetter(syntaxClassifiers, c => c.SyntaxNodeTypes);
var getTokenClassifiers = extensionManager.CreateTokenExtensionGetter(syntaxClassifiers, c => c.SyntaxTokenKinds);
var syntacticClassifications = new List<ClassifiedSpan>();
var semanticClassifications = new List<ClassifiedSpan>();
service.AddSyntacticClassifications(semanticModel.SyntaxTree, textSpan, syntacticClassifications, cancellationToken);
service.AddSemanticClassifications(semanticModel, textSpan, workspace, getNodeClassifiers, getTokenClassifiers, semanticClassifications, cancellationToken);
var syntacticClassifications = ArrayBuilder<ClassifiedSpan>.GetInstance();
var semanticClassifications = ArrayBuilder<ClassifiedSpan>.GetInstance();
try
{
service.AddSyntacticClassifications(semanticModel.SyntaxTree, textSpan, syntacticClassifications, cancellationToken);
service.AddSemanticClassifications(semanticModel, textSpan, workspace, getNodeClassifiers, getTokenClassifiers, semanticClassifications, cancellationToken);
var allClassifications = new List<ClassifiedSpan>(semanticClassifications.Where(s => s.TextSpan.OverlapsWith(textSpan)));
var semanticSet = semanticClassifications.Select(s => s.TextSpan).ToSet();
var allClassifications = new List<ClassifiedSpan>(semanticClassifications.Where(s => s.TextSpan.OverlapsWith(textSpan)));
var semanticSet = semanticClassifications.Select(s => s.TextSpan).ToSet();
allClassifications.AddRange(syntacticClassifications.Where(
s => s.TextSpan.OverlapsWith(textSpan) && !semanticSet.Contains(s.TextSpan)));
allClassifications.Sort((s1, s2) => s1.TextSpan.Start - s2.TextSpan.Start);
allClassifications.AddRange(syntacticClassifications.Where(
s => s.TextSpan.OverlapsWith(textSpan) && !semanticSet.Contains(s.TextSpan)));
allClassifications.Sort((s1, s2) => s1.TextSpan.Start - s2.TextSpan.Start);
return allClassifications;
return allClassifications;
}
finally
{
syntacticClassifications.Free();
semanticClassifications.Free();
}
}
internal static async Task<ImmutableArray<SymbolDisplayPart>> GetClassifiedSymbolDisplayPartsAsync(
......
......@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Classification.Classifiers;
using Microsoft.CodeAnalysis.Text;
......@@ -16,10 +17,10 @@ private struct Worker
private readonly SemanticModel _semanticModel;
private readonly SyntaxTree _syntaxTree;
private readonly TextSpan _textSpan;
private readonly List<ClassifiedSpan> _list;
private readonly ArrayBuilder<ClassifiedSpan> _list;
private readonly CancellationToken _cancellationToken;
private readonly Func<SyntaxNode, List<ISyntaxClassifier>> _getNodeClassifiers;
private readonly Func<SyntaxToken, List<ISyntaxClassifier>> _getTokenClassifiers;
private readonly Func<SyntaxNode, ImmutableArray<ISyntaxClassifier>> _getNodeClassifiers;
private readonly Func<SyntaxToken, ImmutableArray<ISyntaxClassifier>> _getTokenClassifiers;
private readonly HashSet<ClassifiedSpan> _set;
private readonly Stack<SyntaxNodeOrToken> _pendingNodes;
......@@ -27,9 +28,9 @@ private struct Worker
Workspace workspace,
SemanticModel semanticModel,
TextSpan textSpan,
List<ClassifiedSpan> list,
Func<SyntaxNode, List<ISyntaxClassifier>> getNodeClassifiers,
Func<SyntaxToken, List<ISyntaxClassifier>> getTokenClassifiers,
ArrayBuilder<ClassifiedSpan> list,
Func<SyntaxNode, ImmutableArray<ISyntaxClassifier>> getNodeClassifiers,
Func<SyntaxToken, ImmutableArray<ISyntaxClassifier>> getTokenClassifiers,
CancellationToken cancellationToken)
{
_getNodeClassifiers = getNodeClassifiers;
......@@ -49,9 +50,9 @@ private struct Worker
Workspace workspace,
SemanticModel semanticModel,
TextSpan textSpan,
List<ClassifiedSpan> list,
Func<SyntaxNode, List<ISyntaxClassifier>> getNodeClassifiers,
Func<SyntaxToken, List<ISyntaxClassifier>> getTokenClassifiers,
ArrayBuilder<ClassifiedSpan> list,
Func<SyntaxNode, ImmutableArray<ISyntaxClassifier>> getNodeClassifiers,
Func<SyntaxToken, ImmutableArray<ISyntaxClassifier>> getTokenClassifiers,
CancellationToken cancellationToken)
{
var worker = new Worker(workspace, semanticModel, textSpan, list, getNodeClassifiers, getTokenClassifiers, cancellationToken);
......@@ -119,12 +120,15 @@ private void ClassifyNode(SyntaxNode syntax)
foreach (var classifier in _getNodeClassifiers(syntax))
{
_cancellationToken.ThrowIfCancellationRequested();
var classifications = classifier.ClassifyNode(syntax, _semanticModel, _cancellationToken);
AddClassifications(classifications);
var result = ArrayBuilder<ClassifiedSpan>.GetInstance();
classifier.AddClassifications(syntax, _semanticModel, result, _cancellationToken);
AddClassifications(result);
result.Free();
}
}
private void AddClassifications(IEnumerable<ClassifiedSpan> classifications)
private void AddClassifications(ArrayBuilder<ClassifiedSpan> classifications)
{
if (classifications != null)
{
......@@ -150,8 +154,11 @@ private void ClassifyToken(SyntaxToken syntax)
foreach (var classifier in _getTokenClassifiers(syntax))
{
_cancellationToken.ThrowIfCancellationRequested();
var classifications = classifier.ClassifyToken(syntax, _semanticModel, _cancellationToken);
AddClassifications(classifications);
var result = ArrayBuilder<ClassifiedSpan>.GetInstance();
classifier.AddClassifications(syntax, _semanticModel, result, _cancellationToken);
AddClassifications(result);
result.Free();
}
ClassifyStructuredTrivia(syntax.TrailingTrivia);
......@@ -171,4 +178,4 @@ private void ClassifyStructuredTrivia(SyntaxTriviaList triviaList)
}
}
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Classification.Classifiers;
......@@ -18,13 +18,17 @@ protected AbstractSyntaxClassificationService()
{
}
public abstract void AddLexicalClassifications(SourceText text, TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken);
public abstract void AddSyntacticClassifications(SyntaxTree syntaxTree, TextSpan textSpan, List<ClassifiedSpan> result, CancellationToken cancellationToken);
public abstract void AddLexicalClassifications(SourceText text, TextSpan textSpan, ArrayBuilder<ClassifiedSpan> result, CancellationToken cancellationToken);
public abstract void AddSyntacticClassifications(SyntaxTree syntaxTree, TextSpan textSpan, ArrayBuilder<ClassifiedSpan> result, CancellationToken cancellationToken);
public abstract IEnumerable<ISyntaxClassifier> GetDefaultSyntaxClassifiers();
public abstract ImmutableArray<ISyntaxClassifier> GetDefaultSyntaxClassifiers();
public abstract ClassifiedSpan FixClassification(SourceText text, ClassifiedSpan classifiedSpan);
public async Task AddSemanticClassificationsAsync(Document document, TextSpan textSpan, Func<SyntaxNode, List<ISyntaxClassifier>> getNodeClassifiers, Func<SyntaxToken, List<ISyntaxClassifier>> getTokenClassifiers, List<ClassifiedSpan> result, CancellationToken cancellationToken)
public async Task AddSemanticClassificationsAsync(
Document document, TextSpan textSpan,
Func<SyntaxNode, ImmutableArray<ISyntaxClassifier>> getNodeClassifiers,
Func<SyntaxToken, ImmutableArray<ISyntaxClassifier>> getTokenClassifiers,
ArrayBuilder<ClassifiedSpan> result, CancellationToken cancellationToken)
{
try
{
......@@ -37,9 +41,14 @@ public async Task AddSemanticClassificationsAsync(Document document, TextSpan te
}
}
public void AddSemanticClassifications(SemanticModel semanticModel, TextSpan textSpan, Workspace workspace, Func<SyntaxNode, List<ISyntaxClassifier>> getNodeClassifiers, Func<SyntaxToken, List<ISyntaxClassifier>> getTokenClassifiers, List<ClassifiedSpan> result, CancellationToken cancellationToken = default(CancellationToken))
public void AddSemanticClassifications(
SemanticModel semanticModel, TextSpan textSpan, Workspace workspace,
Func<SyntaxNode, ImmutableArray<ISyntaxClassifier>> getNodeClassifiers,
Func<SyntaxToken, ImmutableArray<ISyntaxClassifier>> getTokenClassifiers,
ArrayBuilder<ClassifiedSpan> result,
CancellationToken cancellationToken)
{
Worker.Classify(workspace, semanticModel, textSpan, result, getNodeClassifiers, getTokenClassifiers, cancellationToken);
}
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Classification.Classifiers;
......@@ -12,34 +12,34 @@ namespace Microsoft.CodeAnalysis.Classification
{
internal interface ISyntaxClassificationService : ILanguageService
{
IEnumerable<ISyntaxClassifier> GetDefaultSyntaxClassifiers();
ImmutableArray<ISyntaxClassifier> GetDefaultSyntaxClassifiers();
void AddLexicalClassifications(SourceText text,
TextSpan textSpan,
List<ClassifiedSpan> result,
ArrayBuilder<ClassifiedSpan> result,
CancellationToken cancellationToken);
void AddSyntacticClassifications(SyntaxTree syntaxTree,
TextSpan textSpan,
List<ClassifiedSpan> result,
ArrayBuilder<ClassifiedSpan> result,
CancellationToken cancellationToken);
Task AddSemanticClassificationsAsync(Document document,
TextSpan textSpan,
Func<SyntaxNode, List<ISyntaxClassifier>> getNodeClassifiers,
Func<SyntaxToken, List<ISyntaxClassifier>> getTokenClassifiers,
List<ClassifiedSpan> result,
Func<SyntaxNode, ImmutableArray<ISyntaxClassifier>> getNodeClassifiers,
Func<SyntaxToken, ImmutableArray<ISyntaxClassifier>> getTokenClassifiers,
ArrayBuilder<ClassifiedSpan> result,
CancellationToken cancellationToken);
void AddSemanticClassifications(
SemanticModel semanticModel,
TextSpan textSpan,
Workspace workspace,
Func<SyntaxNode, List<ISyntaxClassifier>> getNodeClassifiers,
Func<SyntaxToken, List<ISyntaxClassifier>> getTokenClassifiers,
List<ClassifiedSpan> result,
Func<SyntaxNode, ImmutableArray<ISyntaxClassifier>> getNodeClassifiers,
Func<SyntaxToken, ImmutableArray<ISyntaxClassifier>> getTokenClassifiers,
ArrayBuilder<ClassifiedSpan> result,
CancellationToken cancellationToken);
ClassifiedSpan FixClassification(SourceText text, ClassifiedSpan classifiedSpan);
}
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
namespace Microsoft.CodeAnalysis.Classification.Classifiers
......@@ -11,23 +12,23 @@ internal interface ISyntaxClassifier
/// <summary>
/// The syntax node types this classifier is able to classify
/// </summary>
IEnumerable<Type> SyntaxNodeTypes { get; }
ImmutableArray<Type> SyntaxNodeTypes { get; }
/// <summary>
/// The syntax token kinds this classifier is able to classify
/// </summary>
IEnumerable<int> SyntaxTokenKinds { get; }
ImmutableArray<int> SyntaxTokenKinds { get; }
/// <summary>
/// This method will be called for all nodes that match the types specified by the SyntaxNodeTypes property.
/// Implementations should return null (instead of an empty enumerable) if they have no classifications for the provided node.
/// </summary>
IEnumerable<ClassifiedSpan> ClassifyNode(SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken);
void AddClassifications(SyntaxNode node, SemanticModel semanticModel, ArrayBuilder<ClassifiedSpan> result, CancellationToken cancellationToken);
/// <summary>
/// This method will be called for all nodes that match the types specified by the SyntaxTokenKinds property.
/// Implementations should return null (instead of an empty enumerable) if they have no classifications for the provided token.
/// </summary>
IEnumerable<ClassifiedSpan> ClassifyToken(SyntaxToken token, SemanticModel semanticModel, CancellationToken cancellationToken);
void AddClassifications(SyntaxToken token, SemanticModel semanticModel, ArrayBuilder<ClassifiedSpan> result, CancellationToken cancellationToken);
}
}
}
\ No newline at end of file
......@@ -3,6 +3,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
......@@ -106,43 +107,39 @@ public static void PerformAction(this IExtensionManager extensionManager, object
return defaultValue;
}
public static Func<SyntaxNode, List<TExtension>> CreateNodeExtensionGetter<TExtension>(
this IExtensionManager extensionManager, IEnumerable<TExtension> extensions, Func<TExtension, IEnumerable<Type>> nodeTypeGetter)
public static Func<SyntaxNode, ImmutableArray<TExtension>> CreateNodeExtensionGetter<TExtension>(
this IExtensionManager extensionManager, IEnumerable<TExtension> extensions, Func<TExtension, ImmutableArray<Type>> nodeTypeGetter)
{
var map = new ConcurrentDictionary<Type, List<TExtension>>();
var map = new ConcurrentDictionary<Type, ImmutableArray<TExtension>>();
Func<Type, List<TExtension>> getter =
t1 =>
{
var query = from e in extensions
let types = extensionManager.PerformFunction(e, () => nodeTypeGetter(e), defaultValue: SpecializedCollections.EmptyEnumerable<Type>())
where types != null
where !types.Any() || types.Any(t2 => t1 == t2 || t1.GetTypeInfo().IsSubclassOf(t2))
select e;
ImmutableArray<TExtension> GetExtensions(Type t1)
{
var query = from e in extensions
let types = extensionManager.PerformFunction(e, () => nodeTypeGetter(e), ImmutableArray<Type>.Empty)
where !types.Any() || types.Any(t2 => t1 == t2 || t1.GetTypeInfo().IsSubclassOf(t2))
select e;
return query.ToList();
};
return query.ToImmutableArray();
}
return n => map.GetOrAdd(n.GetType(), getter);
return n => map.GetOrAdd(n.GetType(), GetExtensions);
}
public static Func<SyntaxToken, List<TExtension>> CreateTokenExtensionGetter<TExtension>(
this IExtensionManager extensionManager, IEnumerable<TExtension> extensions, Func<TExtension, IEnumerable<int>> tokenKindGetter)
public static Func<SyntaxToken, ImmutableArray<TExtension>> CreateTokenExtensionGetter<TExtension>(
this IExtensionManager extensionManager, IEnumerable<TExtension> extensions, Func<TExtension, ImmutableArray<int>> tokenKindGetter)
{
var map = new ConcurrentDictionary<int, List<TExtension>>();
Func<int, List<TExtension>> getter =
k =>
{
var query = from e in extensions
let kinds = extensionManager.PerformFunction(e, () => tokenKindGetter(e), defaultValue: SpecializedCollections.EmptyEnumerable<int>())
where kinds != null
where !kinds.Any() || kinds.Contains(k)
select e;
var map = new ConcurrentDictionary<int, ImmutableArray<TExtension>>();
ImmutableArray<TExtension> GetExtensions(int k)
{
var query = from e in extensions
let kinds = extensionManager.PerformFunction(e, () => tokenKindGetter(e), ImmutableArray<int>.Empty)
where !kinds.Any() || kinds.Contains(k)
select e;
return query.ToList();
};
return query.ToImmutableArray();
}
return t => map.GetOrAdd(t.RawKind, getter);
return t => map.GetOrAdd(t.RawKind, GetExtensions);
}
}
}
}
\ No newline at end of file
......@@ -112,7 +112,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification
End Select
End Function
Friend Sub AddLexicalClassifications(text As SourceText, textSpan As TextSpan, result As List(Of ClassifiedSpan), cancellationToken As CancellationToken)
Friend Sub AddLexicalClassifications(text As SourceText, textSpan As TextSpan, result As ArrayBuilder(Of ClassifiedSpan), cancellationToken As CancellationToken)
Dim text2 = text.ToString(textSpan)
Dim tokens = SyntaxFactory.ParseTokens(text2, initialTokenPosition:=textSpan.Start)
Worker.CollectClassifiedSpans(tokens, textSpan, result, cancellationToken)
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.Classification
Imports Microsoft.CodeAnalysis.Classification.Classifiers
......@@ -15,24 +16,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification.Classifiers
Return type.GetClassification()
End Function
Public Overridable ReadOnly Property SyntaxNodeTypes As IEnumerable(Of System.Type) Implements ISyntaxClassifier.SyntaxNodeTypes
Public Overridable ReadOnly Property SyntaxNodeTypes As ImmutableArray(Of Type) Implements ISyntaxClassifier.SyntaxNodeTypes
Get
Return Nothing
Return ImmutableArray(Of Type).Empty
End Get
End Property
Public Overridable ReadOnly Property SyntaxTokenKinds As IEnumerable(Of Integer) Implements ISyntaxClassifier.SyntaxTokenKinds
Public Overridable ReadOnly Property SyntaxTokenKinds As ImmutableArray(Of Integer) Implements ISyntaxClassifier.SyntaxTokenKinds
Get
Return Nothing
Return ImmutableArray(Of Integer).Empty
End Get
End Property
Public Overridable Function ClassifyNode(syntax As SyntaxNode, semanticModel As SemanticModel, cancellationToken As CancellationToken) As IEnumerable(Of ClassifiedSpan) Implements ISyntaxClassifier.ClassifyNode
Return Nothing
End Function
Public Overridable Sub AddClassifications(syntax As SyntaxNode, semanticModel As SemanticModel, result As ArrayBuilder(Of ClassifiedSpan), cancellationToken As CancellationToken) Implements ISyntaxClassifier.AddClassifications
End Sub
Public Overridable Function ClassifyToken(syntax As SyntaxToken, semanticModel As SemanticModel, cancellationToken As CancellationToken) As IEnumerable(Of ClassifiedSpan) Implements ISyntaxClassifier.ClassifyToken
Return Nothing
End Function
Public Overridable Sub AddClassifications(syntax As SyntaxToken, semanticModel As SemanticModel, result As ArrayBuilder(Of ClassifiedSpan), cancellationToken As CancellationToken) Implements ISyntaxClassifier.AddClassifications
End Sub
End Class
End Namespace
End Namespace
\ No newline at end of file
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.Classification
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Namespace Microsoft.CodeAnalysis.VisualBasic.Classification.Classifiers
Friend Class IdentifierNameSyntaxClassifier
......@@ -12,23 +11,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification.Classifiers
Private Const s_awaitText = "Await"
Public Overrides ReadOnly Property SyntaxNodeTypes As IEnumerable(Of Type)
Get
Return {GetType(IdentifierNameSyntax)}
End Get
End Property
Public Overrides ReadOnly Property SyntaxNodeTypes As ImmutableArray(Of Type) = ImmutableArray.Create(GetType(IdentifierNameSyntax))
Public Overrides Function ClassifyNode(syntax As SyntaxNode, semanticModel As SemanticModel, cancellationToken As CancellationToken) As IEnumerable(Of ClassifiedSpan)
Public Overrides Sub AddClassifications(syntax As SyntaxNode, semanticModel As SemanticModel, result As ArrayBuilder(Of ClassifiedSpan), cancellationToken As CancellationToken)
Dim identifierName = DirectCast(syntax, IdentifierNameSyntax)
Dim identifier = identifierName.Identifier
If CaseInsensitiveComparison.Equals(identifier.ValueText, s_awaitText) Then
Dim symbolInfo = semanticModel.GetSymbolInfo(identifier)
If symbolInfo.GetAnySymbol() Is Nothing Then
Return SpecializedCollections.SingletonEnumerable(New ClassifiedSpan(ClassificationTypeNames.Keyword, identifier.Span))
result.Add(New ClassifiedSpan(ClassificationTypeNames.Keyword, identifier.Span))
Return
End If
End If
Return MyBase.ClassifyNode(syntax, semanticModel, cancellationToken)
End Function
End Sub
End Class
End Namespace
\ No newline at end of file
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.Classification
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
......@@ -8,31 +9,27 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification.Classifiers
Friend Class ImportAliasClauseSyntaxClassifier
Inherits AbstractSyntaxClassifier
Public Overrides ReadOnly Property SyntaxNodeTypes As IEnumerable(Of Type)
Get
Return {GetType(ImportAliasClauseSyntax)}
End Get
End Property
Public Overrides ReadOnly Property SyntaxNodeTypes As ImmutableArray(Of Type) = ImmutableArray.Create(GetType(ImportAliasClauseSyntax))
Public Overrides Function ClassifyNode(syntax As SyntaxNode, semanticModel As SemanticModel, cancellationToken As CancellationToken) As IEnumerable(Of ClassifiedSpan)
Return ClassifyImportAliasClauseSyntax(DirectCast(syntax, ImportAliasClauseSyntax), semanticModel, cancellationToken)
End Function
Public Overrides Sub AddClassifications(syntax As SyntaxNode, semanticModel As SemanticModel, result As ArrayBuilder(Of ClassifiedSpan), cancellationToken As CancellationToken)
ClassifyImportAliasClauseSyntax(DirectCast(syntax, ImportAliasClauseSyntax), semanticModel, result, cancellationToken)
End Sub
Private Function ClassifyImportAliasClauseSyntax(
Private Sub ClassifyImportAliasClauseSyntax(
node As ImportAliasClauseSyntax,
semanticModel As SemanticModel,
cancellationToken As CancellationToken) As IEnumerable(Of ClassifiedSpan)
result As ArrayBuilder(Of ClassifiedSpan),
cancellationToken As CancellationToken)
Dim symbolInfo = semanticModel.GetTypeInfo(DirectCast(node.Parent, SimpleImportsClauseSyntax).Name, cancellationToken)
If symbolInfo.Type IsNot Nothing Then
Dim classification = GetClassificationForType(symbolInfo.Type)
If classification IsNot Nothing Then
Dim token = node.Identifier
Return SpecializedCollections.SingletonEnumerable(New ClassifiedSpan(token.Span, classification))
result.Add(New ClassifiedSpan(token.Span, classification))
Return
End If
End If
Return Nothing
End Function
End Sub
End Class
End Namespace
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.Classification
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Classification.Classifiers
Friend Class NameSyntaxClassifier
Inherits AbstractSyntaxClassifier
Public Overrides ReadOnly Property SyntaxNodeTypes As IEnumerable(Of Type)
Get
Return {GetType(NameSyntax), GetType(ModifiedIdentifierSyntax)}
End Get
End Property
Public Overrides ReadOnly Property SyntaxNodeTypes As ImmutableArray(Of Type) = ImmutableArray.Create(GetType(NameSyntax), GetType(ModifiedIdentifierSyntax))
Public Overrides Function ClassifyNode(
Public Overrides Sub AddClassifications(
syntax As SyntaxNode,
semanticModel As SemanticModel,
cancellationToken As CancellationToken) As IEnumerable(Of ClassifiedSpan)
result As ArrayBuilder(Of ClassifiedSpan),
cancellationToken As CancellationToken)
Dim nameSyntax = TryCast(syntax, NameSyntax)
If nameSyntax IsNot Nothing Then
Return ClassifyNameSyntax(
nameSyntax,
DirectCast(semanticModel, SemanticModel),
cancellationToken)
ClassifyNameSyntax(nameSyntax, semanticModel, result, cancellationToken)
Return
End If
Dim modifiedIdentifier = TryCast(syntax, ModifiedIdentifierSyntax)
If modifiedIdentifier IsNot Nothing Then
Return ClassifyModifiedIdentifier(
modifiedIdentifier,
DirectCast(semanticModel, SemanticModel),
cancellationToken)
ClassifyModifiedIdentifier(modifiedIdentifier, semanticModel, result, cancellationToken)
Return
End If
End Sub
Return SpecializedCollections.EmptyEnumerable(Of ClassifiedSpan)()
End Function
Private Function ClassifyNameSyntax(
Private Sub ClassifyNameSyntax(
node As NameSyntax,
semanticModel As SemanticModel,
cancellationToken As CancellationToken) As IEnumerable(Of ClassifiedSpan)
result As ArrayBuilder(Of ClassifiedSpan),
cancellationToken As CancellationToken)
Dim symbolInfo = semanticModel.GetSymbolInfo(node, cancellationToken)
Dim symbol = symbolInfo.Symbol
......@@ -65,7 +57,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification.Classifiers
Case CandidateReason.Inaccessible
' If we couldn't bind to a constructor, still classify the type if its accessible
If firstSymbol.IsConstructor() AndAlso SemanticModel.IsAccessible(node.SpanStart, firstSymbol.ContainingType) Then
If firstSymbol.IsConstructor() AndAlso semanticModel.IsAccessible(node.SpanStart, firstSymbol.ContainingType) Then
symbol = firstSymbol
End If
End Select
......@@ -78,14 +70,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification.Classifiers
' If node is member access or qualified name with explicit New on the right side, we should classify New as a keyword.
If node.IsNewOnRightSideOfDotOrBang() Then
Dim token = GetNameToken(node)
Return SpecializedCollections.SingletonEnumerable(
New ClassifiedSpan(token.Span, ClassificationTypeNames.Keyword))
result.Add(New ClassifiedSpan(token.Span, ClassificationTypeNames.Keyword))
Return
Else
' We bound to a constructor, but we weren't something like the 'New' in 'X.New'.
' This can happen when we're actually just binding the full node 'X.New'. In this
' case, don't return anything for this full node. We'll end up hitting the
' 'New' node as the worker walks down, and we'll classify it then.
Return Nothing
Return
End If
End If
End If
......@@ -95,13 +87,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification.Classifiers
Dim classification = GetClassificationForType(type)
If classification IsNot Nothing Then
Dim token = GetNameToken(node)
Return SpecializedCollections.SingletonEnumerable(New ClassifiedSpan(token.Span, classification))
result.Add(New ClassifiedSpan(token.Span, classification))
Return
End If
End If
If symbol.IsMyNamespace(semanticModel.Compilation) Then
Return SpecializedCollections.SingletonEnumerable(
New ClassifiedSpan(GetNameToken(node).Span, ClassificationTypeNames.Keyword))
result.Add(New ClassifiedSpan(GetNameToken(node).Span, ClassificationTypeNames.Keyword))
Return
End If
Else
' Okay, it doesn't bind to anything.
......@@ -113,35 +106,32 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification.Classifiers
semanticModel.SyntaxTree.IsExpressionContext(token.SpanStart, cancellationToken, semanticModel) Then
' Optimistically classify "From" as a keyword in expression contexts
Return SpecializedCollections.SingletonEnumerable(
New ClassifiedSpan(token.Span, ClassificationTypeNames.Keyword))
result.Add(New ClassifiedSpan(token.Span, ClassificationTypeNames.Keyword))
Return
ElseIf token.HasMatchingText(SyntaxKind.AsyncKeyword) OrElse
token.HasMatchingText(SyntaxKind.IteratorKeyword) Then
' Optimistically classify "Async" or "Iterator" as a keyword in expression contexts
If semanticModel.SyntaxTree.IsExpressionContext(token.SpanStart, cancellationToken, semanticModel) Then
Return SpecializedCollections.SingletonEnumerable(
New ClassifiedSpan(token.Span, ClassificationTypeNames.Keyword))
result.Add(New ClassifiedSpan(token.Span, ClassificationTypeNames.Keyword))
Return
End If
End If
End If
End If
End Sub
Return Nothing
End Function
Private Function ClassifyModifiedIdentifier(
modifiedIdentifier As ModifiedIdentifierSyntax,
semanticModel As SemanticModel,
cancellationToken As CancellationToken
) As IEnumerable(Of ClassifiedSpan)
Private Sub ClassifyModifiedIdentifier(
modifiedIdentifier As ModifiedIdentifierSyntax,
semanticModel As SemanticModel,
result As ArrayBuilder(Of ClassifiedSpan),
cancellationToken As CancellationToken)
If modifiedIdentifier.ArrayBounds IsNot Nothing OrElse
modifiedIdentifier.ArrayRankSpecifiers.Count > 0 OrElse
modifiedIdentifier.Nullable.Kind <> SyntaxKind.None Then
Return SpecializedCollections.EmptyEnumerable(Of ClassifiedSpan)()
Return
End If
If modifiedIdentifier.IsParentKind(SyntaxKind.VariableDeclarator) AndAlso
......@@ -155,15 +145,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification.Classifiers
token.HasMatchingText(SyntaxKind.IteratorKeyword) Then
' Optimistically classify "Async" or "Iterator" as a keyword
Return SpecializedCollections.SingletonEnumerable(
New ClassifiedSpan(token.Span, ClassificationTypeNames.Keyword))
result.Add(New ClassifiedSpan(token.Span, ClassificationTypeNames.Keyword))
Return
End If
End If
End If
Return SpecializedCollections.EmptyEnumerable(Of ClassifiedSpan)()
End Function
End Sub
Private Function GetNameToken(node As NameSyntax) As SyntaxToken
Select Case node.Kind
......@@ -177,6 +164,5 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification.Classifiers
Throw New NotSupportedException()
End Select
End Function
End Class
End Namespace
End Namespace
\ No newline at end of file
......@@ -14,21 +14,21 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification
Partial Friend Class VisualBasicSyntaxClassificationService
Inherits AbstractSyntaxClassificationService
Private Shared ReadOnly s_defaultSyntaxClassifiers As IEnumerable(Of ISyntaxClassifier) =
Private Shared ReadOnly s_defaultSyntaxClassifiers As ImmutableArray(Of ISyntaxClassifier) =
ImmutableArray.Create(Of ISyntaxClassifier)(
New NameSyntaxClassifier(),
New ImportAliasClauseSyntaxClassifier(),
New IdentifierNameSyntaxClassifier())
Public Overrides Function GetDefaultSyntaxClassifiers() As IEnumerable(Of ISyntaxClassifier)
Public Overrides Function GetDefaultSyntaxClassifiers() As ImmutableArray(Of ISyntaxClassifier)
Return s_defaultSyntaxClassifiers
End Function
Public Overrides Sub AddLexicalClassifications(text As SourceText, textSpan As TextSpan, result As List(Of ClassifiedSpan), cancellationToken As CancellationToken)
Public Overrides Sub AddLexicalClassifications(text As SourceText, textSpan As TextSpan, result As ArrayBuilder(Of ClassifiedSpan), cancellationToken As CancellationToken)
ClassificationHelpers.AddLexicalClassifications(text, textSpan, result, cancellationToken)
End Sub
Public Overrides Sub AddSyntacticClassifications(syntaxTree As SyntaxTree, textSpan As TextSpan, result As List(Of ClassifiedSpan), cancellationToken As CancellationToken)
Public Overrides Sub AddSyntacticClassifications(syntaxTree As SyntaxTree, textSpan As TextSpan, result As ArrayBuilder(Of ClassifiedSpan), cancellationToken As CancellationToken)
Dim root = syntaxTree.GetRoot(cancellationToken)
Worker.CollectClassifiedSpans(root, textSpan, result, cancellationToken)
End Sub
......@@ -37,4 +37,4 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification
Return ClassificationHelpers.AdjustStaleClassification(text, classifiedSpan)
End Function
End Class
End Namespace
End Namespace
\ No newline at end of file
......@@ -12,7 +12,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification
Inherits AbstractClassificationService
Public Overrides Sub AddLexicalClassifications(text As SourceText, textSpan As TextSpan, result As List(Of ClassifiedSpan), cancellationToken As CancellationToken)
ClassificationHelpers.AddLexicalClassifications(text, textSpan, result, cancellationToken)
Dim temp = ArrayBuilder(Of ClassifiedSpan).GetInstance()
ClassificationHelpers.AddLexicalClassifications(text, textSpan, temp, cancellationToken)
AddRange(temp, result)
temp.Free()
End Sub
Public Overrides Function AdjustStaleClassification(text As SourceText, classifiedSpan As ClassifiedSpan) As ClassifiedSpan
......
......@@ -7,13 +7,13 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Classification
Partial Friend Class Worker
Private ReadOnly _list As List(Of ClassifiedSpan)
Private ReadOnly _list As ArrayBuilder(Of ClassifiedSpan)
Private ReadOnly _textSpan As TextSpan
Private ReadOnly _docCommentClassifier As DocumentationCommentClassifier
Private ReadOnly _xmlClassifier As XmlClassifier
Private ReadOnly _cancellationToken As CancellationToken
Private Sub New(textSpan As TextSpan, list As List(Of ClassifiedSpan), cancellationToken As CancellationToken)
Private Sub New(textSpan As TextSpan, list As ArrayBuilder(Of ClassifiedSpan), cancellationToken As CancellationToken)
_textSpan = textSpan
_list = list
_docCommentClassifier = New DocumentationCommentClassifier(Me)
......@@ -22,7 +22,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification
End Sub
Friend Shared Sub CollectClassifiedSpans(
tokens As IEnumerable(Of SyntaxToken), textSpan As TextSpan, list As List(Of ClassifiedSpan), cancellationToken As CancellationToken)
tokens As IEnumerable(Of SyntaxToken), textSpan As TextSpan, list As ArrayBuilder(Of ClassifiedSpan), cancellationToken As CancellationToken)
Dim worker = New Worker(textSpan, list, cancellationToken)
For Each token In tokens
......@@ -31,7 +31,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification
End Sub
Friend Shared Sub CollectClassifiedSpans(
node As SyntaxNode, textSpan As TextSpan, list As List(Of ClassifiedSpan), cancellationToken As CancellationToken)
node As SyntaxNode, textSpan As TextSpan, list As ArrayBuilder(Of ClassifiedSpan), cancellationToken As CancellationToken)
Dim worker = New Worker(textSpan, list, cancellationToken)
worker.ClassifyNode(node)
End Sub
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册