Search in sources :

Example 1 with CUCorrectionCommandProposal

use of org.eclipse.jdt.ls.core.internal.text.correction.CUCorrectionCommandProposal in project eclipse.jdt.ls by eclipse.

the class CodeActionHandler method getCodeActionFromProposal.

private Optional<Either<Command, CodeAction>> getCodeActionFromProposal(ChangeCorrectionProposal proposal, CodeActionContext context) throws CoreException {
    String name = proposal.getName();
    Command command = null;
    if (proposal instanceof CUCorrectionCommandProposal) {
        CUCorrectionCommandProposal commandProposal = (CUCorrectionCommandProposal) proposal;
        command = new Command(name, commandProposal.getCommand(), commandProposal.getCommandArguments());
    } else if (proposal instanceof RefactoringCorrectionCommandProposal) {
        RefactoringCorrectionCommandProposal commandProposal = (RefactoringCorrectionCommandProposal) proposal;
        command = new Command(name, commandProposal.getCommand(), commandProposal.getCommandArguments());
    } else if (proposal instanceof AssignToVariableAssistCommandProposal) {
        AssignToVariableAssistCommandProposal commandProposal = (AssignToVariableAssistCommandProposal) proposal;
        command = new Command(name, commandProposal.getCommand(), commandProposal.getCommandArguments());
    } else {
        if (!this.preferenceManager.getClientPreferences().isResolveCodeActionSupported()) {
            WorkspaceEdit edit = ChangeUtil.convertToWorkspaceEdit(proposal.getChange());
            if (!ChangeUtil.hasChanges(edit)) {
                return Optional.empty();
            }
            command = new Command(name, COMMAND_ID_APPLY_EDIT, Collections.singletonList(edit));
        }
    }
    if (preferenceManager.getClientPreferences().isSupportedCodeActionKind(proposal.getKind())) {
        // TODO: Should set WorkspaceEdit directly instead of Command
        CodeAction codeAction = new CodeAction(name);
        codeAction.setKind(proposal.getKind());
        if (command == null) {
            // lazy resolve the edit.
            codeAction.setData(proposal);
        } else {
            codeAction.setCommand(command);
        }
        codeAction.setDiagnostics(context.getDiagnostics());
        return Optional.of(Either.forRight(codeAction));
    } else {
        return Optional.of(Either.forLeft(command));
    }
}
Also used : Command(org.eclipse.lsp4j.Command) CodeAction(org.eclipse.lsp4j.CodeAction) CUCorrectionCommandProposal(org.eclipse.jdt.ls.core.internal.text.correction.CUCorrectionCommandProposal) RefactoringCorrectionCommandProposal(org.eclipse.jdt.ls.core.internal.text.correction.RefactoringCorrectionCommandProposal) WorkspaceEdit(org.eclipse.lsp4j.WorkspaceEdit) AssignToVariableAssistCommandProposal(org.eclipse.jdt.ls.core.internal.text.correction.AssignToVariableAssistCommandProposal)

Example 2 with CUCorrectionCommandProposal

use of org.eclipse.jdt.ls.core.internal.text.correction.CUCorrectionCommandProposal in project eclipse.jdt.ls by eclipse.

the class InvertBooleanUtility method getInvertVariableProposal.

