use of org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner in project intellij-community by JetBrains.
the class GroovyMethodInliner method inlineReferenceImpl.
@Nullable
static RangeMarker inlineReferenceImpl(@NotNull GrCallExpression call, @NotNull GrMethod method, boolean resultOfCallExplicitlyUsed, boolean isTailMethodCall, @Nullable Editor editor) {
try {
GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(call.getProject());
final Project project = call.getProject();
// Variable declaration for qualifier expression
GrVariableDeclaration qualifierDeclaration = null;
GrReferenceExpression innerQualifier = null;
GrExpression qualifier = null;
if (call instanceof GrMethodCallExpression && ((GrMethodCallExpression) call).getInvokedExpression() != null) {
GrExpression invoked = ((GrMethodCallExpression) call).getInvokedExpression();
if (invoked instanceof GrReferenceExpression && ((GrReferenceExpression) invoked).getQualifierExpression() != null) {
qualifier = ((GrReferenceExpression) invoked).getQualifierExpression();
if (PsiUtil.isSuperReference(qualifier)) {
qualifier = null;
} else if (!GroovyInlineMethodUtil.isSimpleReference(qualifier)) {
String qualName = generateQualifierName(call, method, project, qualifier);
qualifier = (GrExpression) PsiUtil.skipParentheses(qualifier, false);
qualifierDeclaration = factory.createVariableDeclaration(ArrayUtil.EMPTY_STRING_ARRAY, qualifier, null, qualName);
innerQualifier = (GrReferenceExpression) factory.createExpressionFromText(qualName);
} else {
innerQualifier = (GrReferenceExpression) qualifier;
}
}
}
GrMethod _method = prepareNewMethod(call, method, qualifier);
GrExpression result = getAloneResultExpression(_method);
if (result != null) {
GrExpression expression = call.replaceWithExpression(result, false);
TextRange range = expression.getTextRange();
return editor != null ? editor.getDocument().createRangeMarker(range.getStartOffset(), range.getEndOffset(), true) : null;
}
GrMethod newMethod = prepareNewMethod(call, method, innerQualifier);
String resultName = InlineMethodConflictSolver.suggestNewName("result", newMethod, call);
// Add variable for method result
Collection<GrStatement> returnStatements = ControlFlowUtils.collectReturns(newMethod.getBlock());
final int returnCount = returnStatements.size();
PsiType methodType = method.getInferredReturnType();
GrOpenBlock body = newMethod.getBlock();
assert body != null;
GrExpression replaced;
if (resultOfCallExplicitlyUsed && !isTailMethodCall) {
GrExpression resultExpr = null;
if (PsiType.VOID.equals(methodType)) {
resultExpr = factory.createExpressionFromText("null");
} else if (returnCount == 1) {
final GrExpression returnExpression = ControlFlowUtils.extractReturnExpression(returnStatements.iterator().next());
if (returnExpression != null) {
resultExpr = factory.createExpressionFromText(returnExpression.getText());
}
} else if (returnCount > 1) {
resultExpr = factory.createExpressionFromText(resultName);
}
if (resultExpr == null) {
resultExpr = factory.createExpressionFromText("null");
}
replaced = call.replaceWithExpression(resultExpr, false);
} else {
replaced = call;
}
// Calculate anchor to insert before
GrExpression enclosingExpr = GroovyRefactoringUtil.addBlockIntoParent(replaced);
GrVariableDeclarationOwner owner = PsiTreeUtil.getParentOfType(enclosingExpr, GrVariableDeclarationOwner.class);
assert owner != null;
PsiElement element = enclosingExpr;
while (element != null && element.getParent() != owner) {
element = element.getParent();
}
assert element != null && element instanceof GrStatement;
GrStatement anchor = (GrStatement) element;
if (!resultOfCallExplicitlyUsed) {
assert anchor == enclosingExpr;
}
// add qualifier reference declaration
if (qualifierDeclaration != null) {
owner.addVariableDeclarationBefore(qualifierDeclaration, anchor);
}
// Process method return statements
if (returnCount > 1 && !PsiType.VOID.equals(methodType) && !isTailMethodCall) {
PsiType type = methodType != null && methodType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) ? null : methodType;
GrVariableDeclaration resultDecl = factory.createVariableDeclaration(ArrayUtil.EMPTY_STRING_ARRAY, "", type, resultName);
GrStatement statement = ((GrStatementOwner) owner).addStatementBefore(resultDecl, anchor);
JavaCodeStyleManager.getInstance(statement.getProject()).shortenClassReferences(statement);
// Replace all return statements with assignments to 'result' variable
for (GrStatement returnStatement : returnStatements) {
GrExpression value = ControlFlowUtils.extractReturnExpression(returnStatement);
if (value != null) {
GrExpression assignment = factory.createExpressionFromText(resultName + " = " + value.getText());
returnStatement.replaceWithStatement(assignment);
} else {
returnStatement.replaceWithStatement(factory.createExpressionFromText(resultName + " = null"));
}
}
}
if (!isTailMethodCall && resultOfCallExplicitlyUsed && returnCount == 1) {
returnStatements.iterator().next().removeStatement();
} else if (!isTailMethodCall && (PsiType.VOID.equals(methodType) || returnCount == 1)) {
for (GrStatement returnStatement : returnStatements) {
if (returnStatement instanceof GrReturnStatement) {
final GrExpression returnValue = ((GrReturnStatement) returnStatement).getReturnValue();
if (returnValue != null && GroovyRefactoringUtil.hasSideEffect(returnValue)) {
returnStatement.replaceWithStatement(returnValue);
continue;
}
} else if (GroovyRefactoringUtil.hasSideEffect(returnStatement)) {
continue;
}
returnStatement.removeStatement();
}
}
// Add all method statements
GrStatement[] statements = body.getStatements();
for (GrStatement statement : statements) {
((GrStatementOwner) owner).addStatementBefore(statement, anchor);
}
if (resultOfCallExplicitlyUsed && !isTailMethodCall) {
TextRange range = replaced.getTextRange();
RangeMarker marker = editor != null ? editor.getDocument().createRangeMarker(range.getStartOffset(), range.getEndOffset(), true) : null;
reformatOwner(owner);
return marker;
} else {
GrStatement stmt;
if (isTailMethodCall && enclosingExpr.getParent() instanceof GrReturnStatement) {
stmt = (GrReturnStatement) enclosingExpr.getParent();
} else {
stmt = enclosingExpr;
}
stmt.removeStatement();
reformatOwner(owner);
return null;
}
} catch (IncorrectOperationException e) {
LOG.error(e);
}
return null;
}
use of org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner in project intellij-community by JetBrains.
the class GrIntroduceFieldProcessor method generateAssignment.
private void generateAssignment(@NotNull GrVariable field, @Nullable GrStatement anchor, @Nullable GrStatementOwner defaultContainer, @Nullable PsiElement occurrenceToDelete) {
if (myInitializer == null || defaultContainer == null)
return;
GrAssignmentExpression init = (GrAssignmentExpression) GroovyPsiElementFactory.getInstance(myContext.getProject()).createExpressionFromText(mySettings.getName() + " = " + myInitializer.getText());
GrStatementOwner block;
if (anchor != null) {
anchor = GroovyRefactoringUtil.addBlockIntoParent(anchor);
LOG.assertTrue(anchor.getParent() instanceof GrStatementOwner);
block = (GrStatementOwner) anchor.getParent();
} else {
block = defaultContainer;
}
init = (GrAssignmentExpression) block.addStatementBefore(init, anchor);
replaceOccurrence(field, init.getLValue(), (PsiClass) myContext.getScope());
if (occurrenceToDelete != null) {
occurrenceToDelete.delete();
}
}
use of org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner in project intellij-community by JetBrains.
the class GroovyExtractChooser method buildInfo.
@NotNull
private static InitialInfo buildInfo(@NotNull Project project, @NotNull PsiFile file, int start, int end, boolean forceStatements, @NotNull SelectionModel selectionModel, @Nullable GrVariable variable) throws GrRefactoringError {
PsiElement[] elements = getElementsInOffset(file, start, end, forceStatements);
//if (elements.length == 1 && elements[0] instanceof GrExpression) {
// selectionModel.setSelection(start, elements[0].getTextRange().getEndOffset());
//}
GrStatement[] statements = getStatementsByElements(elements);
if (statements.length == 0) {
throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.block.should.represent.a.statement.set"));
}
for (GrStatement statement : statements) {
if (GroovyRefactoringUtil.isSuperOrThisCall(statement, true, true)) {
throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.block.contains.invocation.of.another.class.constructor"));
}
}
GrStatement statement0 = statements[0];
PsiClass owner = PsiUtil.getContextClass(statement0);
GrStatementOwner declarationOwner = GroovyRefactoringUtil.getDeclarationOwner(statement0);
if (owner == null || declarationOwner == null && !ExtractUtil.isSingleExpression(statements)) {
throw new GrRefactoringError(GroovyRefactoringBundle.message("refactoring.is.not.supported.in.the.current.context"));
}
if (declarationOwner == null && ExtractUtil.isSingleExpression(statements) && statement0 instanceof GrExpression && PsiType.VOID.equals(((GrExpression) statement0).getType())) {
throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.expression.has.void.type"));
}
if (ExtractUtil.isSingleExpression(statements) && GrIntroduceHandlerBase.expressionIsIncorrect((GrExpression) statement0, true)) {
throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.block.should.represent.an.expression"));
}
if (ExtractUtil.isSingleExpression(statements) && statement0.getParent() instanceof GrAssignmentExpression && ((GrAssignmentExpression) statement0.getParent()).getLValue() == statement0) {
throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.expression.should.not.be.lvalue"));
}
// collect information about return statements in selected statement set
Set<GrStatement> allReturnStatements = new HashSet<>();
GrControlFlowOwner controlFlowOwner = ControlFlowUtils.findControlFlowOwner(statement0);
LOG.assertTrue(controlFlowOwner != null);
final Instruction[] flow = new ControlFlowBuilder(project, GrAllVarsInitializedPolicy.getInstance()).buildControlFlow(controlFlowOwner);
allReturnStatements.addAll(ControlFlowUtils.collectReturns(flow, true));
ArrayList<GrStatement> returnStatements = new ArrayList<>();
for (GrStatement returnStatement : allReturnStatements) {
for (GrStatement statement : statements) {
if (PsiTreeUtil.isAncestor(statement, returnStatement, false)) {
returnStatements.add(returnStatement);
break;
}
}
}
// collect information about variables in selected block
FragmentVariableInfos fragmentVariableInfos = ReachingDefinitionsCollector.obtainVariableFlowInformation(statement0, statements[statements.length - 1], controlFlowOwner, flow);
VariableInfo[] inputInfos = fragmentVariableInfos.getInputVariableNames();
VariableInfo[] outputInfos = fragmentVariableInfos.getOutputVariableNames();
if (outputInfos.length == 1 && !returnStatements.isEmpty()) {
throw new GrRefactoringError(GroovyRefactoringBundle.message("multiple.output.values"));
}
boolean hasInterruptingStatements = false;
for (GrStatement statement : statements) {
hasInterruptingStatements = GroovyRefactoringUtil.hasWrongBreakStatements(statement) || GroovyRefactoringUtil.hasWrongContinueStatements(statement);
if (hasInterruptingStatements)
break;
}
// must be replaced by return statement
boolean hasReturns = !returnStatements.isEmpty();
List<GrStatement> returnStatementsCopy = new ArrayList<>(returnStatements.size());
returnStatementsCopy.addAll(returnStatements);
boolean isReturnStatement = isReturnStatement(statements[statements.length - 1], returnStatementsCopy);
boolean isLastStatementOfMethod = isLastStatementOfMethodOrClosure(statements);
if (hasReturns && !isLastStatementOfMethod && !isReturnStatement || hasInterruptingStatements) {
throw new GrRefactoringError(GroovyRefactoringBundle.message("refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow"));
}
return new InitialInfo(inputInfos, outputInfos, elements, statements, returnStatements, null, project, variable);
}
use of org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner in project intellij-community by JetBrains.
the class GroovyExtractChooser method isLastStatementOfMethodOrClosure.
private static boolean isLastStatementOfMethodOrClosure(GrStatement[] statements) {
final GrStatement statement0 = statements[0];
PsiElement returnFrom = PsiTreeUtil.getParentOfType(statement0, GrMethod.class, GrClosableBlock.class, GroovyFile.class);
if (returnFrom instanceof GrMethod) {
returnFrom = ((GrMethod) returnFrom).getBlock();
}
LOG.assertTrue(returnFrom instanceof GrStatementOwner);
final GrStatement[] blockStatements = ((GrStatementOwner) returnFrom).getStatements();
final GrStatement lastFromBlock = ArrayUtil.getLastElement(blockStatements);
final GrStatement lastStatement = ArrayUtil.getLastElement(statements);
return statement0.getManager().areElementsEquivalent(lastFromBlock, lastStatement);
}
use of org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner in project intellij-community by JetBrains.
the class GroovyAnnotator method visitTypeDefinitionBody.
@Override
public void visitTypeDefinitionBody(@NotNull GrTypeDefinitionBody typeDefinitionBody) {
final PsiElement parent = typeDefinitionBody.getParent();
if (!(parent instanceof GrAnonymousClassDefinition))
return;
final PsiElement prev = typeDefinitionBody.getPrevSibling();
if (!PsiUtil.isLineFeed(prev))
return;
final PsiElement newExpression = parent.getParent();
if (!(newExpression instanceof GrNewExpression))
return;
final GrStatementOwner statementOwner = PsiTreeUtil.getParentOfType(newExpression, GrStatementOwner.class);
final GrParenthesizedExpression parenthesizedExpression = PsiTreeUtil.getParentOfType(newExpression, GrParenthesizedExpression.class);
if (parenthesizedExpression != null && PsiTreeUtil.isAncestor(statementOwner, parenthesizedExpression, true))
return;
final GrArgumentList argumentList = PsiTreeUtil.getParentOfType(newExpression, GrArgumentList.class);
if (argumentList != null && !(argumentList instanceof GrCommandArgumentList)) {
if (PsiTreeUtil.isAncestor(statementOwner, argumentList, true))
return;
}
myHolder.createErrorAnnotation(typeDefinitionBody, GroovyBundle.message("ambiguous.code.block"));
}
Aggregations