public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var classNode = (ClassDeclarationSyntax) node;

            if (classNode.BaseListOpt == null) return null;

            var walker = new MilSyntaxWalker();
            walker.Visit((SyntaxNode) document.GetSyntaxTree(cancellationToken).Root);
            var allCommandHandlersInProject = walker.CommandHandlers;

           
            if (!allCommandHandlersInProject.Any() && !allCommandHandlersInProject.Contains(node)) return null;

            var dupes = walker.CommandHandlers.SelectMany(x => x.BaseListOpt.Types).FindDuplicates();

            if (!dupes.Any())
            {
                var desc = "{0} is implemented by multiple handlers:{1}{2}";
                var issues = new List<CodeIssue>();
                foreach (var dupe in dupes)
                {
                    var listing = FormatHandlerListing(dupe.GetClassName(), allCommandHandlersInProject.ToDictionary(x => x, syntax => syntax.BaseListOpt.Types.OfType<GenericNameSyntax>()));
                    var text = string.Format(desc, dupe, Environment.NewLine, string.Join(Environment.NewLine, listing));
                    issues.Add(new CodeIssue(CodeIssue.Severity.Warning, classNode.Identifier.FullSpan, text));
                }
                return issues;
            }
            return null;

            //if (allCommandHandlersInProject.Contains(node as ClassDeclarationSyntax))
            //{
            //    return new CodeIssue[] { new CodeIssue(CodeIssue.Severity.Warning, node.FullSpan, "Command Handler detected") };
            //}
        }
Exemple #2
0
 public FixSpellingCodeAction(IDocument document, CommonSyntaxNode syntaxNode, string oldIdentifier, string newIdentifier)
 {
     this.Document      = document;
     this.Node          = syntaxNode;
     this.OldIdentifier = oldIdentifier;
     this.NewIdentifier = newIdentifier;
 }
 public IList<DeclaredItemDocument> DoVisit(ISemanticModel model, CommonSyntaxNode node)
 {
     this.model = model as SemanticModel;
     this.declaredItems = new List<DeclaredItemDocument>();
     Visit(node as SyntaxNode);
     return this.declaredItems;
 }
Exemple #4
0
        public IEnumerable <SyntaxClassification> ClassifyNode(IDocument document, CommonSyntaxNode syntax, CancellationToken cancellationToken)
        {
            // If this node is a field declaration, return syntax classifications for the
            // identifier token of each field name.
            //
            // For example, "x" and "y" would be classified in the following code:
            //
            // class C
            // {
            //     int x, y;
            // }
            if (syntax is FieldDeclarationSyntax)
            {
                var field = (FieldDeclarationSyntax)syntax;

                return(from v in field.Declaration.Variables
                       select new SyntaxClassification(v.Identifier.Span, fieldClassification));
            }

            // If this node is an identifier, use the binding API to retrieve its symbol and return a
            // syntax classification for the node if that symbol is a field.
            if (syntax is IdentifierNameSyntax)
            {
                var semanticModel = document.GetSemanticModel(cancellationToken);
                var symbol        = semanticModel.GetSemanticInfo(syntax).Symbol;

                if (symbol != null && symbol.Kind == CommonSymbolKind.Field)
                {
                    return(new[] { new SyntaxClassification(syntax.Span, fieldClassification) });
                }
            }

            return(null);
        }
        public IEnumerable <CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var solution = document.Project.Solution;

            var newExpression = node as ObjectCreationExpressionSyntax;

            var initializer = newExpression.Initializer;

            var types = newExpression.Type;

            var name = types.ToString();

            var symbols = solution.FindSymbols(name).ToList();

            yield break;
//            foreach (var token in tokens)
//            {
//                var tokenText = token.ToString();
//
//                if (tokenText.Contains("new"))
//                {
//                    var issueDescription = string.Format("'{0}' contains the letter 'a'", tokenText);
//                    yield return new CodeIssue(CodeIssueKind.Warning, token.Span, issueDescription);
//                }
//            }
        }
Exemple #6
0
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            LoadKnownPure();
            var methodCall = node as InvocationExpressionSyntax;//Must be method call
            Debug.Assert(methodCall != null);

            if (!(methodCall.Parent is ExpressionStatementSyntax))//Method call must be the outermost in a statement
                yield break;

            var semanticModel = document.GetSemanticModel();
            var symbol = semanticModel.GetSemanticInfo(methodCall.Expression).Symbol as IMethodSymbol;

            if (symbol == null)//Symbol for method unavailable
                yield break;

            if (knownPureFunctions.Contains(GetMethodNameCecilStyle(symbol)) ||
                symbol.GetAttributes().Any(attr => attr.AttributeClass.Name == "PureAttribute"))
            {
                var issueDescription = string.Format("Call to pure method '{0}' used as a statement.", symbol);
                yield return new CodeIssue(CodeIssue.Severity.Warning, methodCall.Span, issueDescription);
            }

            var typeSymbol = symbol.ContainingType;

            if (typeSymbol.GetAttributes().Any(attr => attr.AttributeClass.Name == "PureAttribute"))
            {
                var issueDescription = string.Format("Call to method '{0}' on pure type '{1}' used as a statement.", symbol.Name, typeSymbol);
                yield return new CodeIssue(CodeIssue.Severity.Warning, methodCall.Span, issueDescription);
            }
        }
        internal SyntaxTransporter(CommonSyntaxNode node)
        {
            if (node is CSharp.SyntaxNode)
            {
                SourceLanguage = LanguageNames.CSharp;
            }
            else
            {
                SourceLanguage = LanguageNames.VisualBasic;
            }

            SyntaxStream = new MemoryStream();
            var rootNode = GetRootNode(node);

            if (rootNode != null)
            {
                if (SourceLanguage == LanguageNames.CSharp)
                {
                    var csharpRootNode = (CSharp.SyntaxNode)rootNode;
                    csharpRootNode.SerializeTo(SyntaxStream);
                }
                else
                {
                    var vbRootNode = (VisualBasic.SyntaxNode)rootNode;
                    vbRootNode.SerializeTo(SyntaxStream);
                }
            }

            ItemSpan     = node.Span;
            ItemKind     = node.GetKind(SourceLanguage);
            ItemCategory = SyntaxCategory.SyntaxNode;
        }