public static ChangeCorrectionProposal getInvertVariableProposal(CodeActionParams params, IInvocationContext context, ASTNode covering, boolean returnAsCommand) {
    // cursor should be placed on variable name
    if (!(covering instanceof SimpleName)) {
        return null;
    }
    SimpleName coveringName = (SimpleName) covering;
    if (!coveringName.isDeclaration()) {
        return null;
    }
    // prepare bindings
    final IBinding variableBinding = coveringName.resolveBinding();
    if (!(variableBinding instanceof IVariableBinding)) {
        return null;
    }
    IVariableBinding binding = (IVariableBinding) variableBinding;
    if (binding.isField()) {
        return null;
    }
    // we operate only on boolean variable
    if (!isBoolean(coveringName)) {
        return null;
    }
    String label = CorrectionMessages.AdvancedQuickAssistProcessor_inverseBooleanVariable;
    if (returnAsCommand) {
        return new CUCorrectionCommandProposal(label, CodeActionKind.Refactor, context.getCompilationUnit(), IProposalRelevance.INVERSE_BOOLEAN_VARIABLE, RefactorProposalUtility.APPLY_REFACTORING_COMMAND_ID, Arrays.asList(INVERT_VARIABLE_COMMAND, params));
    }
    final AST ast = covering.getAST();
    // find linked nodes
    final MethodDeclaration method = ASTResolving.findParentMethodDeclaration(covering);
    SimpleName[] linkedNodes = LinkedNodeFinder.findByBinding(method, variableBinding);
    // 
    final ASTRewrite rewrite = ASTRewrite.create(ast);
    // create proposal
    // $NON-NLS-1$
    final String KEY_NAME = "name";
    final LinkedCorrectionProposal proposal = new LinkedCorrectionProposal(label, CodeActionKind.Refactor, context.getCompilationUnit(), rewrite, IProposalRelevance.INVERSE_BOOLEAN_VARIABLE);
    // prepare new variable identifier
    final String oldIdentifier = coveringName.getIdentifier();
    // $NON-NLS-1$
    final String notString = Messages.format(CorrectionMessages.AdvancedQuickAssistProcessor_negatedVariableName, "");
    final String newIdentifier;
    if (oldIdentifier.startsWith(notString)) {
        int notLength = notString.length();
        if (oldIdentifier.length() > notLength) {
            newIdentifier = Character.toLowerCase(oldIdentifier.charAt(notLength)) + oldIdentifier.substring(notLength + 1);
        } else {
            newIdentifier = oldIdentifier;
        }
    } else {
        newIdentifier = Messages.format(CorrectionMessages.AdvancedQuickAssistProcessor_negatedVariableName, Character.toUpperCase(oldIdentifier.charAt(0)) + oldIdentifier.substring(1));
    }
    // 
    proposal.addLinkedPositionProposal(KEY_NAME, newIdentifier);
    proposal.addLinkedPositionProposal(KEY_NAME, oldIdentifier);
    // iterate over linked nodes and replace variable references with negated reference
    final HashSet<SimpleName> renamedNames = new HashSet<>();
    for (int i = 0; i < linkedNodes.length; i++) {
        SimpleName name = linkedNodes[i];
        if (renamedNames.contains(name)) {
            continue;
        }
        // prepare new name with new identifier
        SimpleName newName = ast.newSimpleName(newIdentifier);
        proposal.addLinkedPosition(rewrite.track(newName), name == coveringName, KEY_NAME);
        // 
        StructuralPropertyDescriptor location = name.getLocationInParent();
        if (location == SingleVariableDeclaration.NAME_PROPERTY) {
            // set new name
            rewrite.replace(name, newName, null);
        } else if (location == Assignment.LEFT_HAND_SIDE_PROPERTY) {
            Assignment assignment = (Assignment) name.getParent();
            Expression expression = assignment.getRightHandSide();
            int exStart = expression.getStartPosition();
            int exEnd = exStart + expression.getLength();
            // collect all names that are used in assignments
            HashSet<SimpleName> overlapNames = new HashSet<>();
            for (int j = 0; j < linkedNodes.length; j++) {
                SimpleName name2 = linkedNodes[j];
                if (name2 == null) {
                    continue;
                }
                int name2Start = name2.getStartPosition();
                if (exStart <= name2Start && name2Start < exEnd) {
                    overlapNames.add(name2);
                }
            }
            // prepare inverted expression
            SimpleNameRenameProvider provider = new SimpleNameRenameProvider() {

                @Override
                public SimpleName getRenamed(SimpleName simpleName) {
                    if (simpleName.resolveBinding() == variableBinding) {
                        renamedNames.add(simpleName);
                        return ast.newSimpleName(newIdentifier);
                    }
                    return null;
                }
            };
            Expression inversedExpression = getInversedExpression(rewrite, expression, provider);
            // if any name was not renamed during expression inverting, we can not already rename it, so fail to create assist
            for (Iterator<SimpleName> iter = overlapNames.iterator(); iter.hasNext(); ) {
                Object o = iter.next();
                if (!renamedNames.contains(o)) {
                    return null;
                }
            }
            // check operator and replace if needed
            Assignment.Operator operator = assignment.getOperator();
            if (operator == Assignment.Operator.BIT_AND_ASSIGN) {
                Assignment newAssignment = ast.newAssignment();
                newAssignment.setLeftHandSide(newName);
                newAssignment.setRightHandSide(inversedExpression);
                newAssignment.setOperator(Assignment.Operator.BIT_OR_ASSIGN);
                rewrite.replace(assignment, newAssignment, null);
            } else if (operator == Assignment.Operator.BIT_OR_ASSIGN) {
                Assignment newAssignment = ast.newAssignment();
                newAssignment.setLeftHandSide(newName);
                newAssignment.setRightHandSide(inversedExpression);
                newAssignment.setOperator(Assignment.Operator.BIT_AND_ASSIGN);
                rewrite.replace(assignment, newAssignment, null);
            } else {
                rewrite.replace(expression, inversedExpression, null);
                // set new name
                rewrite.replace(name, newName, null);
            }
        } else if (location == VariableDeclarationFragment.NAME_PROPERTY) {
            // replace initializer for variable
            VariableDeclarationFragment vdf = (VariableDeclarationFragment) name.getParent();
            Expression expression = vdf.getInitializer();
            if (expression != null) {
                rewrite.replace(expression, getInversedExpression(rewrite, expression), null);
            }
            // set new name
            rewrite.replace(name, newName, null);
        } else if (name.getParent() instanceof PrefixExpression && ((PrefixExpression) name.getParent()).getOperator() == PrefixExpression.Operator.NOT) {
            rewrite.replace(name.getParent(), newName, null);
        } else {
            PrefixExpression expression = ast.newPrefixExpression();
            expression.setOperator(PrefixExpression.Operator.NOT);
            expression.setOperand(newName);
            rewrite.replace(name, expression, null);
        }
    }
    return proposal;
}
Also used : Operator(org.eclipse.jdt.core.dom.InfixExpression.Operator) AST(org.eclipse.jdt.core.dom.AST) MethodDeclaration(org.eclipse.jdt.core.dom.MethodDeclaration) SimpleName(org.eclipse.jdt.core.dom.SimpleName) IBinding(org.eclipse.jdt.core.dom.IBinding) CUCorrectionCommandProposal(org.eclipse.jdt.ls.core.internal.text.correction.CUCorrectionCommandProposal) IVariableBinding(org.eclipse.jdt.core.dom.IVariableBinding) Assignment(org.eclipse.jdt.core.dom.Assignment) ConditionalExpression(org.eclipse.jdt.core.dom.ConditionalExpression) InstanceofExpression(org.eclipse.jdt.core.dom.InstanceofExpression) Expression(org.eclipse.jdt.core.dom.Expression) InfixExpression(org.eclipse.jdt.core.dom.InfixExpression) ParenthesizedExpression(org.eclipse.jdt.core.dom.ParenthesizedExpression) PrefixExpression(org.eclipse.jdt.core.dom.PrefixExpression) LinkedCorrectionProposal(org.eclipse.jdt.ls.core.internal.corrections.proposals.LinkedCorrectionProposal) VariableDeclarationFragment(org.eclipse.jdt.core.dom.VariableDeclarationFragment) PrefixExpression(org.eclipse.jdt.core.dom.PrefixExpression) Iterator(java.util.Iterator) ASTRewrite(org.eclipse.jdt.core.dom.rewrite.ASTRewrite) HashSet(java.util.HashSet) StructuralPropertyDescriptor(org.eclipse.jdt.core.dom.StructuralPropertyDescriptor)

