예제 #1
0
        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);
        }
예제 #2
0
        /// <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);
        }
예제 #4
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
        }
예제 #9
0
        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));
 }
예제 #11
0
        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));
                }
            }
        }
예제 #12
0
        /// <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);
        }
예제 #13
0
        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);
            }
        }