Exemple #8
0
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var declaration = node as VariableDeclarationSyntax;
            var loop = node as ForEachStatementSyntax;
            var model = document.GetSemanticModel();
            var assume = Assumptions.All;

            if (declaration != null) {
                foreach (var r in GetSimplifications(declaration, model, assume, cancellationToken)) {
                    yield return new CodeIssue(
                        CodeIssue.Severity.Warning,
                        r.SuggestedSpan ?? declaration.Type.Span,
                        "Type of local variable can be infered.",
                        new[] { r.AsCodeAction(document) });
                }
            } else if (loop != null) {
                foreach (var r in GetSimplifications(loop, model, assume, cancellationToken)) {
                    yield return new CodeIssue(
                        CodeIssue.Severity.Warning,
                        r.SuggestedSpan ?? loop.Type.Span,
                        "Type of loop variable can be infered.",
                        new[] { r.AsCodeAction(document) });
                }
            }
        }
        private SpellingIssue IdentifyIssues(string word,
            IDocument document,
            SyntaxToken identifier,
            CommonSyntaxNode node,
            ParallelLoopState state,
            SpellingIssue dummy)
        {
            bool found = WordLookupService.SearchExact(word.ToLower());
            if (found)
                return (SpellingIssue)null;

            var suggestions = WordLookupService.Search(word.ToLower())
                .Select(m => char.IsUpper(identifier.ValueText[0]) ? (char.ToUpper(m[0]) + m.Substring(1)) : m)
                .ToList();

            var actions = new List<ICodeAction>();

            foreach (var suggestion in suggestions)
            {
                actions.Add(new FixSpellingCodeAction(document, node, identifier.ValueText,
                    identifier.ValueText.Replace(word, suggestion)));
            }

            var spanStart = identifier.Span.Start + identifier.ValueText.IndexOf(word, StringComparison.InvariantCultureIgnoreCase);
            var span = new TextSpan(spanStart, word.Length);
            return new SpellingIssue(span, word, actions);
        }
 public FixSpellingCodeAction(IDocument document, CommonSyntaxNode syntaxNode, string oldIdentifier, string newIdentifier)
 {
     this.Document = document;
     this.Node = syntaxNode;
     this.OldIdentifier = oldIdentifier;
     this.NewIdentifier = newIdentifier;
 }
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var parameterSyntax = (ParameterSyntax)node;
            var parentMethodBody = parameterSyntax.GetParentMethodBody();
            
            if (parentMethodBody == null) // abstract/interface/extern
                yield break;

            var model = document.GetSemanticModel(cancellationToken);
            var parentMethod = parameterSyntax.Parent.Parent as BaseMethodDeclarationSyntax;

            if (parentMethod != null &&
                parentMethod.SignatureIsRequiredToSatisfyExternalDependency(document, cancellationToken))
                yield break;

            var dataFlow = model.AnalyzeDataFlow(parentMethodBody);

            if (!dataFlow.Succeeded)
                yield break;

            var parameterSymbol = model.GetDeclaredSymbol(node, cancellationToken);

            bool isUsed = dataFlow.ReadInside.Contains(parameterSymbol) || dataFlow.WrittenInside.Contains(parameterSymbol);

            if (!isUsed)
                yield return new CodeIssue(CodeIssueKind.Unnecessary, node.Span,
                    string.Format("{0} is not used.", parameterSymbol.Name));
        }
        public Issue(
            ErrorCode errorCode,
            CommonSyntaxNode syntaxNode,
            ISymbol symbol)
        {
            #region Input validtion

            if (!Enum.IsDefined(typeof(ErrorCode), errorCode))
            {
                throw new ArgumentException("errorCode is not defined.", "errorCode");
            }

            if (syntaxNode == null)
            {
                throw new ArgumentNullException("syntaxNode");
            }

            if (symbol == null)
            {
                throw new ArgumentNullException("symbol");
            }

            #endregion

            _errorCode = errorCode;
            _description = DescriptionResolver.GetDescription(errorCode);
            _syntaxNode = syntaxNode;
            _symbol = symbol;
            _location = syntaxNode.GetLocation();

            _sourceLineNumber = GetSourceLineNumber();
            _sourceLineText = GetSourceLineText(_sourceLineNumber);
            _sourceFileName = GetSourceFileName();
        }
        protected override bool TryInitializeExplicitInterfaceState(
            IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken,
            out CommonSyntaxToken identifierToken, out IPropertySymbol propertySymbol, out INamedTypeSymbol typeToGenerateIn)
        {
            var propertyDeclaration = (PropertyDeclarationSyntax)node;

            identifierToken = propertyDeclaration.Identifier;

            if (propertyDeclaration.ExplicitInterfaceSpecifier != null)
            {
                var semanticModel = document.GetSemanticModel(cancellationToken);
                propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken) as IPropertySymbol;
                if (propertySymbol != null && !propertySymbol.ExplicitInterfaceImplementations.Any())
                {
                    var info = semanticModel.GetTypeInfo(propertyDeclaration.ExplicitInterfaceSpecifier.Name, cancellationToken);
                    typeToGenerateIn = info.Type as INamedTypeSymbol;
                    return(typeToGenerateIn != null);
                }
            }

            identifierToken  = default(CommonSyntaxToken);
            propertySymbol   = null;
            typeToGenerateIn = null;
            return(false);
        }
