public CodeRefactoring GetRefactoring(IDocument document, TextSpan textSpan, CancellationToken cancellationToken)
        {
            var tree = (SyntaxTree)document.GetSyntaxTree(cancellationToken);
            var token = tree.GetRoot().FindToken(textSpan.Start);

            if (token.Parent is ClassDeclarationSyntax || token.Parent is StructDeclarationSyntax) {
                var t = (TypeDeclarationSyntax)token.Parent;
                if (!CanInferNonTrivialConstructor(t)) return null;
                return new CodeRefactoring(new[] { new ReadyCodeAction("Infer Non-Trivial Constructor", document, t, () => {
                    var c = TryInferNonTrivialConstructor(t, document.TryGetSemanticModel());
                    var i = 0;
                    var ms = t.Members.Insert(i, new[] {c}).List();
                    return t.With(members: ms);
                })});
            }

            if (token.Parent is MemberDeclarationSyntax && (token.Parent.Parent is ClassDeclarationSyntax || token.Parent.Parent is StructDeclarationSyntax)) {
                var m = (MemberDeclarationSyntax)token.Parent;
                var t = (TypeDeclarationSyntax)m.Parent;
                if (!CanInferNonTrivialConstructor(t)) return null;
                return new CodeRefactoring(new[] { new ReadyCodeAction("Infer Non-Trivial Constructor Here", document, t, () => {
                    var c = TryInferNonTrivialConstructor(t, document.TryGetSemanticModel());
                    var i = t.Members.IndexOf(m);
                    var ms = t.Members.Insert(i, new[] {c}).List();
                    return t.With(members: ms);
                })});
            }

            return null;
        }
Exemplo n.º 2
0
 /* Check the preconditions of rename refactoring, return true if can be finished succesfully. */
 public static bool CheckRenamePreconditions(IDocument document, int start, int length)
 {
     var service = ServiceArchive.getInstance().RenameService;
     ISemanticModel model;
     document.TryGetSemanticModel(out model);
     return false;
 }
        public CodeRefactoring GetRefactoring(IDocument document, TextSpan textSpan, CancellationToken cancellationToken)
        {
            var tree = (SyntaxTree)document.GetSyntaxTree(cancellationToken);
            var root = tree.GetRoot(cancellationToken);
            var token = tree.GetRoot().FindToken(textSpan.Start);
            var m = token.Parent as MethodDeclarationSyntax;
            if (m == null) return null;
            var model = document.TryGetSemanticModel();
            if (model == null) return null;

            return new CodeRefactoring(new[] { new ReadyCodeAction(
                "Remove method and calls to method (including any side-effects in arguments)",
                document,
                root,
                () => document.NewRootForNukeMethodAndAnySideEffectsInArguments(m))});
        }
Exemplo n.º 4
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())})};
        }
