c#


Determining if the current span is an attribute deleration using Roslyn APIs


I'm building a visual studio extension for coloring various language constructs using Roslyn APIs, I want to change the color of attribute declarations, like Asp.Net MVC [Require] attribute for example. I have access to SyntaxNode and ISymbol, my current check to find out if the current node is an attribute declaration is:
public static bool IsCSharpAttributeSyntaxKind(this SyntaxNode node)
{
return node.Kind() == SyntaxKind.Attribute;
}
And use it like:
if (node.IsCSharpAttributeSyntaxKind())
{
classificationTypeDictionary.TryGetValue(ColorCoderClassificationName.Attribute, out IClassificationType classificationValue);
return new TagSpan<IClassificationTag>(new SnapshotSpan(snapshot, span.TextSpan.Start, span.TextSpan.Length), new ClassificationTag(classificationValue));
}
I get the Roslyn info by:
public IEnumerable<ITagSpan<IClassificationTag>> GetTags(NormalizedSnapshotSpanCollection spans)
{
if (spans.Count == 0)
{
return Enumerable.Empty<ITagSpan<IClassificationTag>>();
}
var cacheStatus = _colorCoderTaggerServices.ManageCache(ref _cache, spans, _buffer);
if (cacheStatus == CacheState.NotResolved)
{
return Enumerable.Empty<ITagSpan<IClassificationTag>>();
}
return _colorCoderTaggerServices.GetClassificationTags(_cache, spans, classificationTypeDictionary);
}
Also the method for retrieving the identifiers:
internal IEnumerable<ClassifiedSpan> GetIdentifiersInSpans(Workspace workspace, SemanticModel model, NormalizedSnapshotSpanCollection spans)
{
var comparer = StringComparer.InvariantCultureIgnoreCase;
var classifiedSpans = spans.SelectMany(span =>
{
var textSpan = TextSpan.FromBounds(span.Start, span.End);
return Classifier.GetClassifiedSpans(model, textSpan, workspace);
});
return classifiedSpans.Where(c => comparer.Compare(c.ClassificationType, "identifier") == 0);
}
I don't know if the attribute declaration is part of the identifiers that I return form GetIdentifiersInSpans, but I did it without the Where with no success.
And for my caching mechanism I use:
public class ProviderCache
{
public Workspace Workspace { get; private set; }
public Document Document { get; private set; }
public SemanticModel SemanticModel { get; private set; }
public SyntaxNode SyntaxRoot { get; private set; }
public ITextSnapshot Snapshot { get; private set; }
public static async Task<ProviderCache> Resolve(ITextBuffer buffer, ITextSnapshot snapshot)
{
var workspace = buffer.GetWorkspace();
var document = snapshot.GetOpenDocumentInCurrentContextWithChanges();
if (document == null)
{
return null;
}
var semanticModel = await document.GetSemanticModelAsync().ConfigureAwait(false);
var syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false);
return new ProviderCache
{
Workspace = workspace,
Document = document,
SemanticModel = semanticModel,
SyntaxRoot = syntaxRoot,
Snapshot = snapshot
};
}
}
I've tried various other things but none of them worked, I believe I miss something else here. I understand that my question is not good enough, I'm sorry for that, that's because I lack the terminology to ask a good question, and visual studio's extensibility frameworks are usually under-documented, if you need any more detail please let me know.
You don't mention how you are getting the roslyn info in your extension, but because you mention SyntaxNode Workspace and SemanticModel in your code samples, I assume you can get the current Document. The approach I would take is to get the root node for the document you are attempting to classify. A good starting place would be somthing like the code below and this VSSDK sample.
public static async Task<IEnumerable<ClassificationSpan>> ClassifyAttributes(Document currentDocument, CancellationToken token)
{
// Get all attribute nodes in the current document
var rootNode = await currentDocument.GetSyntaxRootAsync(token).ConfigureAwait(false);
var attributesInDocument = from descendantNode in rootNode.DescendantNodesAndSelf()
where descendantNode.IsKind(SyntaxKind.Attribute)
select (AttributeSyntax)descendantNode;
// Check to see if the attribute binds to a type (I assume you do not want to classify attributes with errors)
var model = await currentDocument.GetSemanticModelAsync(token).ConfigureAwait(false);
var attributeSpans = from attributeNode in attributesInDocument
let typeInfo = model.GetTypeInfo(attributeNode, token)
where typeInfo.Type.Kind != SymbolKind.ErrorType
select new ClassificationSpan(attributeNode.Span, _classificationType);
// returns a set of ClassifiedSpans that your extensions classifer will colorize
return attributeSpans;
}

Related Links

XSD cant create class from XML based on inherited classes
My stored procedure returns something, but sqlDataAdapter.Fill leaves datatable empty
Is it OK to remove .property statements from ILAsm files for production use?
Printing bitmaps in C# - hasmorepages issue
NHibernate 3.1 Query equals
How to do XSLT 2.0 transformation with C# [duplicate]
Cannot return proper model into view when doing a join linq query
Generate random bytes for TripleDES key C#
Question regarding common class
C# Assign Name for Try-Catch Error
How to compare two objects excluding a single object property?
Setting to DataContext not reflecting in Listbox
TFS 2010, cannot get files to workspace, The server returned content type text/html, which is not supported
Can't get ValueInjecter to map COM objects
WPF: Naming controls generated during binding for UI Automation Tests
NetDataContractSerializer and assembly versions mismatch

Categories

HOME
classification
excel-formula
skype-for-business
indexing
compression
display
python-requests
bigtable
magento-1.9.2.1
crm
where
download
checkpoint
opacity
webpack-dev-server
ionic-native
normals
distinct
cakephp-2.0
jinja2
lambda-calculus
template10
glibc
keystone
fibonacci
klipfolio
gnu-screen
matlab-gui
android-cursorloader
checkmarx
arp
andengine
boost-log
jql
unity3d-5
javax
gitosis
lighting
scip
dotnetnuke-module
jslider
aspose.pdf
wicket-tester
delphi-xe
aspnetboilerplate
directadmin
peerjs
taleo
openxava
google-cloud-shell
seyren
hellosign
dmalloc
petapoco
bipartite
breadcrumbs
blackberry-webworks
visual-web-developer
laterjs
sqlxml
custom-build-step
skbio
wonderware
encode
android-facebook
gulp-cdnizer
self-join
page-flipping
log4cxx
bootstrap-tabs
tess4j
firewire
stereotype
genome
httpmodule
perfect-scrollbar
unityvs
qf-test
react-os
indic
triplestore
xpand
cs193p
debuggervisualizer
dateadd
code-smell
lettuce
jsmpp
farpoint-spread
iwork
slimscroll
android-jack-and-jill
ekevent
mobile-robots
grape-api
octokit
angularjs-select2
azure-scheduler
simplemembership
helicontech
stl-algorithm
maven-eclipse-plugin
apache-commons-email
openwrap
execjs
response-time
cpack
conditional-operator
web-widget
manuals
atmega16

Resources

Encrypt Message



code
soft
python
ios
c
html
jquery
cloud
mobile