Exemple #14
0
        public IEnumerable <CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            LoadKnownPure();
            var methodCall = node as InvocationExpressionSyntax;            //Must be method call

            Debug.Assert(methodCall != null);

            if (!(methodCall.Parent is ExpressionStatementSyntax))            //Method call must be the outermost in a statement
            {
                yield break;
            }

            var semanticModel = document.GetSemanticModel();
            var symbol        = semanticModel.GetSemanticInfo(methodCall.Expression).Symbol as IMethodSymbol;

            if (symbol == null)            //Symbol for method unavailable
            {
                yield break;
            }

            if (knownPureFunctions.Contains(GetMethodNameCecilStyle(symbol)) ||
                symbol.GetAttributes().Any(attr => attr.AttributeClass.Name == "PureAttribute"))
            {
                var issueDescription = string.Format("Call to pure method '{0}' used as a statement.", symbol);
                yield return(new CodeIssue(CodeIssue.Severity.Warning, methodCall.Span, issueDescription));
            }

            var typeSymbol = symbol.ContainingType;

            if (typeSymbol.GetAttributes().Any(attr => attr.AttributeClass.Name == "PureAttribute"))
            {
                var issueDescription = string.Format("Call to method '{0}' on pure type '{1}' used as a statement.", symbol.Name, typeSymbol);
                yield return(new CodeIssue(CodeIssue.Severity.Warning, methodCall.Span, issueDescription));
            }
        }
Exemple #15
0
        public IEnumerable <CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken = new CancellationToken())
        {
            var variable = node as VariableDeclarationSyntax;

            if (variable != null)
            {
                var nodes = variable.ChildNodes().Where(x => x.Kind == SyntaxKind.VariableDeclarator);

                foreach (var syntaxNode in nodes)
                {
                    var fullVariableName = syntaxNode.GetFirstToken().ValueText;

                    var wordsInVariableName = fullVariableName.SplitToWords();

                    if (wordsInVariableName != null)
                    {
                        var correctSpelling = CheckAndCorrectSpelling(wordsInVariableName);

                        if (correctSpelling != null)
                        {
                            yield return(new CodeIssue(CodeIssue.Severity.Info, syntaxNode.GetFirstToken().Span, "Possible Typo ?\nMaybe you meant : " + correctSpelling));
                        }
                    }
                }
            }
        }
        public IEnumerable<SyntaxClassification> ClassifyNode(IDocument document, CommonSyntaxNode syntax, CancellationToken cancellationToken)
        {
            // If this node is a field declaration, return syntax classifications for the
            // identifier token of each field name.
            //
            // For example, "x" and "y" would be classified in the following code:
            // 
            // class C
            // {
            //     int x, y;
            // }
            if (syntax is FieldDeclarationSyntax)
            {
                var field = (FieldDeclarationSyntax)syntax;

                return from v in field.Declaration.Variables
                       select new SyntaxClassification(v.Identifier.Span, fieldClassification);
            }

            // If this node is an identifier, use the binding API to retrieve its symbol and return a 
            // syntax classification for the node if that symbol is a field.
            if (syntax is IdentifierNameSyntax)
            {
                var semanticModel = document.GetSemanticModel(cancellationToken);
                var symbol = semanticModel.GetSemanticInfo(syntax).Symbol;

                if (symbol != null && symbol.Kind == CommonSymbolKind.Field)
                {
                    return new[] { new SyntaxClassification(syntax.Span, fieldClassification) };
                }
            }

            return null;
        }
        private SpellingIssue IdentifyIssues(string word,
                                             IDocument document,
                                             SyntaxToken identifier,
                                             CommonSyntaxNode node,
                                             ParallelLoopState state,
                                             SpellingIssue dummy)
        {
            bool found = WordLookupService.SearchExact(word.ToLower());

            if (found)
            {
                return((SpellingIssue)null);
            }

            var suggestions = WordLookupService.Search(word.ToLower())
                              .Select(m => char.IsUpper(identifier.ValueText[0]) ? (char.ToUpper(m[0]) + m.Substring(1)) : m)
                              .ToList();

            var actions = new List <ICodeAction>();

            foreach (var suggestion in suggestions)
            {
                actions.Add(new FixSpellingCodeAction(document, node, identifier.ValueText,
                                                      identifier.ValueText.Replace(word, suggestion)));
            }

            var spanStart = identifier.Span.Start + identifier.ValueText.IndexOf(word, StringComparison.InvariantCultureIgnoreCase);
            var span      = new TextSpan(spanStart, word.Length);

            return(new SpellingIssue(span, word, actions));
        }
        public IEnumerable <CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            ExpressionStatementSyntax    expressionStatement;
            PostfixUnaryExpressionSyntax postFixExpression;
            PrefixUnaryExpressionSyntax  prefixExpression;
            ISymbol mutatedSymbol;

            if ((expressionStatement = node as ExpressionStatementSyntax) != null)
            {
                mutatedSymbol = GetMutatedSymbol(document, cancellationToken, expressionStatement);
            }
            else if ((postFixExpression = node as PostfixUnaryExpressionSyntax) != null)
            {
                mutatedSymbol = GetMutatedSymbol(document, cancellationToken, postFixExpression);
            }
            else if ((prefixExpression = node as PrefixUnaryExpressionSyntax) != null)
            {
                mutatedSymbol = GetMutatedSymbol(document, cancellationToken, prefixExpression);
            }
            else
            {
                throw new ArgumentException("Unhandled node type.");
            }

            if (mutatedSymbol != null && mutatedSymbol.Kind == CommonSymbolKind.Parameter &&
                ((ParameterSymbol)mutatedSymbol).RefKind == RefKind.None)
            {
                yield return(new CodeIssue(CodeIssueKind.Warning, node.Span, "Do not mutate the values of parameters."));
            }
        }
 public IList <DeclaredItemDocument> DoVisit(ISemanticModel model, CommonSyntaxNode node)
 {
     this.model         = model as SemanticModel;
     this.declaredItems = new List <DeclaredItemDocument>();
     Visit(node as SyntaxNode);
     return(this.declaredItems);
 }
Exemple #20
0
        /// <summary>
        /// Gets a document location from a tree node.
        /// </summary>
        /// <param name="tree">The tree.</param>
        /// <param name="node">The node.</param>
        /// <returns>A new document location.</returns>
        internal static DocumentLocation FromTreeNode(CommonSyntaxTree tree, CommonSyntaxNode node)
        {
            if (tree == null || node == null)
                return Default;

            return FromSpan(tree.GetLineSpan(node.Span, true));
        }