Exemplo n.º 5
0
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var model = document.TryGetSemanticModel();
            if (model == null) return null;
            if (model.GetDiagnostics().Any(e => e.Info.Severity == DiagnosticSeverity.Error)) return null;
            if (document.Project.Documents.Any(e => e.GetSyntaxTree() == null || e.GetSemanticModel() == null)) return null;

            var fieldNode = (FieldDeclarationSyntax)node;
            if (fieldNode.IsReadOnly()) return null;

            var classDecl = fieldNode.Ancestors().OfType<ClassDeclarationSyntax>().FirstOrDefault();
            if (classDecl == null) return null;
            var constructors = classDecl.Members.OfType<ConstructorDeclarationSyntax>().ToRet();

            var modsWithReadOnly = fieldNode.Modifiers.Append(SyntaxKind.ReadOnlyKeyword.AsToken()).AsTokenList();

            var scopes = fieldNode.IsPrivate()
                       ? new[] {Tuple.Create((CommonSyntaxNode)classDecl, model)}
                       : document.Project.Documents.Select(e => Tuple.Create(e.GetSyntaxTree().GetRoot(), e.GetSemanticModel()));

            var unmutatedVars = fieldNode.Declaration.Variables.Where(v => {
                var field = model.GetDeclaredSymbol(v);
                if (scopes.Any(c => c.Item1.DescendantNodes(e => !constructors.Contains(e)).OfType<ExpressionSyntax>().Any(e => SurfaceWritesTo(e, c.Item2, field)))) return false;
                return true;
            }).ToArray();

            if (unmutatedVars.Length == 0) return null;
            if (unmutatedVars.Length == fieldNode.Declaration.Variables.Count) {
                var r = new ReadyCodeAction("Make readonly", document, fieldNode, () => fieldNode.WithModifiers(modsWithReadOnly));
                var desc = unmutatedVars.Length == 1 ? "Mutable field is never modified." : "Mutable fields are never modified.";
                return r.CodeIssues1(CodeIssue.Severity.Warning, fieldNode.Declaration.Type.Span, desc);
            }

            return unmutatedVars.Select(v => {
                var singleReadOnly = fieldNode.WithModifiers(modsWithReadOnly)
                                              .WithDeclaration(fieldNode.Declaration.WithVariables(v.SepList1()));
                var rest = fieldNode
                           .WithLeadingTrivia()
                           .WithTrailingTrivia(Syntax.Whitespace(Environment.NewLine))
                           .WithDeclaration(fieldNode.Declaration.WithVariables(fieldNode.Declaration.Variables.Without(v)));
                var newClassDecl = classDecl.With(members: classDecl.Members.WithItemReplacedByMany(fieldNode, new[] { singleReadOnly, rest }));
                var action = new ReadyCodeAction("Split readonly", document, classDecl, () => newClassDecl);
                return new CodeIssue(CodeIssue.Severity.Warning, v.Identifier.Span, "Mutable field is never modified.", new[] { action });
            }).ToArray();
        }
Exemplo n.º 6
0
        public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken)
        {
            var forLoop = (ForEachStatementSyntax)node;
            var model = document.TryGetSemanticModel();
            if (model == null) return null;

            // list created just before loop starts?
            var initStatement = forLoop.TryGetPrevStatement();
            var lhs = initStatement.TryGetLHSExpOfAssignmentOrInit() as IdentifierNameSyntax;
            if (lhs == null) return null;
            var target = lhs.Identifier;
            var rhs = initStatement.TryGetRHSOfAssignmentOrInit() as ObjectCreationExpressionSyntax;
            if (rhs == null) return null;
            var cr = model.GetTypeInfo(rhs).Type;
            if (cr.AllInterfaces.All(e => e.Name != "IList")) return null;

            // loop adds things directly into the list?
            var adderStatement = forLoop.Statement.Statements().SingleOrDefaultAllowMany() as ExpressionStatementSyntax;
            if (adderStatement == null) return null;
            var adderInvoke = adderStatement.Expression as InvocationExpressionSyntax;
            if (adderInvoke == null) return null;
            var adderAccess = adderInvoke.Expression as MemberAccessExpressionSyntax;
            if (adderAccess == null) return null;
            var adderTarget = adderAccess.Expression as IdentifierNameSyntax;
            if (adderTarget == null) return null;
            if (adderTarget.PlainName != target.ValueText) return null;
            if (adderAccess.Name.PlainName != "Add") return null;
            if (adderInvoke.ArgumentList.Arguments.Count != 1) return null;
            var adderExp = adderInvoke.ArgumentList.Arguments.Single().Expression as SimpleNameSyntax;
            if (adderExp == null) return null;
            if (adderExp.PlainName != forLoop.Identifier.ValueText) return null;

            var linqed = forLoop.Expression.Accessing("ToList").Invoking();
            var replacedInit = initStatement.TryWithNewRightHandSideOfAssignmentOrSingleInit(linqed);

            var action = new ReadyCodeAction(
                "Select into list",
                document,
                new[] { initStatement, forLoop },
                (e, a) => e == initStatement ? replacedInit : a.Dropped());
            return action.CodeIssues1(
                CodeIssue.Severity.Warning,
                forLoop.ForEachKeyword.Span,
                "Initializing a list with a 'for each' loop.");
        }