2 * Copyright 2000-2011 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.jetbrains.plugins.groovy.refactoring;
19 import com.intellij.codeInsight.PsiEquivalenceUtil;
20 import com.intellij.codeInsight.highlighting.HighlightManager;
21 import com.intellij.lang.Language;
22 import com.intellij.openapi.diagnostic.Logger;
23 import com.intellij.openapi.editor.Editor;
24 import com.intellij.openapi.editor.colors.EditorColors;
25 import com.intellij.openapi.editor.colors.EditorColorsManager;
26 import com.intellij.openapi.editor.markup.RangeHighlighter;
27 import com.intellij.openapi.editor.markup.TextAttributes;
28 import com.intellij.openapi.project.Project;
29 import com.intellij.openapi.util.Ref;
30 import com.intellij.openapi.util.TextRange;
31 import com.intellij.openapi.util.text.StringUtil;
32 import com.intellij.psi.*;
33 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
34 import com.intellij.psi.impl.source.tree.LeafPsiElement;
35 import com.intellij.psi.tree.IElementType;
36 import com.intellij.psi.util.MethodSignature;
37 import com.intellij.psi.util.PsiTreeUtil;
38 import com.intellij.psi.util.PsiUtilCore;
39 import com.intellij.util.ArrayUtil;
40 import com.intellij.util.IncorrectOperationException;
41 import com.intellij.util.ReflectionCache;
42 import com.intellij.util.containers.ContainerUtil;
43 import org.jetbrains.annotations.NotNull;
44 import org.jetbrains.annotations.Nullable;
45 import org.jetbrains.plugins.groovy.GroovyFileType;
46 import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
47 import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
48 import org.jetbrains.plugins.groovy.lang.psi.*;
49 import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
50 import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
51 import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
52 import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
53 import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrBreakStatement;
54 import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrContinueStatement;
55 import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
56 import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseSection;
57 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
58 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection;
59 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression;
60 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
61 import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
62 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
63 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
64 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
65 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
66 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList;
67 import org.jetbrains.plugins.groovy.lang.psi.api.util.GrDeclarationHolder;
68 import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
69 import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner;
73 import static com.intellij.refactoring.util.RefactoringUtil.*;
74 import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.isNewLine;
75 import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.skipParentheses;
80 public abstract class GroovyRefactoringUtil {
81 private static final Logger LOG = Logger.getInstance(GroovyRefactoringUtil.class);
83 public static final Collection<String> KEYWORDS = ContainerUtil.map(
84 TokenSets.KEYWORDS.getTypes(), StringUtil.createToStringFunction(IElementType.class));
86 private static final String[] finalModifiers = new String[]{PsiModifier.FINAL};
89 public static PsiElement getEnclosingContainer(PsiElement place) {
90 PsiElement parent = place.getParent();
95 if (parent instanceof GrDeclarationHolder && !(parent instanceof GrClosableBlock && parent.getParent() instanceof GrStringInjection)) {
98 if (parent instanceof GrLoopStatement) {
102 parent = parent.getParent();
107 public static <T extends PsiElement> T findElementInRange(final PsiFile file,
110 final Class<T> klass) {
111 PsiElement element1 = file.getViewProvider().findElementAt(startOffset, file.getLanguage());
112 PsiElement element2 = file.getViewProvider().findElementAt(endOffset - 1, file.getLanguage());
113 if (element1 == null) return null;
115 if (TokenSets.WHITE_SPACES_SET.contains(element1.getNode().getElementType())) {
116 startOffset = element1.getTextRange().getEndOffset();
117 element1 = file.getViewProvider().findElementAt(startOffset, file.getLanguage());
119 if (TokenSets.WHITE_SPACES_SET.contains(element2.getNode().getElementType())) {
120 endOffset = element2.getTextRange().getStartOffset();
121 element2 = file.getViewProvider().findElementAt(endOffset - 1, file.getLanguage());
123 if (element2 == null || element1 == null) return null;
124 final PsiElement commonParent = PsiTreeUtil.findCommonParent(element1, element2);
125 assert commonParent != null;
126 final T element = ReflectionCache.isAssignable(klass, commonParent.getClass()) ? (T) commonParent : PsiTreeUtil.getParentOfType(commonParent, klass);
127 if (element == null || element.getTextRange().getStartOffset() != startOffset) {
133 public static PsiElement[] getExpressionOccurrences(@NotNull PsiElement expr, @NotNull PsiElement scope) {
134 ArrayList<PsiElement> occurrences = new ArrayList<PsiElement>();
135 Comparator<PsiElement> comparator = new Comparator<PsiElement>() {
136 public int compare(PsiElement element1, PsiElement element2) {
137 if (element1.equals(element2)) return 0;
139 if (element1 instanceof GrParameter &&
140 element2 instanceof GrParameter) {
141 final String name1 = ((GrParameter) element1).getName();
142 final String name2 = ((GrParameter) element2).getName();
143 return name1.compareTo(name2);
149 if (scope instanceof GrLoopStatement) {
150 PsiElement son = expr;
151 while (son.getParent() != null && !(son.getParent() instanceof GrLoopStatement)) {
152 son = son.getParent();
154 assert scope.equals(son.getParent());
155 collectOccurrences(expr, son, occurrences, comparator, false);
157 collectOccurrences(expr, scope, occurrences, comparator, scope instanceof GrTypeDefinition || scope instanceof GroovyFileBase);
159 return PsiUtilCore.toPsiElementArray(occurrences);
163 private static void collectOccurrences(@NotNull PsiElement expr, @NotNull PsiElement scope, @NotNull ArrayList<PsiElement> acc, Comparator<PsiElement> comparator, boolean goIntoInner) {
164 if (scope.equals(expr)) {
168 for (PsiElement child : scope.getChildren()) {
169 if (goIntoInner || !(child instanceof GrTypeDefinition) && !(child instanceof GrMethod && scope instanceof GroovyFileBase)) {
170 if (PsiEquivalenceUtil.areElementsEquivalent(child, expr, comparator, false)) {
173 collectOccurrences(expr, child, acc, comparator, goIntoInner);
180 public static boolean isAppropriateContainerForIntroduceVariable(PsiElement tempContainer) {
181 return tempContainer instanceof GrOpenBlock ||
182 tempContainer instanceof GrClosableBlock ||
183 tempContainer instanceof GroovyFileBase ||
184 tempContainer instanceof GrCaseSection ||
185 tempContainer instanceof GrLoopStatement ||
186 tempContainer instanceof GrIfStatement;
189 public static void sortOccurrences(PsiElement[] occurrences) {
190 Arrays.sort(occurrences, new Comparator<PsiElement>() {
191 public int compare(PsiElement elem1, PsiElement elem2) {
192 final int offset1 = elem1.getTextRange().getStartOffset();
193 final int offset2 = elem2.getTextRange().getStartOffset();
194 return offset1 - offset2;
199 public static boolean isLocalVariable(GrVariable variable) {
200 return !(variable instanceof GrField || variable instanceof GrParameter);
204 public static void highlightOccurrences(Project project, Editor editor, PsiElement[] elements) {
205 if (editor == null) return;
206 ArrayList<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
207 HighlightManager highlightManager = HighlightManager.getInstance(project);
208 EditorColorsManager colorsManager = EditorColorsManager.getInstance();
209 TextAttributes attributes = colorsManager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
210 if (elements.length > 0) {
211 highlightManager.addOccurrenceHighlights(editor, elements, attributes, false, highlighters);
215 public static void highlightOccurrencesByRanges(Project project, Editor editor, TextRange[] ranges) {
216 if (editor == null) return;
217 ArrayList<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
218 HighlightManager highlightManager = HighlightManager.getInstance(project);
219 EditorColorsManager colorsManager = EditorColorsManager.getInstance();
220 TextAttributes attributes = colorsManager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
221 for (TextRange range : ranges) {
222 highlightManager.addRangeHighlight(editor, range.getStartOffset(), range.getEndOffset(), attributes, false, highlighters);
226 public static void trimSpacesAndComments(Editor editor, PsiFile file, boolean trimComments) {
227 int start = editor.getSelectionModel().getSelectionStart();
228 int end = editor.getSelectionModel().getSelectionEnd();
229 while (file.findElementAt(start) instanceof PsiWhiteSpace ||
230 (file.findElementAt(start) instanceof PsiComment && trimComments) ||
231 (file.findElementAt(start) != null &&
232 GroovyTokenTypes.mNLS.equals(file.findElementAt(start).getNode().getElementType()))) {
235 while (file.findElementAt(end - 1) instanceof PsiWhiteSpace ||
236 (file.findElementAt(end - 1) instanceof PsiComment && trimComments) ||
237 (file.findElementAt(end - 1) != null &&
238 (GroovyTokenTypes.mNLS.equals(file.findElementAt(end - 1).getNode().getElementType()) ||
239 GroovyTokenTypes.mSEMI.equals(file.findElementAt(end - 1).getNode().getElementType())))) {
243 editor.getSelectionModel().setSelection(start, end);
246 @NotNull public static PsiElement[] findStatementsInRange(PsiFile file, int startOffset, int endOffset, boolean strict) {
247 if (!(file instanceof GroovyFileBase)) return PsiElement.EMPTY_ARRAY;
248 Language language = GroovyFileType.GROOVY_LANGUAGE;
249 PsiElement element1 = file.getViewProvider().findElementAt(startOffset, language);
250 PsiElement element2 = file.getViewProvider().findElementAt(endOffset - 1, language);
252 if (element1 instanceof PsiWhiteSpace || isNewLine(element1)) {
253 startOffset = element1.getTextRange().getEndOffset();
254 element1 = file.findElementAt(startOffset);
256 if (element2 instanceof PsiWhiteSpace || isNewLine(element2)) {
257 endOffset = element2.getTextRange().getStartOffset();
258 element2 = file.findElementAt(endOffset - 1);
260 if (element1 == null || element2 == null) return PsiElement.EMPTY_ARRAY;
262 PsiElement parent = PsiTreeUtil.findCommonParent(element1, element2);
263 if (parent == null) return PsiElement.EMPTY_ARRAY;
265 if (parent instanceof GrCodeBlock) break;
266 if (parent instanceof GroovyFileBase) break;
267 if (parent instanceof GrCaseSection) break;
268 if (parent instanceof GrStatement) {
269 parent = parent.getParent();
272 if (parent == null) return PsiElement.EMPTY_ARRAY;
273 final PsiElement prev = parent;
274 parent = parent.getParent();
275 if (parent instanceof GrCodeBlock && prev instanceof LeafPsiElement) { //braces
276 parent = parent.getParent();
280 if (!parent.equals(element1)) {
281 while (!parent.equals(element1.getParent())) {
282 element1 = element1.getParent();
285 if (startOffset != element1.getTextRange().getStartOffset() && strict) return PsiElement.EMPTY_ARRAY;
287 if (!parent.equals(element2)) {
288 while (!parent.equals(element2.getParent())) {
289 element2 = element2.getParent();
292 if (endOffset != element2.getTextRange().getEndOffset() && strict) return PsiElement.EMPTY_ARRAY;
294 if (parent instanceof GrCodeBlock && parent.getParent() instanceof GrBlockStatement &&
295 element1 == ((GrCodeBlock) parent).getLBrace() && element2 == ((GrCodeBlock) parent).getRBrace()) {
296 return new PsiElement[]{parent.getParent()};
299 // calculate children
300 PsiElement[] children = PsiElement.EMPTY_ARRAY;
301 PsiElement psiChild = parent.getFirstChild();
302 if (psiChild != null) {
303 List<PsiElement> result = new ArrayList<PsiElement>();
304 while (psiChild != null) {
305 result.add(psiChild);
306 psiChild = psiChild.getNextSibling();
308 children = PsiUtilCore.toPsiElementArray(result);
312 ArrayList<PsiElement> possibleStatements = new ArrayList<PsiElement>();
313 boolean flag = false;
314 for (PsiElement child : children) {
315 if (child == element1) {
319 possibleStatements.add(child);
321 if (child == element2) {
326 for (PsiElement element : possibleStatements) {
327 if (!(element instanceof GrStatement ||
328 element instanceof PsiWhiteSpace ||
329 element instanceof PsiComment ||
330 TokenSets.SEPARATORS.contains(element.getNode().getElementType()))) {
331 return PsiElement.EMPTY_ARRAY;
335 return PsiUtilCore.toPsiElementArray(possibleStatements);
338 public static boolean isSuperOrThisCall(GrStatement statement, boolean testForSuper, boolean testForThis) {
339 if (!(statement instanceof GrConstructorInvocation)) return false;
340 GrConstructorInvocation expr = (GrConstructorInvocation) statement;
341 return (testForSuper && expr.isSuperCall()) || (testForThis && expr.isThisCall());
344 public static boolean hasWrongBreakStatements(PsiElement element) {
345 ArrayList<GrBreakStatement> vector = new ArrayList<GrBreakStatement>();
346 addBreakStatements(element, vector);
347 return !vector.isEmpty();
350 private static void addBreakStatements(PsiElement element, ArrayList<GrBreakStatement> vector) {
351 if (element instanceof GrBreakStatement) {
352 vector.add(((GrBreakStatement) element));
353 } else if (!(element instanceof GrLoopStatement ||
354 element instanceof GrSwitchStatement ||
355 element instanceof GrClosableBlock)) {
356 for (PsiElement psiElement : element.getChildren()) {
357 addBreakStatements(psiElement, vector);
362 public static boolean hasWrongContinueStatements(PsiElement element) {
363 ArrayList<GrContinueStatement> vector = new ArrayList<GrContinueStatement>();
364 addContinueStatements(element, vector);
365 return !vector.isEmpty();
368 private static void addContinueStatements(PsiElement element, ArrayList<GrContinueStatement> vector) {
369 if (element instanceof GrContinueStatement) {
370 vector.add(((GrContinueStatement) element));
371 } else if (!(element instanceof GrLoopStatement || element instanceof GrClosableBlock)) {
372 for (PsiElement psiElement : element.getChildren()) {
373 addContinueStatements(psiElement, vector);
379 public static String getMethodSignature(PsiMethod method) {
380 MethodSignature signature = method.getSignature(PsiSubstitutor.EMPTY);
381 String s = signature.getName() + "(";
383 PsiType[] types = signature.getParameterTypes();
384 for (PsiType type : types) {
385 s += type.getPresentableText();
386 if (i < types.length - 1) {
397 public static GrCall getCallExpressionByMethodReference(@Nullable PsiElement ref) {
398 if (ref == null) return null;
399 if (ref instanceof GrEnumConstant) return (GrEnumConstant)ref;
400 if (ref instanceof GrConstructorInvocation) return (GrCall)ref;
401 PsiElement parent = ref.getParent();
402 if (parent instanceof GrCall) {
403 return (GrCall)parent;
410 public static boolean isMethodUsage(PsiElement ref) {
411 return (ref instanceof GrEnumConstant) || (ref.getParent() instanceof GrCall) || (ref instanceof GrConstructorInvocation);
414 public static String createTempVar(GrExpression expr, final GroovyPsiElement context, boolean declareFinal) {
415 expr = addBlockIntoParent(expr);
416 final GrVariableDeclarationOwner block = PsiTreeUtil.getParentOfType(expr, GrVariableDeclarationOwner.class);
417 LOG.assertTrue(block != null);
418 final PsiElement anchorStatement = PsiTreeUtil.findPrevParent(block, expr);
419 LOG.assertTrue(anchorStatement instanceof GrStatement);
421 Project project = expr.getProject();
422 String[] suggestedNames =GroovyNameSuggestionUtil.suggestVariableNames(expr, new NameValidator() {
423 public String validateName(String name, boolean increaseNumber) {
427 public Project getProject() {
428 return context.getProject();
432 JavaCodeStyleManager.getInstance(project).suggestVariableName(VariableKind.LOCAL_VARIABLE, null, expr, null).names;*/
433 final String prefix = suggestedNames[0];
434 final String id = JavaCodeStyleManager.getInstance(project).suggestUniqueVariableName(prefix, context, true);
436 GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(expr.getProject());
439 modifiers = finalModifiers;
442 modifiers = ArrayUtil.EMPTY_STRING_ARRAY;
444 GrVariableDeclaration decl =
445 factory.createVariableDeclaration(modifiers, (GrExpression)skipParentheses(expr, false), expr.getType(), id);
446 /* if (declareFinal) {
447 com.intellij.psi.util.PsiUtil.setModifierProperty((decl.getMembers()[0]), PsiModifier.FINAL, true);
449 ((GrStatementOwner)anchorStatement.getParent()).addStatementBefore(decl, (GrStatement)anchorStatement);
454 public static int verifySafeCopyExpression(GrExpression expression) {
455 return verifySafeCopyExpressionSubElement(expression);
458 private static int verifySafeCopyExpressionSubElement(PsiElement element) {
459 int result = EXPR_COPY_SAFE;
460 if (element == null) return result;
462 if (element instanceof GrThisReferenceExpression || element instanceof GrSuperReferenceExpression || element instanceof GrNamedElement) {
463 return EXPR_COPY_SAFE;
466 if (element instanceof GrMethodCallExpression) {
467 result = EXPR_COPY_UNSAFE;
470 if (element instanceof GrNewExpression) {
471 return EXPR_COPY_PROHIBITED;
474 if (element instanceof GrAssignmentExpression) {
475 return EXPR_COPY_PROHIBITED;
478 if (element instanceof GrClosableBlock) {
479 return EXPR_COPY_PROHIBITED;
482 if (isPlusPlusOrMinusMinus(element)) {
483 return EXPR_COPY_PROHIBITED;
486 PsiElement[] children = element.getChildren();
488 for (PsiElement child : children) {
489 int childResult = verifySafeCopyExpressionSubElement(child);
490 result = Math.max(result, childResult);
495 public static boolean isPlusPlusOrMinusMinus(PsiElement element) {
496 if (element instanceof GrUnaryExpression) {
497 IElementType operandSign = ((GrUnaryExpression)element).getOperationTokenType();
498 return operandSign == GroovyTokenTypes.mDEC || operandSign == GroovyTokenTypes.mINC;
503 public static boolean isCorrectReferenceName(String newName, Project project) {
504 if (newName.startsWith("'''") || newName.startsWith("\"\"\"")) {
505 if (newName.length() < 6 || !newName.endsWith("'''")) {
509 else if (newName.startsWith("'") || newName.startsWith("\"")) {
510 if (newName.length() < 2 || !newName.endsWith("'")) {
514 if (KEYWORDS.contains(newName)) {
518 GroovyPsiElementFactory.getInstance(project).createReferenceNameFromText(newName);
520 catch (IncorrectOperationException e) {
526 public static GrExpression generateArgFromMultiArg(PsiSubstitutor substitutor,
527 List<? extends PsiElement> arguments,
528 @Nullable PsiType type,
529 final Project project) {
530 StringBuilder argText = new StringBuilder();
532 for (PsiElement argument : arguments) {
533 argText.append(argument.getText()).append(", ");
536 if (arguments.size() > 0) {
537 argText.delete(argText.length() - 2, argText.length());
540 if (type instanceof PsiArrayType) {
541 type = substitutor.substitute(type);
542 String typeText = type.getCanonicalText();
543 if (type instanceof PsiEllipsisType) {
544 typeText = typeText.replace("...", "[]");
546 argText.append(" as ").append(typeText);
548 return GroovyPsiElementFactory.getInstance(project).createExpressionFromText(argText.toString());
551 public static boolean hasSideEffect(@NotNull GroovyPsiElement statement) {
552 final Ref<Boolean> hasSideEffect = new Ref<Boolean>(false);
553 statement.accept(new GroovyRecursiveElementVisitor() {
555 public void visitMethodCallExpression(GrMethodCallExpression methodCallExpression) {
556 hasSideEffect.set(true);
560 public void visitCallExpression(GrCallExpression callExpression) {
561 hasSideEffect.set(true);
565 public void visitApplicationStatement(GrApplicationStatement applicationStatement) {
566 hasSideEffect.set(true);
572 public void visitElement(GroovyPsiElement element) {
573 if (hasSideEffect.get()) return;
574 super.visitElement(element);
578 return hasSideEffect.get();
582 * adds block statement in parent of statement if needed. For Example:
583 * while (true) a=foo()
584 * will be replaced with
585 * while(true) {a=foo()}
587 * @return corresponding statement inside block if it has been created or statement itself.
588 * @throws com.intellij.util.IncorrectOperationException
592 public static <Type extends PsiElement> Type addBlockIntoParent(@NotNull Type statement) throws IncorrectOperationException {
594 PsiElement parent = statement.getParent();
595 PsiElement child = statement;
596 while (!(parent instanceof GrLoopStatement) &&
597 !(parent instanceof GrIfStatement) &&
598 !(parent instanceof GrVariableDeclarationOwner) &&
600 parent = parent.getParent();
601 child = child.getParent();
603 if (parent instanceof GrWhileStatement && child == ((GrWhileStatement)parent).getCondition() ||
604 parent instanceof GrIfStatement && child == ((GrIfStatement)parent).getCondition()) {
605 parent = parent.getParent();
607 assert parent != null;
608 if (parent instanceof GrVariableDeclarationOwner) {
612 GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(statement.getProject());
613 PsiElement tempStmt = statement;
614 while (parent != tempStmt.getParent()) {
615 tempStmt = tempStmt.getParent();
617 GrStatement toAdd = (GrStatement)tempStmt.copy();
618 GrBlockStatement blockStatement = factory.createBlockStatement();
619 if (parent instanceof GrLoopStatement) {
620 ((GrLoopStatement)parent).replaceBody(blockStatement);
623 GrIfStatement ifStatement = (GrIfStatement)parent;
624 if (tempStmt == ifStatement.getThenBranch()) {
625 ifStatement.replaceThenBranch(blockStatement);
627 else if (tempStmt == ifStatement.getElseBranch()) {
628 ifStatement.replaceElseBranch(blockStatement);
631 GrStatement result = blockStatement.getBlock().addStatementBefore(toAdd, null);
632 if (result instanceof GrReturnStatement) {
633 //noinspection ConstantConditions,unchecked
634 statement = (Type)((GrReturnStatement)result).getReturnValue();
637 //noinspection unchecked
638 statement = (Type)result;
644 public static boolean isDiamondNewOperator(GrExpression expression) {
645 PsiElement element = skipParentheses(expression, false);
646 if (!(element instanceof GrNewExpression)) return false;
647 if (((GrNewExpression)element).getArrayCount() > 0) return false;
649 GrCodeReferenceElement referenceElement = ((GrNewExpression)element).getReferenceElement();
650 if (referenceElement == null) return false;
652 GrTypeArgumentList typeArgumentList = referenceElement.getTypeArgumentList();
653 return typeArgumentList != null && typeArgumentList.isDiamond();
656 public static boolean checkPsiElementsAreEqual(PsiElement l, PsiElement r) {
657 if (!l.getText().equals(r.getText())) return false;
658 if (l.getNode().getElementType() != r.getNode().getElementType()) return false;
660 final PsiElement[] lChildren = l.getChildren();
661 final PsiElement[] rChildren = r.getChildren();
663 if (lChildren.length != rChildren.length) return false;
665 for (int i = 0; i < rChildren.length; i++) {
666 if (!checkPsiElementsAreEqual(lChildren[i], rChildren[i])) return false;