Exemple #21
0
        public override Task <ConflictInfoCollection> GetDataAsync()
        {
            // TFS binaries not loaded. Hasty exit.
            if (!this.EditingSession.SCCServiceReady)
            {
                return(null);
            }

            CommonSyntaxNode syntaxNode = this.MethodIdentifier.SyntaxNode;

            this.MethodIdentifier.SyntaxNodeChanged += this.OnSyntaxNodeChanged;

            return(this.Run <ConflictInfoCollection>(token =>
            {
                return Task.Run <ConflictInfoCollection>(() =>
                {
                    IEnumerable <ConflictInfo> conflicts = this.EditingSession.GetConflicts();

                    if (conflicts != null)
                    {
                        // Get the conflicts that intersect with this method.
                        FileLinePositionSpan syntaxNodeFileLineSpan = syntaxNode.SyntaxTree.GetLineSpan(syntaxNode.FullSpan, false);
                        Span syntaxNodeLineSpan = new Span(syntaxNodeFileLineSpan.StartLinePosition.Line, syntaxNodeFileLineSpan.EndLinePosition.Line - syntaxNodeFileLineSpan.StartLinePosition.Line);
                        IEnumerable <ConflictInfo> conflictsWithinNode = conflicts.Where(c => c.IntersectsWith(syntaxNodeLineSpan));

                        if (conflictsWithinNode.Any())
                        {
                            return new ConflictInfoCollection(conflictsWithinNode, this.EditingSession.LatestVersion);
                        }
                    }

                    return null;
                });
            }));
        }
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var solution = document.Project.Solution;

            var newExpression = node as ObjectCreationExpressionSyntax;

            var initializer = newExpression.Initializer;

            var types = newExpression.Type;

            var name = types.ToString();

            var symbols = solution.FindSymbols(name).ToList();
                
            yield break;
//            foreach (var token in tokens)
//            {
//                var tokenText = token.ToString();
//
//                if (tokenText.Contains("new"))
//                {
//                    var issueDescription = string.Format("'{0}' contains the letter 'a'", tokenText);
//                    yield return new CodeIssue(CodeIssueKind.Warning, token.Span, issueDescription);
//                }
//            }
        }
        private static SyntaxToken[] GetIdentifiers(CommonSyntaxNode node)
        {
            VariableDeclaratorSyntax    variableDeclarator; // includes fields
            BaseTypeDeclarationSyntax   typeDeclaration;
            MethodDeclarationSyntax     methodDeclaration;
            NamespaceDeclarationSyntax  namespaceDeclaration;
            EnumMemberDeclarationSyntax enumMemberDeclaration;
            PropertyDeclarationSyntax   propertyDeclaration;
            EventDeclarationSyntax      eventDeclaration;
            ParameterSyntax             parameterSyntax;

            SyntaxToken[] identifiers;

            if ((variableDeclarator = node as VariableDeclaratorSyntax) != null)
            {
                identifiers = new[] { variableDeclarator.Identifier }
            }
            ;
            else if ((parameterSyntax = node as ParameterSyntax) != null)
            {
                identifiers = new[] { parameterSyntax.Identifier }
            }
            ;
            else if ((propertyDeclaration = node as PropertyDeclarationSyntax) != null)
            {
                identifiers = new[] { propertyDeclaration.Identifier }
            }
            ;
            else if ((typeDeclaration = node as BaseTypeDeclarationSyntax) != null)
            {
                identifiers = new[] { typeDeclaration.Identifier }
            }
            ;
            else if ((methodDeclaration = node as MethodDeclarationSyntax) != null)
            {
                identifiers = new[] { methodDeclaration.Identifier }
            }
            ;
            else if ((enumMemberDeclaration = node as EnumMemberDeclarationSyntax) != null)
            {
                identifiers = new[] { enumMemberDeclaration.Identifier }
            }
            ;
            else if ((eventDeclaration = node as EventDeclarationSyntax) != null)
            {
                identifiers = new[] { eventDeclaration.Identifier }
            }
            ;
            else if ((namespaceDeclaration = node as NamespaceDeclarationSyntax) != null)
            {
                identifiers = namespaceDeclaration.Name.ChildNodes().OfType <IdentifierNameSyntax>()
                              .Select(i => i.Identifier).ToArray();
            }
            else
            {
                throw new ArgumentException("Unhandled node.");
            }
            return(identifiers);
        }
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            initialize(document);

            // Add the new record to the history component.
            GhostFactorComponents.historyComponent.UpdateActiveDocument(document);
            return GhostFactorComponents.RefactoringCodeIssueComputerComponent.GetCodeIssues(document, (SyntaxNode) node);
        }
Exemple #25
0
 internal void DoVisit(ISemanticModel semanticModel, CommonSyntaxNode token, TokenParameter parameter, TokenKind searchTokenKind, Action <int> symbolFoundDelegate)
 {
     this.semanticModel       = semanticModel;
     this.symbolFoundDelegate = symbolFoundDelegate;
     this.parameter           = parameter;
     this.searchTokenKind     = searchTokenKind;
     Visit(token);
 }
 internal void DoVisit(ISemanticModel semanticModel, CommonSyntaxNode token, TokenParameter parameter, TokenKind searchTokenKind, Action<int> symbolFoundDelegate)
 {
     this.semanticModel = semanticModel as SemanticModel;
     this.symbolFoundDelegate = symbolFoundDelegate;
     this.parameter = parameter;
     this.searchTokenKind = searchTokenKind;
     Visit(token as SyntaxNode);
 }
Exemple #27
0
        // explicit interface implementation
        void ISyntaxValidator.Validate(CommonSyntaxNode node, CommonSyntaxTree tree, CompilationResult result)
        {
            _currentTree   = tree;
            _currentNode   = node;
            _currentResult = result;

            Validate(node as T, tree, result);
        }