Aggregations

CUCorrectionCommandProposal (org.eclipse.jdt.ls.core.internal.text.correction.CUCorrectionCommandProposal)2 HashSet (java.util.HashSet)1 Iterator (java.util.Iterator)1 AST (org.eclipse.jdt.core.dom.AST)1 Assignment (org.eclipse.jdt.core.dom.Assignment)1 ConditionalExpression (org.eclipse.jdt.core.dom.ConditionalExpression)1 Expression (org.eclipse.jdt.core.dom.Expression)1 IBinding (org.eclipse.jdt.core.dom.IBinding)1 IVariableBinding (org.eclipse.jdt.core.dom.IVariableBinding)1 InfixExpression (org.eclipse.jdt.core.dom.InfixExpression)1 Operator (org.eclipse.jdt.core.dom.InfixExpression.Operator)1 InstanceofExpression (org.eclipse.jdt.core.dom.InstanceofExpression)1 MethodDeclaration (org.eclipse.jdt.core.dom.MethodDeclaration)1 ParenthesizedExpression (org.eclipse.jdt.core.dom.ParenthesizedExpression)1 PrefixExpression (org.eclipse.jdt.core.dom.PrefixExpression)1 SimpleName (org.eclipse.jdt.core.dom.SimpleName)1 StructuralPropertyDescriptor (org.eclipse.jdt.core.dom.StructuralPropertyDescriptor)1 VariableDeclarationFragment (org.eclipse.jdt.core.dom.VariableDeclarationFragment)1 ASTRewrite (org.eclipse.jdt.core.dom.rewrite.ASTRewrite)1 LinkedCorrectionProposal (org.eclipse.jdt.ls.core.internal.corrections.proposals.LinkedCorrectionProposal)1