@Nullable public static GrExpression getRuntimeQualifier(GrReferenceExpression refExpr) { GrExpression qualifier = refExpr.getQualifierExpression(); if (qualifier != null) return qualifier; for (GrClosableBlock closure = PsiTreeUtil.getParentOfType(refExpr, GrClosableBlock.class); closure != null; closure = PsiTreeUtil.getParentOfType(closure, GrClosableBlock.class)) { PsiElement parent = closure.getParent(); if (parent instanceof GrArgumentList) parent = parent.getParent(); if (!(parent instanceof GrMethodCall)) continue; GrExpression funExpr = ((GrMethodCall) parent).getInvokedExpression(); if (!(funExpr instanceof GrReferenceExpression)) return funExpr; final PsiElement resolved = ((GrReferenceExpression) funExpr).resolve(); if (!(resolved instanceof PsiMethod)) return funExpr; if (resolved instanceof GrGdkMethod && isFromDGM((GrGdkMethod) resolved) && !GdkMethodUtil.isWithName(((GrGdkMethod) resolved).getStaticMethod().getName())) { continue; } qualifier = ((GrReferenceExpression) funExpr).getQualifierExpression(); if (qualifier != null) return qualifier; } return null; }
public static void deleteStatementTail(PsiElement container, @NotNull PsiElement statement) { PsiElement next = statement.getNextSibling(); while (next != null) { final ASTNode node = next.getNode(); final IElementType type = node.getElementType(); if (type == mSEMI) { final PsiElement nnext = next.getNextSibling(); container.deleteChildRange(next, next); next = nnext; } else if (type == mNLS || type == TokenType.WHITE_SPACE && next.getText().contains("\n")) { final String text = next.getText(); final int first = text.indexOf("\n"); final int second = text.indexOf("\n", first + 1); if (second < 0) { container.deleteChildRange(next, next); return; } final String substring = text.substring(second); container .getNode() .replaceChild( node, createSingleLeafElement( type, substring, 0, substring.length(), null, container.getManager())); return; } else { break; } } }
public static boolean hasNamedArguments(@Nullable GrNamedArgumentsOwner list) { if (list == null) return false; for (PsiElement child = list.getFirstChild(); child != null; child = child.getNextSibling()) { if (child instanceof GrNamedArgument) return true; } return false; }
public static boolean hasExpressionArguments(@Nullable GrArgumentList list) { if (list == null) return false; for (PsiElement child = list.getFirstChild(); child != null; child = child.getNextSibling()) { if (child instanceof GrExpression) return true; } return false; }
public static boolean hasClosureArguments(@Nullable GrCall call) { if (call == null) return false; for (PsiElement child = call.getFirstChild(); child != null; child = child.getNextSibling()) { if (child instanceof GrClosableBlock) return true; } return false; }
public static PsiElement findTailingSemicolon(@NotNull GrStatement statement) { final PsiElement nextNonSpace = PsiUtil.skipWhitespaces(statement.getNextSibling(), true); if (nextNonSpace != null && nextNonSpace.getNode().getElementType() == mSEMI) { return nextNonSpace; } return null; }
public static GrStatement[] getStatements(final GrStatementOwner statementOwner) { List<GrStatement> result = new ArrayList<GrStatement>(); for (PsiElement cur = statementOwner.getFirstChild(); cur != null; cur = cur.getNextSibling()) { if (cur instanceof GrStatement) { result.add((GrStatement) cur); } } return result.toArray(new GrStatement[result.size()]); }
@Override public void visitParenthesizedExpression(GrParenthesizedExpression expression) { final PsiElement parent = expression.getParent(); if (parent instanceof GroovyPsiElement) { ((GroovyPsiElement) parent).accept(this); } else { parent.accept(new GroovyPsiElementVisitor(this)); } }
/** @return leading regex or null if it does not exist */ @Nullable private static GrLiteral getRegexAtTheBeginning(PsiElement expr) { PsiElement fchild = expr; while (fchild != null) { if (fchild instanceof GrLiteral && GrStringUtil.isRegex((GrLiteral) fchild)) return (GrLiteral) fchild; fchild = fchild.getFirstChild(); } return null; }
@Override public void visitCaseLabel(GrCaseLabel caseLabel) { final PsiElement parent = caseLabel.getParent().getParent(); assert parent instanceof GrSwitchStatement : parent + " of class " + parent.getClass(); final GrExpression condition = ((GrSwitchStatement) parent).getCondition(); if (condition == null) return; final PsiType type = condition.getType(); if (type == null) return; myResult = new TypeConstraint[] {SubtypeConstraint.create(type)}; }
@NotNull public static PsiType createSetType(@NotNull PsiElement context, @NotNull PsiType type) { JavaPsiFacade facade = JavaPsiFacade.getInstance(context.getProject()); GlobalSearchScope resolveScope = context.getResolveScope(); PsiClass setClass = facade.findClass(JAVA_UTIL_SET, resolveScope); if (setClass != null && setClass.getTypeParameters().length == 1) { return facade.getElementFactory().createType(setClass, type); } return facade.getElementFactory().createTypeByFQClassName(JAVA_UTIL_SET, resolveScope); }
@Override public void visitAnnotationArrayInitializer(GrAnnotationArrayInitializer arrayInitializer) { final GrAnnotationNameValuePair nameValuePair = PsiTreeUtil.getParentOfType( arrayInitializer, GrAnnotationNameValuePair.class, true, GrDefaultAnnotationValue.class); if (nameValuePair != null) { final PsiClass annot = ResolveUtil.resolveAnnotation(arrayInitializer); if (annot == null) return; final String name = nameValuePair.getName(); if (name == null) return; final PsiMethod[] attrs = annot.findMethodsByName(name, false); if (attrs.length > 0) { PsiType type = attrs[0].getReturnType(); while (type instanceof PsiArrayType) type = ((PsiArrayType) type).getComponentType(); if (type != null && isAcceptableAnnotationValueType(type)) { myResult = createSimpleSubTypeResult(type); } } } else { final GrAnnotationMethod method = PsiTreeUtil.getParentOfType(arrayInitializer, GrAnnotationMethod.class); assert method != null; PsiType type = method.getReturnType(); int count = 1; PsiElement parent = arrayInitializer.getParent(); while (parent instanceof GrAnnotationArrayInitializer) { count++; parent = parent.getParent(); } while (type instanceof PsiArrayType && count > 0) { type = ((PsiArrayType) type).getComponentType(); count--; } if (type != null && isAcceptableAnnotationValueType(type)) { myResult = createSimpleSubTypeResult(type); } } }
public static void removeVariable(GrVariable variable) { final GrVariableDeclaration varDecl = (GrVariableDeclaration) variable.getParent(); final List<GrVariable> variables = Arrays.asList(varDecl.getVariables()); if (!variables.contains(variable)) { throw new IllegalArgumentException(); } final PsiElement parent = varDecl.getParent(); final ASTNode owner = parent.getNode(); if (variables.size() == 1 && owner != null) { PsiElement next = varDecl.getNextSibling(); // remove redundant semicolons //noinspection ConstantConditions while (next != null && next.getNode() != null && next.getNode().getElementType() == mSEMI) { PsiElement tmpNext = next.getNextSibling(); //noinspection ConstantConditions next.delete(); next = tmpNext; } removeNewLineAfter(varDecl); varDecl.delete(); return; } variable.delete(); }
@Nullable private InstructionImpl findInstruction(PsiElement element) { final Iterator<InstructionImpl> iterator = myProcessingStack.descendingIterator(); while (iterator.hasNext()) { final InstructionImpl instruction = iterator.next(); if (element.equals(instruction.getElement())) return instruction; } return null; }
public static boolean isAssignableWithoutConversions( @Nullable PsiType lType, @Nullable PsiType rType, @NotNull PsiElement context) { if (lType == null || rType == null) return false; if (rType == PsiType.NULL) { return !(lType instanceof PsiPrimitiveType); } PsiManager manager = context.getManager(); GlobalSearchScope scope = context.getResolveScope(); if (rType instanceof GrTupleType && ((GrTupleType) rType).getComponentTypes().length == 0) { if (lType instanceof PsiArrayType || InheritanceUtil.isInheritor(lType, JAVA_UTIL_LIST) || InheritanceUtil.isInheritor(lType, JAVA_UTIL_SET)) { return true; } } if (isClassType(rType, GROOVY_LANG_GSTRING) && lType.equalsToText(JAVA_LANG_STRING)) { return true; } if (isNumericType(lType) && isNumericType(rType)) { lType = unboxPrimitiveTypeWrapper(lType); if (isClassType(lType, JAVA_MATH_BIG_DECIMAL)) lType = PsiType.DOUBLE; rType = unboxPrimitiveTypeWrapper(rType); if (isClassType(rType, JAVA_MATH_BIG_DECIMAL)) rType = PsiType.DOUBLE; } else { rType = boxPrimitiveType(rType, manager, scope); lType = boxPrimitiveType(lType, manager, scope); } if (rType instanceof GrMapType || rType instanceof GrTupleType) { Boolean result = isAssignableForNativeTypes(lType, (PsiClassType) rType, context); if (result != null && result.booleanValue()) return true; } if (TypeConversionUtil.isAssignable(lType, rType)) { return true; } return false; }
@Nullable public static PsiElement realPrevious(PsiElement previousLeaf) { while (previousLeaf != null && (previousLeaf instanceof PsiWhiteSpace || previousLeaf instanceof PsiComment || previousLeaf instanceof PsiErrorElement)) { previousLeaf = previousLeaf.getPrevSibling(); } return previousLeaf; }
public static <T extends PsiElement> void setQualifier( @NotNull GrQualifiedReference<T> ref, @Nullable T newQualifier) { final T oldQualifier = ref.getQualifier(); final ASTNode node = ref.getNode(); final PsiElement refNameElement = ref.getReferenceNameElement(); if (newQualifier == null) { if (oldQualifier != null && refNameElement != null) { ref.deleteChildRange(ref.getFirstChild(), refNameElement.getPrevSibling()); } } else { if (oldQualifier == null) { if (refNameElement != null) { node.addLeaf(mDOT, ".", refNameElement.getNode()); ref.addBefore(newQualifier, refNameElement.getPrevSibling()); } } else { oldQualifier.replace(newQualifier); } } }
@NotNull public static String getName(@NotNull GrNamedElement namedElement) { PsiElement nameElement = namedElement.getNameIdentifierGroovy(); ASTNode node = nameElement.getNode(); LOG.assertTrue(node != null); if (node.getElementType() == mIDENT) { return nameElement.getText(); } if (node.getElementType() == mSTRING_LITERAL || node.getElementType() == mGSTRING_LITERAL) { final Object value = GrLiteralImpl.getLiteralValue(nameElement); if (value instanceof String) { return (String) value; } else { return GrStringUtil.removeQuotes(nameElement.getText()); } } throw new IncorrectOperationException( "incorrect name element: " + node.getElementType() + ", named element: " + namedElement); }
private void buildFlowForClosure(final GrClosableBlock closure) { for (GrParameter parameter : closure.getAllParameters()) { if (myPolicy.isVariableInitialized(parameter)) { addNode(new ReadWriteVariableInstruction(parameter.getName(), parameter, WRITE)); } } addNode(new ReadWriteVariableInstruction("owner", closure.getLBrace(), WRITE)); PsiElement child = closure.getFirstChild(); while (child != null) { if (child instanceof GroovyPsiElement) { ((GroovyPsiElement) child).accept(this); } child = child.getNextSibling(); } final GrStatement[] statements = closure.getStatements(); if (statements.length > 0) { handlePossibleReturn(statements[statements.length - 1]); } }
@Nullable public static PsiType inferExpectedTypeForDiamond(GrExpression diamondNew) { PsiElement skipped = PsiUtil.skipParentheses(diamondNew, true); assert skipped != null; PsiElement pparent = skipped.getParent(); if (pparent instanceof GrAssignmentExpression && PsiTreeUtil.isAncestor( ((GrAssignmentExpression) pparent).getRValue(), diamondNew, false)) { GrExpression lValue = ((GrAssignmentExpression) pparent).getLValue(); if (PsiUtil.mightBeLValue(lValue)) { return lValue.getNominalType(); } } else if (pparent instanceof GrVariable && ((GrVariable) pparent).getInitializerGroovy() == diamondNew) { return ((GrVariable) pparent).getDeclaredType(); } else if (pparent instanceof GrListOrMap) { PsiElement ppparent = PsiUtil.skipParentheses(pparent.getParent(), true); if (ppparent instanceof GrAssignmentExpression && PsiTreeUtil.isAncestor( ((GrAssignmentExpression) ppparent).getRValue(), pparent, false)) { PsiElement lValue = PsiUtil.skipParentheses(((GrAssignmentExpression) ppparent).getLValue(), false); if (lValue instanceof GrTupleExpression) { GrExpression[] initializers = ((GrListOrMap) pparent).getInitializers(); int index = ArrayUtil.find(initializers, diamondNew); GrExpression[] expressions = ((GrTupleExpression) lValue).getExpressions(); if (index < expressions.length) { return expressions[index].getNominalType(); } } } } return null; }
@Nullable public static GrExpression replaceExpression( GrExpression oldExpr, GrExpression newExpr, boolean removeUnnecessaryParentheses) { PsiElement oldParent = oldExpr.getParent(); if (oldParent == null) throw new PsiInvalidElementAccessException(oldExpr); if (!(oldExpr instanceof GrApplicationStatement)) { newExpr = ApplicationStatementUtil.convertToMethodCallExpression(newExpr); } // Remove unnecessary parentheses if (removeUnnecessaryParentheses && oldParent instanceof GrParenthesizedExpression && !(oldParent.getParent() instanceof GrArgumentLabel)) { return ((GrExpression) oldParent) .replaceWithExpression(newExpr, removeUnnecessaryParentheses); } // regexes cannot be after identifier , try to replace it with simple string if (getRegexAtTheBeginning(newExpr) != null && isAfterIdentifier(oldExpr)) { final PsiElement copy = newExpr.copy(); final GrLiteral regex = getRegexAtTheBeginning(copy); LOG.assertTrue(regex != null); final GrLiteral stringLiteral = GrStringUtil.createStringFromRegex(regex); if (regex == copy) { return oldExpr.replaceWithExpression(stringLiteral, removeUnnecessaryParentheses); } else { regex.replace(stringLiteral); return oldExpr.replaceWithExpression((GrExpression) copy, removeUnnecessaryParentheses); } } GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(oldExpr.getProject()); if (oldParent instanceof GrStringInjection) { if (newExpr instanceof GrString || newExpr instanceof GrLiteral && ((GrLiteral) newExpr).getValue() instanceof String) { return GrStringUtil.replaceStringInjectionByLiteral( (GrStringInjection) oldParent, (GrLiteral) newExpr); } else { newExpr = factory.createExpressionFromText("{" + newExpr.getText() + "}"); oldParent.getNode().replaceChild(oldExpr.getNode(), newExpr.getNode()); return newExpr; } } if (PsiTreeUtil.getParentOfType(oldExpr, GrStringInjection.class, false, GrCodeBlock.class) != null) { final PsiElement replaced = oldExpr.replace(newExpr); final GrStringInjection stringInjection = PsiTreeUtil.getParentOfType(replaced, GrStringInjection.class); GrStringUtil.wrapInjection(stringInjection); assert stringInjection != null; return stringInjection.getClosableBlock(); } // check priorities if (oldParent instanceof GrExpression && !(oldParent instanceof GrParenthesizedExpression)) { GrExpression addedParenth = addParenthesesIfNeeded(newExpr, oldExpr, (GrExpression) oldParent); if (newExpr != addedParenth) { return oldExpr.replaceWithExpression(addedParenth, removeUnnecessaryParentheses); } } // if replace closure argument with expression // we should add the expression in arg list if (oldExpr instanceof GrClosableBlock && !(newExpr instanceof GrClosableBlock) && oldParent instanceof GrMethodCallExpression && ArrayUtil.contains( oldExpr, ((GrMethodCallExpression) oldParent).getClosureArguments())) { return ((GrMethodCallExpression) oldParent) .replaceClosureArgument((GrClosableBlock) oldExpr, newExpr); } newExpr = (GrExpression) oldExpr.replace(newExpr); // if newExpr is the first grand child of command argument list we should replace command arg // list with parenthesised arg list. // In other case the code will be broken. So we try to find wrapping command arg list counting // levels. After arg list replace we go inside it // to find target parenthesised expression. if (newExpr instanceof GrParenthesizedExpression && isFirstChild(newExpr)) { int parentCount = 0; PsiElement element = oldParent; while (element != null && !(element instanceof GrCommandArgumentList)) { if (element instanceof GrCodeBlock || element instanceof GrParenthesizedExpression) break; if (element instanceof PsiFile) break; final PsiElement parent = element.getParent(); if (parent == null) break; if (!isFirstChild(element)) break; element = parent; parentCount++; } if (element instanceof GrCommandArgumentList) { final GrCommandArgumentList commandArgList = (GrCommandArgumentList) element; final PsiElement parent = commandArgList.getParent(); LOG.assertTrue(parent instanceof GrApplicationStatement); final GrMethodCall methodCall = factory.createMethodCallByAppCall((GrApplicationStatement) parent); final GrMethodCall newCall = (GrMethodCall) parent.replace(methodCall); PsiElement result = newCall.getArgumentList().getAllArguments()[0]; for (int i = 0; i < parentCount; i++) { result = PsiUtil.skipWhitespacesAndComments(result.getFirstChild(), true); } LOG.assertTrue(result instanceof GrParenthesizedExpression); return (GrExpression) result; } } return newExpr; }
@NotNull public static PsiClassType createTypeByFQClassName( @NotNull String fqName, @NotNull PsiElement context) { return GroovyPsiManager.getInstance(context.getProject()) .createTypeByFQClassName(fqName, context.getResolveScope()); }
@NotNull public static PsiClassType getJavaLangObject(@NotNull PsiElement context) { return PsiType.getJavaLangObject(context.getManager(), context.getResolveScope()); }
public static boolean isAssignable( @Nullable PsiType lType, @Nullable PsiType rType, @NotNull PsiElement context) { if (lType == null || rType == null) { return false; } if (rType instanceof PsiIntersectionType) { for (PsiType child : ((PsiIntersectionType) rType).getConjuncts()) { if (isAssignable(lType, child, context)) { return true; } } return false; } if (lType instanceof PsiIntersectionType) { for (PsiType child : ((PsiIntersectionType) lType).getConjuncts()) { if (!isAssignable(child, rType, context)) { return false; } } return true; } if (rType == PsiType.NULL) { return !(lType instanceof PsiPrimitiveType); } if (isNumericType(lType) && isNumericType(rType)) { return true; } if (isClassType(lType, JAVA_LANG_STRING)) { return true; } final PsiManager manager = context.getManager(); final GlobalSearchScope scope = context.getResolveScope(); if (lType instanceof PsiArrayType) { PsiType lComponentType = ((PsiArrayType) lType).getComponentType(); PsiType rComponentType = ClosureParameterEnhancer.findTypeForIteration(rType, context); if (rComponentType != null && isAssignable(lComponentType, rComponentType, context)) { return true; } } if (unboxPrimitiveTypeWrapper(lType) == PsiType.CHAR && (isClassType(rType, JAVA_LANG_STRING) || isClassType(rType, GROOVY_LANG_GSTRING))) { return true; } if (isAssignableByMethodCallConversion(lType, rType, context)) return true; lType = boxPrimitiveType(lType, manager, scope); rType = boxPrimitiveType(rType, manager, scope); if (lType.isAssignableFrom(rType)) { return true; } if (context instanceof GroovyPsiElement) { for (GrTypeConverter converter : GrTypeConverter.EP_NAME.getExtensions()) { if (!converter.isAllowedInMethodCall()) { Boolean result = converter.isConvertible(lType, rType, (GroovyPsiElement) context); if (result != null) { return result; } } } } return false; }
private static boolean isAfterIdentifier(PsiElement el) { final PsiElement prev = GeeseUtil.getPreviousNonWhitespaceToken(el); return prev != null && prev.getNode().getElementType() == mIDENT; }
public static void setName(String name, PsiElement nameElement) { final PsiElement newNameElement = GroovyPsiElementFactory.getInstance(nameElement.getProject()) .createReferenceNameFromText(name); nameElement.replace(newNameElement); }
private static boolean isFirstChild(PsiElement element) { return PsiUtil.skipWhitespacesAndComments(element.getParent().getFirstChild(), true) == element; }
public static boolean hasElementType(@Nullable PsiElement next, final TokenSet set) { if (next == null) return false; final ASTNode astNode = next.getNode(); return astNode != null && set.contains(astNode.getElementType()); }
public static boolean hasElementType( @Nullable PsiElement next, @NotNull final IElementType type) { if (next == null) return false; final ASTNode astNode = next.getNode(); return astNode != null && astNode.getElementType() == type; }