Exemple #28
0
        public IEnumerable <CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var model  = document.GetSemanticModel(cancellationToken);
            var symbol = (MethodSymbol)model.GetDeclaredSymbol(node, cancellationToken);

            if (symbol.MethodKind == MethodKind.StaticConstructor)
            {
                yield break;
            }

            var entryPoint = model.Compilation.GetEntryPoint(cancellationToken);

            if (symbol.Equals(entryPoint))
            {
                yield break;
            }

            var callers = symbol.FindCallers(document.Project.Solution, cancellationToken);

            if (callers.Any())
            {
                yield break;
            }

            var interfaceMembers = symbol.FindImplementedInterfaceMembers(document.Project.Solution, cancellationToken);

            if (interfaceMembers.Any(im => !im.IsDeclaredInSource() || im.IsExternallyVisible()))
            {
                yield break;
            }

            var implementations = interfaceMembers.SelectMany(im => im.FindImplementations(document.Project.Solution, cancellationToken));

            if (implementations.Any(impl => impl.IsExternallyVisible()))
            {
                yield break;
            }

            if (symbol.FindImplementations(document.Project.Solution, cancellationToken).Any(impl => impl.IsExternallyVisible()))
            {
                yield break;
            }

            if (symbol.IsExternallyVisible())
            {
                yield break;
            }

            if (symbol.OverriddenMethod != null &&
                (!symbol.OverriddenMethod.IsDeclaredInSource() || symbol.OverriddenMethod.IsExternallyVisible()))
            {
                yield break;
            }

            yield return(new CodeIssue(CodeIssueKind.Unnecessary, node.Span,
                                       string.Format("{0} is never called.", symbol.Name),
                                       new RemoveMethodCodeAction(document, (BaseMethodDeclarationSyntax)node)));
        }
        private void TraverseThroughAllTheProjectFiles(TokenParameter parameter, IFindReferenceProgress findReferenceProgressListener, Func <string, string, ISemanticModel, CommonSyntaxNode, bool> visitorAction)
        {
            findReferenceProgressListener.OnFindReferenceStarted();

            var projectCodeDirectory = new DirectoryInfo(this.applicationConfigurationProvider.GetProjectSourceCodePath(parameter.Username, parameter.Project));

            var solutionPath = FindSolutionPath(parameter.Username, parameter.Project);

            if (solutionPath == null)
            {
                findReferenceProgressListener.OnFindReferenceCompleted(0);
                return;
            }

            findReferenceProgressListener.OnFindReferenceInProgress();

            var workspace       = Roslyn.Services.Workspace.LoadSolution(solutionPath);
            var currentFilePath = Path.Combine(projectCodeDirectory.FullName, parameter.Path.Replace(@"/", @"\"));
            var solution        = workspace.CurrentSolution;

            foreach (var project in solution.Projects)
            {
                try
                {
                    bool processingCompleted = false;

                    if (!project.HasDocuments)
                    {
                        continue;
                    }

                    foreach (var document in project.Documents)
                    {
                        var documentSemanticModel      = document.GetSemanticModel();
                        var findReferenceSyntaxtWalker = new FindReferenceSyntaxWalker();
                        CommonSyntaxNode syntaxRoot    = null;
                        if (documentSemanticModel.SyntaxTree.TryGetRoot(out syntaxRoot))
                        {
                            var documentRelativePath = new Uri(projectCodeDirectory.FullName + Path.DirectorySeparatorChar).MakeRelativeUri(new Uri(document.FilePath)).ToString();
                            processingCompleted = visitorAction(document.Name, documentRelativePath, documentSemanticModel, syntaxRoot);
                            if (processingCompleted)
                            {
                                break;
                            }
                        }
                    }

                    if (processingCompleted)
                    {
                        break;
                    }
                }
                catch (Exception ex)
                {
                    this.logger.Error(ex, "An error has occured while loading the project {0}", project.Name);
                }
            }
        }
Exemple #30
0
        public IEnumerable <CodeIssue> GetIssues(IDocument document,
                                                 CommonSyntaxNode node,
                                                 CancellationToken cancellationToken)
        {
            var methodNode = (MethodDeclarationSyntax)node;

            if (methodNode.Attributes != null)
            {
                var model = document.GetSemanticModel();
                var operationContractType =
                    typeof(OperationContractAttribute);
                var operationSyntax = (
                    from attribute in methodNode.Attributes
                    from syntax in attribute.Attributes
                    let attributeType = model.GetTypeInfo(syntax).Type
                                        where
                                        attributeType != null &&
                                        attributeType.Name ==
                                        operationContractType.Name &&
                                        attributeType.ContainingAssembly.Name ==
                                        operationContractType.Assembly.GetName().Name
                                        from argument in syntax.ArgumentList.Arguments
                                        where (
                        argument.NameEquals.Identifier.GetText() ==
                        "IsOneWay" &&
                        argument.Expression.Kind ==
                        SyntaxKind.TrueLiteralExpression)
                                        select new { syntax, argument }).FirstOrDefault();

                if (operationSyntax != null)
                {
                    var returnType = model.GetTypeInfo(methodNode.ReturnType).Type;

                    if (returnType != null &&
                        returnType.SpecialType != SpecialType.System_Void)
                    {
                        return(new[]
                        {
                            new CodeIssue(CodeIssue.Severity.Error,
                                          methodNode.ReturnType.Span,
                                          "One-way WCF operations must return System.Void.",
                                          new ICodeAction[]
                            {
                                new OneWayOperationReturnVoidCodeAction(
                                    document,
                                    methodNode.ReturnType),
                                new OneWayOperationMakeIsOneWayFalseCodeAction(
                                    document,
                                    operationSyntax.argument)
                            })
                        });
                    }
                }
            }

            return(null);
        }
Exemple #31
0
        /// <summary>
        /// Gets a document location from a tree node.
        /// </summary>
        /// <param name="tree">The tree.</param>
        /// <param name="node">The node.</param>
        /// <returns>A new document location.</returns>
        internal static DocumentLocation FromTreeNode(CommonSyntaxTree tree, CommonSyntaxNode node)
        {
            if (tree == null || node == null)
            {
                return(Default);
            }

            return(FromSpan(tree.GetLineSpan(node.Span, true)));
        }
        public override void Visit(CommonSyntaxNode node)
        {
            var validator = _provider.ResolveImport(node.GetType());

            if (validator != null)
                validator.Validate(node, CurrentTree, _result);

            base.Visit(node);
        }
        public MyCodeAction(ICodeActionEditFactory editFactory, IDocument document, CommonSyntaxNode node)
        {
            _editFactory = editFactory;
            _document = document;
            _node = node;

            Description = "Replace 'a' with 'b'";
            Icon = null;
        }
        public AddThrowCodeAction(CodeActionEdit editFactory, IDocument document, CommonSyntaxNode node)
        {
            _editFactory = editFactory;
            _document = document;
            _node = (CatchClauseSyntax)node;

            Description = "please throw the exception if you can't handle it";
            Icon = null;
        }
Exemple #35
0
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var statement = (IfStatementSyntax)node;
            var model = document.GetSemanticModel();
            var newStatement = statement.DropEmptyBranchesIfApplicable(Assumptions.All, model);
            if (newStatement == statement) return null;

            var r = new ReadyCodeAction("Omit useless code", document, statement, () => newStatement);
            return r.CodeIssues1(CodeIssue.Severity.Warning, statement.IfKeyword.Span, "Useless branch");
        }
        public override void Visit(CommonSyntaxNode node)
        {
            var validator = _provider.ResolveImport(node.GetType());

            if (validator != null)
            {
                validator.Validate(node, CurrentTree, _result);
            }

            base.Visit(node);
        }
 public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
 {
     var forLoop = (ForEachStatementSyntax)node;
     var model = document.GetSemanticModel();
     var simplifications = GetSimplifications(forLoop, model, Assumptions.All, cancellationToken);
     return simplifications.Select(e => new CodeIssue(
         CodeIssue.Severity.Warning,
         forLoop.ForEachKeyword.Span,
         "Single execution of 'for each' loop body is sufficient.",
         new[] { e.AsCodeAction(document) }));
 }
        public IEnumerable <CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var methodNode = (MethodDeclarationSyntax)node;

            // Code Complexity
            var nodes = methodNode.DescendantNodes();

            var totalCount         = nodes.Count();
            var switchSectionCount = nodes.OfType <SwitchSectionSyntax>().Count();
            var loopCount          = (nodes.OfType <ForEachStatementSyntax>().Count()
                                      + nodes.OfType <WhileStatementSyntax>().Count()
                                      + nodes.OfType <ForStatementSyntax>().Count());

            var ifCount     = nodes.OfType <IfStatementSyntax>().Count();
            var elseifCount = nodes.OfType <ElseClauseSyntax>()
                              .Where(x => typeof(IfStatementSyntax).IsAssignableFrom(x.Statement.GetType()))
                              .Count();

            var switchBranchs      = switchSectionCount;
            var loopBranchs        = loopCount * 2;
            var conditionalBranchs = ifCount * 2 - elseifCount;

            var complexity = switchBranchs + loopBranchs + conditionalBranchs;

            var message = string.Format("{0} complexity: {1} switch branchs, {2} for/foreach/while branchs, {3} if/else branchs, {4} total nodes",
                                        complexity, switchBranchs, loopBranchs, conditionalBranchs, totalCount);

            if (complexity < 10)
            {
                yield return(new CodeIssue(CodeIssueKind.Info, methodNode.Identifier.Span, message));
            }
            else
            {
                yield return(new CodeIssue(CodeIssueKind.Warning, methodNode.Identifier.Span, message));
            }

            // Code Length
            var methodLineSpan = methodNode.SyntaxTree.GetLineSpan(methodNode.Body.Span, true);

            var startLine     = methodLineSpan.StartLinePosition.Line + 1;
            var endLine       = methodLineSpan.EndLinePosition.Line + 1;
            var numberOfLines = endLine - startLine + 1;

            var msg = string.Format("Line {0} to line {1}: {2} total lines", startLine, endLine, numberOfLines);

            if (numberOfLines < 30)
            {
                yield return(new CodeIssue(CodeIssueKind.Info, methodNode.Identifier.Span, msg));
            }
            else
            {
                yield return(new CodeIssue(CodeIssueKind.Warning, methodNode.Identifier.Span, msg));
            }
        }
 // If lazy is true then treeview items are populated on-demand. In other words, when lazy is true
 // the children for any given item are only populated when the item is selected. If lazy is
 // false then the entire tree is populated at once (and this can result in bad performance when
 // displaying large trees).
 public void DisplaySyntaxNode(CommonSyntaxNode node, string language, bool lazy = true)
 {
     if (node != null && !string.IsNullOrEmpty(language))
     {
         SourceLanguage = language;
         IsLazy         = lazy;
         SyntaxTree     = node.SyntaxTree;
         AddNode(null, node);
         legendButton.Visibility = Visibility.Visible;
     }
 }
            public static IEnumerable <CommonSyntaxNodeOrToken> Resolve(CommonSyntaxNode root, SyntaxAnnotation annotation)
            {
                Contract.ThrowIfNull(root);
                Contract.ThrowIfNull(annotation);

                var result   = new List <CommonSyntaxNodeOrToken>();
                var resolver = new NodeOrTokenResolver(annotation);

                resolver.Visit(root, result);

                return(result);
            }
            public override void Visit(CommonSyntaxNode node, List <CommonSyntaxTrivia> results)
            {
                // if it doesnt have annotations, don't even bother to go in.
                var baseNode = (IBaseSyntaxNodeExt)node;

                if (!baseNode.HasAnnotations)
                {
                    return;
                }

                base.Visit(node, results);
            }
        public CodeRefactoring GetRefactoring(IDocument document, TextSpan textSpan, CancellationToken cancellationToken)
        {
            string      newName = "newVariableName";
            SyntaxNode  root    = (SyntaxNode)document.GetSyntaxRoot(cancellationToken);
            SyntaxToken token   = root.FindToken(textSpan.Start, findInsideTrivia: true);

            // Verify is the selected token an identifier
            if (token.Kind == SyntaxKind.IdentifierToken && token.Span.Start <= textSpan.End && textSpan.End <= token.Span.End)
            {
                ISemanticModel   model      = document.GetSemanticModel(cancellationToken);
                ISymbol          symbol     = null;
                CommonSyntaxNode parentNode = token.Parent;

                // Local variable node-reference can be either IdentifierName node or VariableDeclarator node
                if (parentNode is IdentifierNameSyntax)
                {
                    CommonSymbolInfo symbolInfo = model.GetSymbolInfo(parentNode, cancellationToken);
                    symbol = symbolInfo.Symbol;
                }
                else if (parentNode is VariableDeclaratorSyntax)
                {
                    symbol = model.GetDeclaredSymbol(parentNode, cancellationToken);
                }

                if (symbol == null)
                {
                    return(null);
                }

                // Verify is the symbol of local variable kind
                if (symbol.Kind != CommonSymbolKind.Local)
                {
                    return(null);
                }

                // Verify is there any other local variable of the same name
                IList <ISymbol> visibleSymbols = model.LookupSymbols(token.Span.Start, name: newName, container: symbol.ContainingType);

                bool isNameReserved = visibleSymbols
                                      .Any(otherSymbol =>
                                           (otherSymbol.Kind == CommonSymbolKind.Local || otherSymbol.Kind == CommonSymbolKind.Parameter) &&
                                           !otherSymbol.Equals(symbol));

                if (!isNameReserved)
                {
                    return(new CodeRefactoring(
                               new[] { new RenameLocalAction(document, token, symbol, newName) },
                               token.Span));
                }
            }

            return(null);
        }
