public SyntaxNode GetNode(int position, bool includeTrivia, bool deep) { if (Compilation == null || Compilation.FullSpan.Contains(position) == false) { return(null); } var node = Compilation.FindNode(new TextSpan(position, 0), includeTrivia, deep); SeparatedSyntaxList <VariableDeclaratorSyntax> variables; if (node.IsKind(SyntaxKind.FieldDeclaration) || node.IsKind(SyntaxKind.EventFieldDeclaration)) { variables = (node as BaseFieldDeclarationSyntax).Declaration.Variables; } else if (node.IsKind(SyntaxKind.VariableDeclaration)) { variables = (node as VariableDeclarationSyntax).Variables; } else if (node.IsKind(SyntaxKind.LocalDeclarationStatement)) { variables = (node as LocalDeclarationStatementSyntax).Declaration.Variables; } else { return(node); } foreach (var variable in variables) { if (variable.Span.Contains(position)) { return(node); } } return(node.FullSpan.Contains(position) ? node : null); }
/// <summary> /// Obtains an <see cref="IClassificationType"/> object based on the given span. /// Returns null if no classification is found for the given span. /// </summary> /// <param name="currentSpan">The span to be processed.</param> /// <param name="documentRoot">The root of the document. Needed to find the parent node of the proccessed span.</param> /// <param name="semanticModel">The semantic model of the current document. Needed to find the symbols of the proccessed span.</param> /// <returns>An <see cref="IClassificationType"/> based on the given span. Null if no classification is found.</returns> private IClassificationType GetClassificationType(ClassifiedSpan currentSpan, CompilationUnitSyntax documentRoot, SemanticModel semanticModel) { IClassificationType classificationType = null; // Get the innermost span, which corresponds to the span being proccessed var node = documentRoot.FindNode(currentSpan.TextSpan, true, true); var nodeKind = node.Kind(); var token = node.FindToken(currentSpan.TextSpan.Start); var spanType = currentSpan.ClassificationType; if (spanType.Contains("name")) { classificationType = GetIdentifierClassification(token, semanticModel); } else { switch (spanType) { case "keyword": classificationType = GetKeywordClassification(token); break; case "identifier": { classificationType = GetIdentifierClassification(token); if (classificationType != null) { break; } if (IsChildOfKind(token, SyntaxKind.NamespaceDeclaration)) { classificationType = _classifications[ClassificationTypes.Identifiers.NamespaceIdentifier]; } break; } case "operator": { if (token.IsKind(SyntaxKind.DotToken)) { if (IsChildOfKind(token, SyntaxKind.NamespaceDeclaration)) { classificationType = _classifications[ClassificationTypes.Identifiers.NamespaceIdentifier]; } } break; } } } return(classificationType); }
/// <remarks>These are tidied up so we can add as many GlobalImports as we want when building compilations</remarks> private CSharpSyntaxNode TidyUsings(CompilationUnitSyntax compilationUnitSyntax) { var diagnostics = _semanticModel.GetDiagnostics().ToList(); var unusedUsings = diagnostics .Where(d => d.Id == UnusedUsingDiagnosticId) .Select(d => compilationUnitSyntax.FindNode(d.Location.SourceSpan)) .OfType <UsingDirectiveSyntax>() .ToList(); var nodesWithUnresolvedTypes = diagnostics .Where(d => d.Id == UnresolvedTypeOrNamespaceDiagnosticId && d.Location.IsInSource) .Select(d => compilationUnitSyntax.FindNode(d.Location.SourceSpan)) .ToLookup(d => d.GetAncestor <UsingDirectiveSyntax>()); unusedUsings = unusedUsings.Except(nodesWithUnresolvedTypes.Select(g => g.Key)).ToList(); if (!nodesWithUnresolvedTypes[null].Any() && unusedUsings.Any()) { compilationUnitSyntax = compilationUnitSyntax.RemoveNodes(unusedUsings, SyntaxRemoveOptions.KeepNoTrivia); } return(compilationUnitSyntax); }
static void GetAttributeNotationSpan(ITextSnapshot snapshot, List <ClassificationSpan> result, TextSpan textSpan, CompilationUnitSyntax unitCompilation) { var spanNode = unitCompilation.FindNode(textSpan, true, false); if (spanNode.HasLeadingTrivia != false && spanNode.GetLeadingTrivia().FullSpan.Contains(textSpan) != false) { return; } switch (spanNode.Kind()) { case SyntaxKind.AttributeList: case SyntaxKind.AttributeArgumentList: result.Add(CreateClassificationSpan(snapshot, textSpan, _Classifications.AttributeNotation)); return; } }
/// <remarks>These are tidied up so we can add as many GlobalImports as we want when building compilations</remarks> private CSharpSyntaxNode TidyUsings(CompilationUnitSyntax compilationUnitSyntax) { var diagnostics = _semanticModel.GetDiagnostics().ToList(); var unusedUsings = diagnostics .Where(d => d.Id == UnusedUsingDiagnosticId) .Select(d => compilationUnitSyntax.FindNode(d.Location.SourceSpan)) .OfType <UsingDirectiveSyntax>() .ToList(); if (diagnostics.All(d => d.Id != UnresolvedTypeOrNamespaceDiagnosticId) && unusedUsings.Any()) { compilationUnitSyntax = compilationUnitSyntax.RemoveNodes(unusedUsings, SyntaxRemoveOptions.KeepNoTrivia); } return(compilationUnitSyntax); }
static ITagSpan <IClassificationTag> GetAttributeNotationSpan(ITextSnapshot snapshot, TextSpan textSpan, CompilationUnitSyntax unitCompilation) { var spanNode = unitCompilation.FindNode(textSpan, true, false); if (spanNode.HasLeadingTrivia && spanNode.GetLeadingTrivia().FullSpan.Contains(textSpan)) { return(null); } switch (spanNode.Kind()) { case SyntaxKind.AttributeArgument: case SyntaxKind.AttributeList: case SyntaxKind.AttributeArgumentList: return(CreateClassificationSpan(snapshot, textSpan, _Classifications.AttributeNotation)); } return(null); }
public static CompilationUnitSyntax ExtractClass(this CompilationUnitSyntax root, TextSpan span) { var node = root.FindNode(span); var typeDecl = node as BaseTypeDeclarationSyntax; if (typeDecl == null) { return(null); } var member = node as MemberDeclarationSyntax; var namespaceDeclarations = typeDecl .Ancestors() .OfType <NamespaceDeclarationSyntax>() .Select(n => (member = n.WithMembers(SyntaxFactory.SingletonList(member)))); var namespaceDecl = namespaceDeclarations.LastOrDefault() as MemberDeclarationSyntax; if (namespaceDecl == null) { namespaceDecl = typeDecl; } var usings = root .DescendantNodesAndSelf(n => true) .OfType <UsingDirectiveSyntax>() .Select(u => u.WithAdditionalAnnotations(Simplifier.Annotation)); var extAlias = root .ChildNodes() .OfType <ExternAliasDirectiveSyntax>(); var ret = SyntaxFactory.CompilationUnit( SyntaxFactory.List(extAlias), SyntaxFactory.List(usings), SyntaxFactory.List <AttributeListSyntax>(), SyntaxFactory.SingletonList(namespaceDecl) ); return(ret); }
bool UpdateSemanticModel() { try { _Document = View.TextSnapshot.GetOpenDocumentInCurrentContextWithChanges(); _SemanticModel = _Document.GetSemanticModelAsync().Result; _Compilation = _SemanticModel.SyntaxTree.GetCompilationUnitRoot(); } catch (NullReferenceException) { _Node = null; _Token = default; _Trivia = default; _LineComment = default; return(false); } int pos = View.Selection.Start.Position; try { _Token = _Compilation.FindToken(pos, true); } catch (ArgumentOutOfRangeException) { _Node = null; _Token = default; _Trivia = default; _LineComment = default; return(false); } var triviaList = _Token.HasLeadingTrivia ? _Token.LeadingTrivia : _Token.HasTrailingTrivia ? _Token.TrailingTrivia : default; if (triviaList.Equals(SyntaxTriviaList.Empty) == false && triviaList.FullSpan.Contains(pos)) { _Trivia = triviaList.FirstOrDefault(i => i.Span.Contains(pos)); _LineComment = triviaList.FirstOrDefault(i => i.IsLineComment()); } else { _Trivia = _LineComment = default; } _Node = _Compilation.FindNode(_Token.Span, true, true); return(true); }
static ITagSpan <IClassificationTag> ClassifyPunctuation(TextSpan itemSpan, ITextSnapshot snapshot, SemanticModel semanticModel, CompilationUnitSyntax unitCompilation) { if (HighlightOptions.AllBraces == false) { return(null); } var s = snapshot.GetText(itemSpan.Start, itemSpan.Length)[0]; if (s == '{' || s == '}') { var node = unitCompilation.FindNode(itemSpan, true, true); if (node is BaseTypeDeclarationSyntax == false && node is ExpressionSyntax == false && node is NamespaceDeclarationSyntax == false && node.Kind() != SyntaxKind.SwitchStatement && (node = node.Parent) == null) { return(null); } var type = ClassifySyntaxNode(node, node is ExpressionSyntax ? HighlightOptions.MemberBraceTags : HighlightOptions.MemberDeclarationBraceTags, HighlightOptions.KeywordBraceTags); if (type != null) { return(CreateClassificationSpan(snapshot, itemSpan, type)); } } else if ((s == '(' || s == ')') && HighlightOptions.AllParentheses) { var node = unitCompilation.FindNode(itemSpan, true, true); switch (node.Kind()) { case SyntaxKind.CastExpression: return(HighlightOptions.KeywordBraceTags.TypeCast != null && semanticModel.GetSymbolInfo(((CastExpressionSyntax)node).Type).Symbol != null ? CreateClassificationSpan(snapshot, itemSpan, HighlightOptions.KeywordBraceTags.TypeCast) : null); case SyntaxKind.ParenthesizedExpression: return((HighlightOptions.KeywordBraceTags.TypeCast != null && node.ChildNodes().FirstOrDefault().IsKind(SyntaxKind.AsExpression) && semanticModel.GetSymbolInfo(((BinaryExpressionSyntax)node.ChildNodes().First()).Right).Symbol != null) ? CreateClassificationSpan(snapshot, itemSpan, HighlightOptions.KeywordBraceTags.TypeCast) : null); case SyntaxKind.SwitchStatement: case SyntaxKind.SwitchSection: case SyntaxKind.IfStatement: case SyntaxKind.ElseClause: case (SyntaxKind)9023: // positional pattern clause return(CreateClassificationSpan(snapshot, itemSpan, HighlightOptions.KeywordBraceTags.Branching)); case SyntaxKind.ForStatement: case SyntaxKind.ForEachStatement: case SyntaxKind.ForEachVariableStatement: case SyntaxKind.WhileStatement: case SyntaxKind.DoStatement: return(CreateClassificationSpan(snapshot, itemSpan, HighlightOptions.KeywordBraceTags.Loop)); case SyntaxKind.UsingStatement: case SyntaxKind.FixedStatement: case SyntaxKind.LockStatement: case SyntaxKind.UnsafeStatement: case SyntaxKind.TryStatement: case SyntaxKind.CatchDeclaration: case SyntaxKind.CatchClause: case SyntaxKind.CatchFilterClause: case SyntaxKind.FinallyClause: return(CreateClassificationSpan(snapshot, itemSpan, HighlightOptions.KeywordBraceTags.Resource)); case SyntaxKind.ParenthesizedVariableDesignation: return(CreateClassificationSpan(snapshot, itemSpan, node.Parent.IsKind((SyntaxKind)9027) ? HighlightOptions.KeywordBraceTags.Branching : HighlightOptions.MemberBraceTags.Constructor)); case SyntaxKind.TupleExpression: case SyntaxKind.TupleType: return(CreateClassificationSpan(snapshot, itemSpan, HighlightOptions.MemberBraceTags.Constructor)); case SyntaxKind.CheckedExpression: case SyntaxKind.UncheckedExpression: return(CreateClassificationSpan(snapshot, itemSpan, HighlightOptions.KeywordBraceTags.TypeCast)); } if (HighlightOptions.MemberBraceTags.Constructor != null) { // SpecialHighlightOptions.ParameterBrace or SpecialHighlightOptions.SpecialPunctuation is ON node = (node as BaseArgumentListSyntax ?? node as BaseParameterListSyntax ?? (CSharpSyntaxNode)(node as CastExpressionSyntax) )?.Parent; if (node != null) { var type = ClassifySyntaxNode(node, HighlightOptions.MemberBraceTags, HighlightOptions.KeywordBraceTags); if (type != null) { return(CreateClassificationSpan(snapshot, itemSpan, type)); } } } } else if (s == '[' || s == ']') { // highlight attribute annotation var node = unitCompilation.FindNode(itemSpan, true, false); switch (node.Kind()) { case SyntaxKind.AttributeList: return(CreateClassificationSpan(snapshot, node.Span, _Classifications.AttributeNotation)); case SyntaxKind.ArrayRankSpecifier: return(node.Parent.Parent.IsKind(SyntaxKind.ArrayCreationExpression) ? CreateClassificationSpan(snapshot, itemSpan, HighlightOptions.MemberBraceTags.Constructor) : null); case SyntaxKind.ImplicitStackAllocArrayCreationExpression: return(CreateClassificationSpan(snapshot, itemSpan, HighlightOptions.MemberBraceTags.Constructor)); case SyntaxKind.Argument: return(((ArgumentSyntax)node).Expression.IsKind(SyntaxKind.ImplicitStackAllocArrayCreationExpression) ? CreateClassificationSpan(snapshot, itemSpan, HighlightOptions.MemberBraceTags.Constructor) : null); } } return(null); }
public static SyntaxNode GetSyntaxNode(this Diagnostic diagnostic, CompilationUnitSyntax root) { return(root.FindNode(diagnostic.Location.SourceSpan)); }
static void ClassifyPunctuation(TextSpan itemSpan, ITextSnapshot snapshot, List <ClassificationSpan> result, SemanticModel semanticModel, CompilationUnitSyntax unitCompilation) { if (Config.Instance.SpecialHighlightOptions.HasAnyFlag(SpecialHighlightOptions.AllBraces) == false) { return; } var s = snapshot.GetText(itemSpan.Start, itemSpan.Length)[0]; if (s == '{' || s == '}') { var node = unitCompilation.FindNode(itemSpan, true, true); if (node is BaseTypeDeclarationSyntax == false && node is ExpressionSyntax == false && node is NamespaceDeclarationSyntax == false && node.Kind() != SyntaxKind.SwitchStatement && (node = node.Parent) == null) { return; } var type = ClassifySyntaxNode(node); if (type != null) { if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.SpecialPunctuation)) { result.Add(CreateClassificationSpan(snapshot, itemSpan, _GeneralClassifications.SpecialPunctuation)); } if (type == _GeneralClassifications.BranchingKeyword) { if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.BranchBrace)) { result.Add(CreateClassificationSpan(snapshot, itemSpan, type)); } return; } if (type == _GeneralClassifications.LoopKeyword) { if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.LoopBrace)) { result.Add(CreateClassificationSpan(snapshot, itemSpan, type)); } return; } if (type == _Classifications.ResourceKeyword) { if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.ResourceBrace)) { result.Add(CreateClassificationSpan(snapshot, itemSpan, type)); } return; } if (node is ExpressionSyntax == false) { result.Add(CreateClassificationSpan(snapshot, itemSpan, _Classifications.DeclarationBrace)); } if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.DeclarationBrace)) { result.Add(CreateClassificationSpan(snapshot, itemSpan, type)); } } } else if ((s == '(' || s == ')') && Config.Instance.SpecialHighlightOptions.HasAnyFlag(SpecialHighlightOptions.ParameterBrace | SpecialHighlightOptions.BranchBrace | SpecialHighlightOptions.LoopBrace | SpecialHighlightOptions.ResourceBrace)) { var node = unitCompilation.FindNode(itemSpan, true, true); switch (node.Kind()) { case SyntaxKind.CastExpression: if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.ParameterBrace) == false) { return; } var symbol = semanticModel.GetSymbolInfo((node as CastExpressionSyntax).Type).Symbol; if (symbol == null) { return; } IClassificationType type = null; switch (symbol.Kind) { case SymbolKind.NamedType: switch ((symbol as INamedTypeSymbol).TypeKind) { case TypeKind.Class: type = _Classifications.ClassName; break; case TypeKind.Interface: type = _Classifications.InterfaceName; break; case TypeKind.Struct: type = _Classifications.StructName; break; case TypeKind.Delegate: type = _Classifications.DelegateName; break; case TypeKind.Enum: type = _Classifications.EnumName; break; } break; case SymbolKind.TypeParameter: type = _Classifications.TypeParameter; break; } if (type != null) { result.Add(CreateClassificationSpan(snapshot, itemSpan, type)); return; } break; case SyntaxKind.SwitchStatement: case SyntaxKind.SwitchSection: case SyntaxKind.IfStatement: case SyntaxKind.ElseClause: MarkClassificationTypeForBrace(itemSpan, snapshot, result, _GeneralClassifications.BranchingKeyword, SpecialHighlightOptions.BranchBrace); return; case SyntaxKind.ForStatement: case SyntaxKind.ForEachStatement: case SyntaxKind.WhileStatement: case SyntaxKind.DoStatement: MarkClassificationTypeForBrace(itemSpan, snapshot, result, _GeneralClassifications.LoopKeyword, SpecialHighlightOptions.LoopBrace); return; case SyntaxKind.UsingStatement: case SyntaxKind.FixedStatement: case SyntaxKind.LockStatement: case SyntaxKind.UnsafeStatement: case SyntaxKind.TryStatement: case SyntaxKind.CatchDeclaration: case SyntaxKind.CatchClause: case SyntaxKind.CatchFilterClause: case SyntaxKind.FinallyClause: MarkClassificationTypeForBrace(itemSpan, snapshot, result, _Classifications.ResourceKeyword, SpecialHighlightOptions.ResourceBrace); return; case SyntaxKind.TupleExpression: MarkClassificationTypeForBrace(itemSpan, snapshot, result, _Classifications.ConstructorMethod, SpecialHighlightOptions.ParameterBrace); return; } if (Config.Instance.SpecialHighlightOptions.HasAnyFlag(SpecialHighlightOptions.SpecialPunctuation | SpecialHighlightOptions.ParameterBrace)) { node = (node as BaseArgumentListSyntax ?? node as BaseParameterListSyntax ?? (CSharpSyntaxNode)(node as CastExpressionSyntax) )?.Parent; if (node != null) { var type = ClassifySyntaxNode(node); if (type != null) { MarkClassificationTypeForBrace(itemSpan, snapshot, result, type, SpecialHighlightOptions.ParameterBrace); } } } } else if (s == '[' || s == ']') { // highlight attribute annotation var node = unitCompilation.FindNode(itemSpan, true, false); if (node.IsKind(SyntaxKind.AttributeList)) { result.Add(CreateClassificationSpan(snapshot, node.Span, _Classifications.AttributeNotation)); } } }
/// <summary> /// Gets all the <see cref="ClassificationSpan"/> objects that intersect with the given range /// of text. /// </summary> /// <remarks> /// This method scans the given SnapshotSpan for potential matches for this classification. /// In this instance, it classifies everything and returns each span as a new ClassificationSpan. /// </remarks> /// <param name="span">The span currently being classified.</param> /// <returns> /// A list of ClassificationSpans that represent spans identified to be of this classification. /// </returns> public IList <ClassificationSpan> GetClassificationSpans(SnapshotSpan span) { _logger.ConditionalInfo("Span start position is={0} and end position is={1}", span.Start.Position, span.End.Position); var result = new List <ClassificationSpan>(); // NOTE: Workspace can be null for "Using directive is unnecessary". Also workspace can // be null when solution/project failed to load and VS gave some reasons of it or when // try to open a file doesn't contained in the current solution Workspace workspace = span.Snapshot.TextBuffer.GetWorkspace(); if (workspace == null) { // TODO: Add supporting a files that doesn't included to the current solution return(result); } Document document = workspace.GetDocument(span.Snapshot.AsText()); SemanticModel semanticModel = _semanticModel ?? (_semanticModel = document.GetSemanticModelAsync().Result); SyntaxTree syntaxTree = semanticModel.SyntaxTree; TextSpan textSpan = new TextSpan(span.Start.Position, span.Length); var classifiedSpans = Classifier.GetClassifiedSpans(semanticModel, textSpan, workspace) .Where(item => item.ClassificationType == "identifier"); CompilationUnitSyntax unitCompilation = syntaxTree.GetCompilationUnitRoot(); foreach (var item in classifiedSpans) { // NOTE: Some kind of nodes, for example ArgumentSyntax, should are handled with a // specific way SyntaxNode node = unitCompilation.FindNode(item.TextSpan, true).HandleNode(); ISymbol symbol = semanticModel.GetSymbolInfo(node).Symbol ?? semanticModel.GetDeclaredSymbol(node); if (symbol == null) { // NOTE: handle alias in using directive if ((node.Parent as NameEqualsSyntax)?.Parent is UsingDirectiveSyntax) { result.Add(CreateClassificationSpan(span.Snapshot, item.TextSpan, _aliasNamespaceType)); continue; } // TODO: Log information about a node and semantic model, because semantic model // didn't retrive information from node in this case _logger.ConditionalInfo("Nothing is found. Span start at {0} and end at {1}", span.Start.Position, span.End.Position); _logger.ConditionalInfo("Node is {0} {1}", node.Kind(), node.RawKind); continue; } switch (symbol.Kind) { case SymbolKind.Alias: case SymbolKind.ArrayType: case SymbolKind.Assembly: case SymbolKind.DynamicType: case SymbolKind.ErrorType: case SymbolKind.Label: case SymbolKind.NetModule: case SymbolKind.NamedType: case SymbolKind.PointerType: case SymbolKind.RangeVariable: case SymbolKind.TypeParameter: case SymbolKind.Preprocessing: //case SymbolKind.Discard: _logger.ConditionalInfo("Symbol kind={0} was on position [{1}..{2}]", symbol.Kind, item.TextSpan.Start, item.TextSpan.End); _logger.ConditionalInfo("Text was: {0}", node.GetText().ToString()); break; case SymbolKind.Field: var fieldSymbol = (symbol as IFieldSymbol).Type; var fieldType = fieldSymbol.TypeKind == TypeKind.Enum ? _enumFieldType : _fieldType; result.Add(CreateClassificationSpan(span.Snapshot, item.TextSpan, fieldType)); break; case SymbolKind.Property: result.Add(CreateClassificationSpan(span.Snapshot, item.TextSpan, _propertyType)); break; case SymbolKind.Event: result.Add(CreateClassificationSpan(span.Snapshot, item.TextSpan, _eventType)); break; case SymbolKind.Local: result.Add(CreateClassificationSpan(span.Snapshot, item.TextSpan, _localFieldType)); break; case SymbolKind.Namespace: var namesapceType = IsAliasNamespace(symbol, node) ? _namespaceType : _aliasNamespaceType; result.Add(CreateClassificationSpan(span.Snapshot, item.TextSpan, namesapceType)); break; case SymbolKind.Parameter: // NOTE: Skip argument in summaries if (node.Parent.Kind() != SyntaxKind.XmlNameAttribute) { result.Add(CreateClassificationSpan(span.Snapshot, item.TextSpan, _parameterType)); } break; case SymbolKind.Method: var methodSymbol = symbol as IMethodSymbol; var methodType = methodSymbol.MethodKind == MethodKind.Constructor ? _constructorMethodType : methodSymbol.IsExtensionMethod ? _extensionMethodType : methodSymbol.IsStatic ? _staticMethodType : _methodType; result.Add(CreateClassificationSpan(span.Snapshot, item.TextSpan, methodType)); break; default: break; } } return(result); }
static void ClassifyPunctuation(TextSpan itemSpan, ITextSnapshot snapshot, List <ClassificationSpan> result, SemanticModel semanticModel, CompilationUnitSyntax unitCompilation) { if (Config.Instance.SpecialHighlightOptions.HasAnyFlag(SpecialHighlightOptions.AllBraces) == false) { return; } var s = snapshot.GetText(itemSpan.Start, itemSpan.Length)[0]; if (s == '{' || s == '}') { var node = unitCompilation.FindNode(itemSpan, true, true); if (node is BaseTypeDeclarationSyntax == false && node is ExpressionSyntax == false && node is NamespaceDeclarationSyntax == false && node.Kind() != SyntaxKind.SwitchStatement && (node = node.Parent) == null) { return; } var type = ClassifySyntaxNode(node); if (type != null) { if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.SpecialPunctuation)) { result.Add(CreateClassificationSpan(snapshot, itemSpan, _GeneralClassifications.SpecialPunctuation)); } if (type == _GeneralClassifications.BranchingKeyword) { if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.BranchBrace)) { result.Add(CreateClassificationSpan(snapshot, itemSpan, type)); } return; } if (type == _GeneralClassifications.LoopKeyword) { if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.LoopBrace)) { result.Add(CreateClassificationSpan(snapshot, itemSpan, type)); } return; } if (type == _Classifications.ResourceKeyword) { if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.ResourceBrace)) { result.Add(CreateClassificationSpan(snapshot, itemSpan, type)); } return; } if (node is ExpressionSyntax == false) { result.Add(CreateClassificationSpan(snapshot, itemSpan, _Classifications.DeclarationBrace)); } if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.DeclarationBrace)) { result.Add(CreateClassificationSpan(snapshot, itemSpan, type)); } } } else if ((s == '(' || s == ')') && Config.Instance.SpecialHighlightOptions.HasAnyFlag(SpecialHighlightOptions.AllParentheses)) { var node = unitCompilation.FindNode(itemSpan, true, true); switch (node.Kind()) { case SyntaxKind.CastExpression: if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.CastBrace) == false) { return; } var symbol = semanticModel.GetSymbolInfo(((CastExpressionSyntax)node).Type).Symbol; if (symbol == null) { return; } var type = GetClassificationType(symbol); if (type != null) { if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.SpecialPunctuation)) { result.Add(CreateClassificationSpan(snapshot, itemSpan, _GeneralClassifications.SpecialPunctuation)); } result.Add(CreateClassificationSpan(snapshot, itemSpan, type)); return; } break; case SyntaxKind.ParenthesizedExpression: if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.CastBrace) == false) { return; } if (node.ChildNodes().FirstOrDefault().IsKind(SyntaxKind.AsExpression)) { symbol = semanticModel.GetSymbolInfo(((BinaryExpressionSyntax)node.ChildNodes().First()).Right).Symbol; if (symbol == null) { return; } type = GetClassificationType(symbol); if (type != null) { if (Config.Instance.SpecialHighlightOptions.MatchFlags(SpecialHighlightOptions.SpecialPunctuation)) { result.Add(CreateClassificationSpan(snapshot, itemSpan, _GeneralClassifications.SpecialPunctuation)); } result.Add(CreateClassificationSpan(snapshot, itemSpan, type)); return; } } break; case SyntaxKind.SwitchStatement: case SyntaxKind.SwitchSection: case SyntaxKind.IfStatement: case SyntaxKind.ElseClause: MarkClassificationTypeForBrace(itemSpan, snapshot, result, _GeneralClassifications.BranchingKeyword, SpecialHighlightOptions.BranchBrace); return; case SyntaxKind.ForStatement: case SyntaxKind.ForEachStatement: case SyntaxKind.ForEachVariableStatement: case SyntaxKind.WhileStatement: case SyntaxKind.DoStatement: MarkClassificationTypeForBrace(itemSpan, snapshot, result, _GeneralClassifications.LoopKeyword, SpecialHighlightOptions.LoopBrace); return; case SyntaxKind.UsingStatement: case SyntaxKind.FixedStatement: case SyntaxKind.LockStatement: case SyntaxKind.UnsafeStatement: case SyntaxKind.TryStatement: case SyntaxKind.CatchDeclaration: case SyntaxKind.CatchClause: case SyntaxKind.CatchFilterClause: case SyntaxKind.FinallyClause: MarkClassificationTypeForBrace(itemSpan, snapshot, result, _Classifications.ResourceKeyword, SpecialHighlightOptions.ResourceBrace); return; case SyntaxKind.TupleExpression: MarkClassificationTypeForBrace(itemSpan, snapshot, result, _Classifications.ConstructorMethod, SpecialHighlightOptions.ParameterBrace); return; } if (Config.Instance.SpecialHighlightOptions.HasAnyFlag(SpecialHighlightOptions.SpecialPunctuation | SpecialHighlightOptions.ParameterBrace)) { node = (node as BaseArgumentListSyntax ?? node as BaseParameterListSyntax ?? (CSharpSyntaxNode)(node as CastExpressionSyntax) )?.Parent; if (node != null) { var type = ClassifySyntaxNode(node); if (type != null) { MarkClassificationTypeForBrace(itemSpan, snapshot, result, type, SpecialHighlightOptions.ParameterBrace); } } } } else if (s == '[' || s == ']') { // highlight attribute annotation var node = unitCompilation.FindNode(itemSpan, true, false); if (node.IsKind(SyntaxKind.AttributeList)) { result.Add(CreateClassificationSpan(snapshot, node.Span, _Classifications.AttributeNotation)); } } IClassificationType GetClassificationType(ISymbol symbol) { switch (symbol.Kind) { case SymbolKind.NamedType: switch (((INamedTypeSymbol)symbol).TypeKind) { case TypeKind.Class: return(_Classifications.ClassName); case TypeKind.Interface: return(_Classifications.InterfaceName); case TypeKind.Struct: return(_Classifications.StructName); case TypeKind.Delegate: return(_Classifications.DelegateName); case TypeKind.Enum: return(_Classifications.EnumName); } break; case SymbolKind.ArrayType: return(_Classifications.ClassName); case SymbolKind.Event: return(_Classifications.Event); case SymbolKind.PointerType: return(_Classifications.StructName); case SymbolKind.TypeParameter: var p = (ITypeParameterSymbol)symbol; foreach (var c in p.ConstraintTypes) { switch (c.SpecialType) { case SpecialType.System_Enum: return(_Classifications.EnumName); case SpecialType.System_Delegate: return(_Classifications.DelegateName); } return(_Classifications.ClassName); } if (p.HasReferenceTypeConstraint) { return(_Classifications.ClassName); } if (p.HasValueTypeConstraint || p.HasUnmanagedTypeConstraint) { return(_Classifications.StructName); } return(_Classifications.TypeParameter); } return(null); } }