@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; }
@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; }
@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); } } }
@Nullable private PsiType getNominalTypeInner(PsiElement resolved) { if (resolved == null && !"class".equals(getReferenceName())) { resolved = resolve(); } if (resolved instanceof PsiClass) { final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); if (PsiUtil.isInstanceThisRef(this)) { final PsiClassType categoryType = GdkMethodUtil.getCategoryType((PsiClass) resolved); if (categoryType != null) { return categoryType; } else { return factory.createType((PsiClass) resolved); } } if (getParent() instanceof GrReferenceExpression || PsiUtil.isSuperReference(this)) { return factory.createType((PsiClass) resolved); } else { return TypesUtil.createJavaLangClassType( factory.createType((PsiClass) resolved), getProject(), getResolveScope()); } } if (resolved instanceof GrVariable) { return ((GrVariable) resolved).getDeclaredType(); } if (resolved instanceof PsiVariable) { return ((PsiVariable) resolved).getType(); } if (resolved instanceof PsiMethod) { PsiMethod method = (PsiMethod) resolved; if (PropertyUtil.isSimplePropertySetter(method) && !method.getName().equals(getReferenceName())) { return method.getParameterList().getParameters()[0].getType(); } // 'class' property with explicit generic PsiClass containingClass = method.getContainingClass(); if (containingClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName()) && "getClass".equals(method.getName())) { return TypesUtil.createJavaLangClassType( GrReferenceResolveUtil.getQualifierType(this), getProject(), getResolveScope()); } return PsiUtil.getSmartReturnType(method); } if (resolved instanceof GrReferenceExpression) { PsiElement parent = resolved.getParent(); if (parent instanceof GrAssignmentExpression) { GrAssignmentExpression assignment = (GrAssignmentExpression) parent; if (resolved.equals(assignment.getLValue())) { GrExpression rValue = assignment.getRValue(); if (rValue != null) { PsiType rType = rValue.getType(); if (rType != null) { return rType; } } } } } if (resolved == null) { final PsiType fromClassRef = getTypeFromClassRef(this); if (fromClassRef != null) { return fromClassRef; } final PsiType fromMapAccess = getTypeFromMapAccess(this); if (fromMapAccess != null) { return fromMapAccess; } final PsiType fromSpreadOperator = getTypeFromSpreadOperator(this); if (fromSpreadOperator != null) { return fromSpreadOperator; } } return null; }
private static boolean isFirstChild(PsiElement element) { return PsiUtil.skipWhitespacesAndComments(element.getParent().getFirstChild(), true) == element; }
@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; }
private static boolean shouldBeClass(GrReferenceElement myRefElement) { PsiElement parent = myRefElement.getParent(); return parent instanceof GrExtendsClause && !(parent.getParent() instanceof GrInterfaceDefinition); }