Exemple #43
0
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var invocation = (InvocationExpressionSyntax)node;
            var model = document.GetSemanticModel();
            var simplifications = GetSimplifications(invocation, model, cancellationToken);

            return simplifications.Select(e => new CodeIssue(
                CodeIssue.Severity.Warning,
                invocation.ArgumentList.Span,
                "Filter can be inlined into fold.",
                new[] { e.AsCodeAction(document) }));
        }
        public IEnumerable <CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            ISemanticModel model = document.GetSemanticModel(cancellationToken);

            ObjectCreationExpressionSyntax expression = (ObjectCreationExpressionSyntax)node;

            // Note: Do NOT use HasDiagnostics, as this expression obviously DOES produce errors (type is not known yet)

            TypeSyntax typeSyntax = expression.Type;

            CommonTypeInfo typeInfo = model.GetTypeInfo(typeSyntax, cancellationToken);

            TypeSymbol typeSymbol = (TypeSymbol)typeInfo.Type;

            if (typeSymbol == null)
            {
                yield break;
            }

            // Check if this is an unrecognized symbol
            if (typeSymbol.Kind == SymbolKind.ErrorType)
            {
                string className = string.Empty;

                // TODO: extract container info and propose solutions
                // Considers:
                // new A.B.C() -> namespace A.B { class C {} }

                // Extract top-level name
                // Considers:
                // new A.B.C<int,float>() -> C
                if (typeSyntax.Kind == SyntaxKind.IdentifierName)
                {
                    className = typeSyntax.GetText();
                }
                else if (typeSyntax.Kind == SyntaxKind.GenericName)
                {
                    GenericNameSyntax genericName = (GenericNameSyntax)typeSyntax;
                    className = genericName.Identifier.GetText();
                }
                else if (typeSyntax.Kind == SyntaxKind.QualifiedName)
                {
                    QualifiedNameSyntax qualifiedName = (QualifiedNameSyntax)typeSyntax;
                    className = qualifiedName.Right.GetText();
                }

                yield return(new CodeIssue(CodeIssue.Severity.Info, expression.Span, String.Format("Generate class `{0}'", className), new GenerateClassFromUsageAction(document, expression, className)));
            }

            yield break;
        }
        public void TestNoIssue <T, Node>(String code, TextSpan textSpan)
            where T : ICodeIssueProvider, new()
            where Node : CommonSyntaxNode
        {
            CreateWorkspace(code);

            CommonSyntaxNode node = document.GetSyntaxRoot().FindToken(textSpan.Start).Parent.FirstAncestorOrSelf <Node>();

            ICodeIssueProvider codeIssueProvider = new T();

            IEnumerable <CodeIssue> codeIssues = codeIssueProvider.GetIssues(document, node, cancellationToken);

            Assert.AreEqual(0, codeIssues.Count());
        }
 public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
 {
     if (node.Kind == (int)SyntaxKind.VariableDeclarator)
     {
         var nodeText = node.GetText();
         if (nodeText.Contains('a'))
         {
             var issueDescription = string.Format("'{0}' contains the letter 'a'", nodeText);
             yield return
                 new CodeIssue(CodeIssue.Severity.Warning, node.Span, issueDescription,
                               new MyCodeAction(editFactory, document, node));
         }
     }
 }
Exemple #47
0
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var declaration = (LocalDeclarationStatementSyntax)node;
            var model = document.GetSemanticModel();
            var assume = Assumptions.All;

            foreach (var r in GetSimplifications(declaration, model, assume, cancellationToken)) {
                yield return new CodeIssue(
                    CodeIssue.Severity.Warning,
                    r.SuggestedSpan ?? declaration.Declaration.Type.Span,
                    "Scope of local variable can be reduced.",
                    new[] { r.AsCodeAction(document) });
            }
        }
Exemple #48
0
        private CommonSyntaxNode FindArgumentListRecursive(CommonSyntaxNode node)
        {
            if (node == null)
            {
                return(null);
            }

            if (node.Kind == GetArgumentListCode())
            {
                return(node);
            }

            return(FindArgumentListRecursive(node.Parent));
        }
 // If lazy is true then treeview items are populated on-demand. In other words, when lazy is true
 // the children for any given item are only populated when the item is selected. If lazy is
 // false then the entire tree is populated at once (and this can result in bad performance when
 // displaying large trees).
 public void DisplaySyntaxNode(CommonSyntaxNode node, string language, bool lazy = true)
 {
     if (node != null && !string.IsNullOrEmpty(language))
     {
         SourceLanguage = language;
         IsLazy         = lazy;
         SyntaxTree     = node.SyntaxTree;
         AddNode(root, node);
         if (SyntaxTreeLoaded != null && node != null)
         {
             SyntaxTreeLoaded(this, new SyntaxLoadedArgs(node));
         }
     }
 }
Exemple #50
0
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var ifStatement = node as IfStatementSyntax;
            if (ifStatement == null || ifStatement.Else != null) return null;
            var trueBlock = ifStatement.Statement as BlockSyntax;
            if (trueBlock == null) return null;
            if (trueBlock.Statements.Count != 1) return null;
            if (!trueBlock.IsGuaranteedToJumpOut()) return null;
            var r = new ReadyCodeAction("Remove unnecessary braces", document, trueBlock, () => trueBlock.Statements.Single());

            return new[] {
                new CodeIssue(CodeIssue.Severity.Warning, trueBlock.OpenBraceToken.Span, "Unnecessary braces", new[] { r })
            };
        }
Exemple #51
0
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var typeSyntax = (TypeSyntax)node;
            if (!typeSyntax.IsVar)
                yield break;

            ISemanticModel semanticModel = document.GetSemanticModel();
            ITypeSymbol variableType = semanticModel.GetSemanticInfo(typeSyntax).Type;

            if (variableType is ErrorTypeSymbol)
                yield break;

            yield return new CodeIssue(CodeIssue.Severity.Info, typeSyntax.Span, new ICodeAction[] { new ReplaceVarByConcreteAction(editFactory, document, typeSyntax) });
        }
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var typedNode = (ClassDeclarationSyntax) node;
            if (!typedNode.BaseList.Types.Any(x => x.GetFirstToken().ValueText == "ApiController")) yield break;

            var methods = typedNode.Members.OfType<MethodDeclarationSyntax>().
                                    Where(x => (x.Identifier.ValueText.StartsWith("Post") || x.AttributeLists.Any(a => a.Attributes.Any(s => s.Name.ToString() == "HttpPost"))) && 
                                        x.ReturnType.GetType().IsAssignableFrom(typeof(PredefinedTypeSyntax)) && ((PredefinedTypeSyntax)x.ReturnType).Keyword.Kind == SyntaxKind.VoidKeyword);

            foreach (var method in methods)
            {
                yield return new CodeIssue(CodeIssueKind.Warning, method.ReturnType.Span, 
                    "Consider returning a 201 Status Code", new CodeAction(document, method));
            }
        }
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var model = document.GetSemanticModel();
            var b = (BinaryExpressionSyntax)node;
            var actions = GetSimplifications(b, model, Assumptions.All, cancellationToken)
                          .Select(e => e.AsCodeAction(document))
                          .ToArray();
            if (actions.Length == 0) yield break;

            yield return new CodeIssue(
                CodeIssue.Severity.Warning,
                b.OperatorToken.Span,
                "Boolean operation can be simplified.",
                actions);
        }
        private CommonSyntaxNode GetRootNode(CommonSyntaxToken token)
        {
            CommonSyntaxNode rootNode = null;

            if (token.SyntaxTree != null)
            {
                rootNode = token.SyntaxTree.GetRoot();
            }
            else
            {
                rootNode = GetRootNode(token.Parent);
            }

            return(rootNode);
        }
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var model = document.GetSemanticModel();
            var ternaryNode = (ConditionalExpressionSyntax)node;
            var actions = GetSimplifications(ternaryNode, model, Assumptions.All, cancellationToken)
                          .Select(e => e.AsCodeAction(document))
                          .ToArray();
            if (actions.Length == 0) yield break;

            yield return new CodeIssue(
                CodeIssue.Severity.Warning,
                ternaryNode.QuestionToken.Span,
                "Conditional expression simplifies into boolean expression.",
                actions);
        }
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            CommonSyntaxTree syntaxTree = document.GetSyntaxTree();
            SemanticModel semanticModel = (SemanticModel) document.GetSemanticModel();

            AnalysisResult result = _engine.Analyze(syntaxTree, semanticModel);

            if (!result.Success)
            {
                foreach (Issue issue in result.Issues)
                {
                    yield return new CodeIssue(CodeIssueKind.Error, issue.SyntaxNode.Span, issue.Description);
                }
            }
        }
        public static string GetKind(this CommonSyntaxNode node, string language)
        {
            var kind = string.Empty;

            if (language == LanguageNames.CSharp)
            {
                kind = ((CSharp.SyntaxKind)node.Kind).ToString();
            }
            else
            {
                kind = ((VisualBasic.SyntaxKind)node.Kind).ToString();
            }

            return(kind);
        }
Exemple #58
0
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var assume = Assumptions.All;
            var c = (StatementSyntax)node;
            if (!(c.Parent is BlockSyntax)) {
                if (c is EmptyStatementSyntax) return null;
                if (c is BlockSyntax && c.Statements().None()) return null;
            }

            if (c.HasSideEffects(document.TryGetSemanticModel(), assume) != false) return null;
            return new[] { new CodeIssue(CodeIssue.Severity.Warning, c.Span, "Statement without any effect", new[] { new ReadyCodeAction(
                "Remove Unnecessary Statement",
                document,
                c,
                () => c.Parent is BlockSyntax ? null : Syntax.EmptyStatement())})};
        }
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            editFactory = new CodeActionEdit(document);

            if (node.Kind == (int)SyntaxKind.CatchClause)
            {
                var CatchNode = (Roslyn.Compilers.CSharp.CatchClauseSyntax)node;
                if (CatchNode.Block.Statements.Count == 0 )
                {
                    var issueDescription = "Ouch! Do you really want to leave this CatchBlock empty? ";
                    yield return
                        new CodeIssue(CodeIssueKind.Error, node.Span, issueDescription,
                                        new AddThrowCodeAction(editFactory, document, node));
                }
            }
        }
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var methodDeclaration = (MethodDeclarationSyntax)node;

            if (methodDeclaration.AttributeLists.Any(a => a.Attributes.Any(at => at.Name.ToString() == "Fact")) &&
                !methodDeclaration.Identifier.ToString().IsUnderscoreCase()) // Not already underscore case
            {
                return new[] {
                    new CodeIssue(CodeIssueKind.Warning, methodDeclaration.Identifier.Span,
                    "Convert to underscore_case",
                    new CodeAction(document, methodDeclaration))
                };
            }

            return null;
        }