public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { Set<String> classes = new LinkedHashSet<String>(); Set<String> interfaces = new LinkedHashSet<String>(); Set<String> unknownClasses = new LinkedHashSet<String>(); Set<String> unknownInterfaces = new LinkedHashSet<String>(); if (myExtendsClause != null) { collectRefs( myExtendsClause.getReferenceElementsGroovy(), classes, interfaces, myClass.isInterface() ? unknownInterfaces : unknownClasses); myExtendsClause.delete(); } if (myImplementsClause != null) { collectRefs( myImplementsClause.getReferenceElementsGroovy(), classes, interfaces, unknownInterfaces); myImplementsClause.delete(); } if (myClass.isInterface()) { interfaces.addAll(classes); unknownInterfaces.addAll(unknownClasses); addNewClause(interfaces, unknownInterfaces, project, true); } else { addNewClause(classes, unknownClasses, project, true); addNewClause(interfaces, unknownInterfaces, project, false); } }
private void getVariantsFromQualifierType( @NotNull PsiType qualifierType, @NotNull Project project) { final ResolveState state = ResolveState.initial(); if (qualifierType instanceof PsiClassType) { PsiClassType.ClassResolveResult result = ((PsiClassType) qualifierType).resolveGenerics(); PsiClass qualifierClass = result.getElement(); if (qualifierClass != null) { qualifierClass.processDeclarations( myProcessor, state.put(PsiSubstitutor.KEY, result.getSubstitutor()), null, myRefExpr); } } else if (qualifierType instanceof PsiArrayType) { final GrTypeDefinition arrayClass = GroovyPsiManager.getInstance(project) .getArrayClass(((PsiArrayType) qualifierType).getComponentType()); if (arrayClass != null) { if (!arrayClass.processDeclarations(myProcessor, state, null, myRefExpr)) return; } } else if (qualifierType instanceof PsiIntersectionType) { for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) { getVariantsFromQualifierType(conjunct, project); } return; } ResolveUtil.processNonCodeMembers(qualifierType, myProcessor, myRefExpr, state); }
private void addNewClause( Collection<String> elements, Collection<String> additional, Project project, boolean isExtends) throws IncorrectOperationException { if (elements.isEmpty() && additional.isEmpty()) return; StringBuilder classText = new StringBuilder(); classText.append("class A "); classText.append(isExtends ? "extends " : "implements "); for (String str : elements) { classText.append(str); classText.append(", "); } for (String str : additional) { classText.append(str); classText.append(", "); } classText.delete(classText.length() - 2, classText.length()); classText.append(" {}"); final GrTypeDefinition definition = GroovyPsiElementFactory.getInstance(project).createTypeDefinition(classText.toString()); GroovyPsiElement clause = isExtends ? definition.getExtendsClause() : definition.getImplementsClause(); assert clause != null; PsiElement addedClause = myClass.addBefore(clause, myClass.getBody()); JavaCodeStyleManager.getInstance(project).shortenClassReferences(addedClause); }
@NotNull public static PsiClassType[] getExtendsListTypes(GrTypeDefinition grType) { final PsiClassType[] extendsTypes = getReferenceListTypes(grType.getExtendsClause()); if (grType.isInterface()) { return extendsTypes; } for (PsiClassType type : extendsTypes) { final PsiClass superClass = type.resolve(); if (superClass instanceof GrTypeDefinition && !superClass.isInterface() || superClass != null && GroovyCommonClassNames.GROOVY_OBJECT_SUPPORT.equals( superClass.getQualifiedName())) { return extendsTypes; } } PsiClass grObSupport = GroovyPsiManager.getInstance(grType.getProject()) .findClassWithCache( GroovyCommonClassNames.GROOVY_OBJECT_SUPPORT, grType.getResolveScope()); if (grObSupport != null) { final PsiClassType type = JavaPsiFacade.getInstance(grType.getProject()) .getElementFactory() .createType(grObSupport); return ArrayUtil.append(extendsTypes, type, PsiClassType.ARRAY_FACTORY); } return extendsTypes; }
@Nullable public static PsiClass getBaseClass(GrTypeDefinition grType) { if (grType.isEnum()) { return JavaPsiFacade.getInstance(grType.getProject()) .findClass(CommonClassNames.JAVA_LANG_ENUM, grType.getResolveScope()); } else { return JavaPsiFacade.getInstance(grType.getProject()) .findClass(CommonClassNames.JAVA_LANG_OBJECT, grType.getResolveScope()); } }
@NotNull public static PsiClassType[] getSuperTypes(GrTypeDefinition grType) { PsiClassType[] extendsList = grType.getExtendsListTypes(); if (extendsList.length == 0) { extendsList = new PsiClassType[] {createBaseClassType(grType)}; } return ArrayUtil.mergeArrays( extendsList, grType.getImplementsListTypes(), PsiClassType.ARRAY_FACTORY); }
@Nullable public static PsiClass createSubclassGroovy( final GrTypeDefinition psiClass, final PsiDirectory targetDirectory, final String className) { final Project project = psiClass.getProject(); final Ref<GrTypeDefinition> targetClass = new Ref<GrTypeDefinition>(); new WriteCommandAction(project, getTitle(psiClass), getTitle(psiClass)) { @Override protected void run(Result result) throws Throwable { IdeDocumentHistory.getInstance(project).includeCurrentPlaceAsChangePlace(); final GrTypeParameterList oldTypeParameterList = psiClass.getTypeParameterList(); try { targetClass.set( CreateClassActionBase.createClassByType( targetDirectory, className, PsiManager.getInstance(project), psiClass, NewGroovyClassAction.GROOVY_CLASS)); } catch (final IncorrectOperationException e) { ApplicationManager.getApplication() .invokeLater( new Runnable() { @Override public void run() { Messages.showErrorDialog( project, CodeInsightBundle.message( "intention.error.cannot.create.class.message", className) + "\n" + e.getLocalizedMessage(), CodeInsightBundle.message("intention.error.cannot.create.class.title")); } }); return; } startTemplate(oldTypeParameterList, project, psiClass, targetClass.get(), false); GrReferenceAdjuster.shortenReferences(targetClass.get()); } }.execute(); if (targetClass.get() == null) return null; if (!ApplicationManager.getApplication().isUnitTestMode() && !psiClass.hasTypeParameters()) { final Editor editor = CodeInsightUtil.positionCursor( project, targetClass.get().getContainingFile(), targetClass.get().getLBrace()); if (editor == null) return targetClass.get(); chooseAndImplement(psiClass, project, targetClass.get(), editor); } return targetClass.get(); }
public static void collectMethodsFromBody( @NotNull GrTypeDefinition definition, List<PsiMethod> result) { for (GrMethod method : definition.getCodeMethods()) { addExpandingReflectedMethods(result, method); } for (GrField field : definition.getFields()) { if (!field.isProperty()) continue; ContainerUtil.addAll(result, field.getGetters()); ContainerUtil.addIfNotNull(result, field.getSetter()); } }
private void doMoveField(PsiSubstitutor substitutor, GrMemberInfo info) { GroovyPsiElementFactory elementFactory = GroovyPsiElementFactory.getInstance(myProject); GrField field = (GrField) info.getMember(); field.normalizeDeclaration(); replaceMovedMemberTypeParameters( field, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory); // fixReferencesToStatic(field, movedMembers); if (myTargetSuperClass.isInterface()) { PsiUtil.setModifierProperty(field, PsiModifier.PUBLIC, true); } final PsiMember movedElement = (PsiMember) myTargetSuperClass.add(field); myMembersAfterMove.add(movedElement); deleteMemberWithDocComment(field); }
@Nullable public static GrTypeDefinition findContainingClass(GrIntroduceContext context) { PsiElement place = context.getPlace(); while (true) { final GrTypeDefinition typeDefinition = PsiTreeUtil.getParentOfType(place, GrTypeDefinition.class, true, GroovyFileBase.class); if (typeDefinition == null) return null; if (!typeDefinition.isAnonymous() && (typeDefinition.hasModifierProperty(PsiModifier.STATIC) || typeDefinition.getContainingClass() == null)) { return typeDefinition; } place = typeDefinition; } }
private static boolean checkForDelegate(GrTypeDefinition clazz) { for (GrField field : clazz.getFields()) { if (PsiImplUtil.getAnnotation(field, GroovyCommonClassNames.GROOVY_LANG_DELEGATE) != null) return true; } return false; }
@NotNull public static List<Pair<PsiMethod, PsiSubstitutor>> findMethodsAndTheirSubstitutorsByName( GrTypeDefinition grType, String name, boolean checkBases) { final ArrayList<Pair<PsiMethod, PsiSubstitutor>> result = new ArrayList<Pair<PsiMethod, PsiSubstitutor>>(); if (!checkBases) { final PsiMethod[] methods = grType.findMethodsByName(name, false); for (PsiMethod method : methods) { result.add(new Pair<PsiMethod, PsiSubstitutor>(method, PsiSubstitutor.EMPTY)); } } else { final Map<String, List<CandidateInfo>> map = CollectClassMembersUtil.getAllMethods(grType, true); final List<CandidateInfo> candidateInfos = map.get(name); if (candidateInfos != null) { for (CandidateInfo info : candidateInfos) { final PsiElement element = info.getElement(); result.add( new Pair<PsiMethod, PsiSubstitutor>((PsiMethod) element, info.getSubstitutor())); } } } return result; }
@Nullable public static PsiClass getSuperClass(GrTypeDefinition grType) { final PsiClassType[] extendsList = grType.getExtendsListTypes(); if (extendsList.length == 0) return getBaseClass(grType); final PsiClass superClass = extendsList[0].resolve(); return superClass != null ? superClass : getBaseClass(grType); }
@NotNull private Set<String> addAllRestrictedProperties() { if (myRefExpr.getQualifier() != null) { return Collections.emptySet(); } Set<String> propertyNames = new HashSet<String>(); for (GrTypeDefinition containingClass = PsiTreeUtil.getParentOfType(myRefExpr, GrTypeDefinition.class); containingClass != null; containingClass = PsiTreeUtil.getParentOfType(containingClass, GrTypeDefinition.class)) { for (PsiField field : containingClass.getFields()) { propertyNames.add(field.getName()); } } return propertyNames; }
private static void getImplementListsInner( GrTypeDefinition grType, List<PsiClassType> result, Set<PsiClass> visited) { if (!visited.add(grType)) return; final PsiClassType[] implementsTypes = getReferenceListTypes(grType.getImplementsClause()); List<PsiClassType> fromDelegates = getImplementsFromDelegate(grType, visited); if (fromDelegates != null) { result.addAll(fromDelegates); } result.addAll(Arrays.asList(implementsTypes)); if (!grType.isInterface() && !ContainerUtil.or(implementsTypes, IS_GROOVY_OBJECT) && !ContainerUtil.or(getReferenceListTypes(grType.getExtendsClause()), IS_GROOVY_OBJECT)) { result.add(getGroovyObjectType(grType)); } }
public static PsiClass[] getInterfaces(GrTypeDefinition grType) { final PsiClassType[] implementsListTypes = grType.getImplementsListTypes(); List<PsiClass> result = new ArrayList<PsiClass>(implementsListTypes.length); for (PsiClassType type : implementsListTypes) { final PsiClass psiClass = type.resolve(); if (psiClass != null) result.add(psiClass); } return result.toArray(new PsiClass[result.size()]); }
@Override public void collectMethods( @NotNull GrTypeDefinition clazz, @NotNull Collection<PsiMethod> collector) { if (!hasGeneratedImplementations(clazz)) return; final LightMethodBuilder write = new LightMethodBuilder(clazz.getManager(), "writeExternal"); write.setContainingClass(clazz); write.addParameter("out", ObjectOutput.class.getName()); write.addException(IOException.class.getName()); write.setOriginInfo("created by @AutoExternalize"); collector.add(write); final LightMethodBuilder read = new LightMethodBuilder(clazz.getManager(), "readExternal"); read.setContainingClass(clazz); read.addParameter("oin", ObjectInput.class.getName()); read.setOriginInfo("created by @AutoExternalize"); collector.add(read); }
public void setCorrectVisibility(final HashSet<PsiMember> movedMembers, GrMemberInfo info) { PsiModifierListOwner modifierListOwner = info.getMember(); if (myTargetSuperClass.isInterface()) { PsiUtil.setModifierProperty(modifierListOwner, PsiModifier.PUBLIC, true); } else if (modifierListOwner.hasModifierProperty(PsiModifier.PRIVATE)) { if (info.isToAbstract() || willBeUsedInSubclass( modifierListOwner, movedMembers, myTargetSuperClass, mySourceClass)) { PsiUtil.setModifierProperty(modifierListOwner, PsiModifier.PROTECTED, true); } if (modifierListOwner instanceof GrTypeDefinition) { ((GrTypeDefinition) modifierListOwner) .accept( new GroovyRecursiveElementVisitor() { @Override public void visitMethod(GrMethod method) { check(method); } @Override public void visitField(GrField field) { check(field); } @Override public void visitTypeDefinition(GrTypeDefinition typeDefinition) { check(typeDefinition); super.visitTypeDefinition(typeDefinition); } private void check(PsiMember member) { if (member.hasModifierProperty(PsiModifier.PRIVATE)) { if (willBeUsedInSubclass( member, movedMembers, myTargetSuperClass, mySourceClass)) { PsiUtil.setModifierProperty(member, PsiModifier.PROTECTED, true); } } } }); } } }
private static void processClassUsage(GrTypeDefinition psiClass, JavaChangeInfo changeInfo) { String name = psiClass.getName(); GrMethod constructor = GroovyPsiElementFactory.getInstance(psiClass.getProject()) .createConstructorFromText( name, ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY, "{}", null); GrModifierList list = constructor.getModifierList(); if (psiClass.hasModifierProperty(PsiModifier.PRIVATE)) list.setModifierProperty(PsiModifier.PRIVATE, true); if (psiClass.hasModifierProperty(PsiModifier.PROTECTED)) list.setModifierProperty(PsiModifier.PROTECTED, true); if (!list.hasExplicitVisibilityModifiers()) { list.setModifierProperty(GrModifier.DEF, true); } constructor = (GrMethod) psiClass.add(constructor); processConstructor(constructor, changeInfo); }
private static boolean shouldProcessInstanceMembers( @NotNull GrTypeDefinition grType, @Nullable PsiElement lastParent) { if (lastParent != null) { final GrModifierList modifierList = grType.getModifierList(); if (modifierList != null && modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_LANG_CATEGORY) != null) { return false; } } return true; }
@NotNull private static List<PsiClass> getInnerClassesForResolve( @NotNull final GrTypeDefinition grType, @Nullable final PsiElement lastParent, @NotNull final PsiElement place) { if (lastParent instanceof GrReferenceList || PsiTreeUtil.getParentOfType(place, GrReferenceList.class) != null) { return Arrays.asList(grType.getInnerClasses()); } List<PsiClass> classes = RecursionManager.doPreventingRecursion( grType, true, new Computable<List<PsiClass>>() { @Override public List<PsiClass> compute() { List<PsiClass> result = new ArrayList<PsiClass>(); for (CandidateInfo info : CollectClassMembersUtil.getAllInnerClasses(grType, false).values()) { final PsiClass inner = (PsiClass) info.getElement(); final PsiClass containingClass = inner.getContainingClass(); assert containingClass != null; if (lastParent == null || !containingClass.isInterface() || PsiTreeUtil.isAncestor(containingClass, place, false)) { ContainerUtil.addIfNotNull(result, inner); } } return result; } }); if (classes == null) { return Arrays.asList(grType.getInnerClasses()); } return classes; }
@NotNull public static PsiClass[] getSupers(GrTypeDefinition grType) { PsiClassType[] superTypes = grType.getSuperTypes(); List<PsiClass> result = new ArrayList<PsiClass>(); for (PsiClassType superType : superTypes) { PsiClass superClass = superType.resolve(); if (superClass != null) { result.add(superClass); } } return result.toArray(new PsiClass[result.size()]); }
@Nullable public static PsiClass findInnerClassByName( GrTypeDefinition grType, String name, boolean checkBases) { if (!checkBases) { for (PsiClass inner : grType.getInnerClasses()) { if (name.equals(inner.getName())) return inner; } return null; } else { Map<String, CandidateInfo> innerClasses = CollectClassMembersUtil.getAllInnerClasses(grType, true); final CandidateInfo info = innerClasses.get(name); return info == null ? null : (PsiClass) info.getElement(); } }
private static Set<ReadWriteVariableInstruction> collectUsedVariableWithoutInitialization( GrTypeDefinition typeDefinition) { final Set<ReadWriteVariableInstruction> vars = ContainerUtil.newLinkedHashSet(); typeDefinition.acceptChildren( new GroovyRecursiveElementVisitor() { private void collectVars(Instruction[] flow) { ReadWriteVariableInstruction[] reads = ControlFlowBuilderUtil.getReadsWithoutPriorWrites(flow, false); Collections.addAll(vars, reads); } @Override public void visitField(GrField field) { GrExpression initializer = field.getInitializerGroovy(); if (initializer != null) { Instruction[] flow = new ControlFlowBuilder(field.getProject()).buildControlFlow(initializer); collectVars(flow); } } @Override public void visitMethod(GrMethod method) { GrOpenBlock block = method.getBlock(); if (block != null) { collectVars(block.getControlFlow()); } } @Override public void visitClassInitializer(GrClassInitializer initializer) { GrOpenBlock block = initializer.getBlock(); collectVars(block.getControlFlow()); } }); return vars; }
public static boolean processDeclarations( @NotNull GrTypeDefinition grType, @NotNull PsiScopeProcessor processor, @NotNull ResolveState state, @Nullable PsiElement lastParent, @NotNull PsiElement place) { if (place instanceof GrCodeReferenceElement && lastParent instanceof GrModifierList) { final PsiElement possibleAnnotation = PsiTreeUtil.skipParentsOfType(place, GrCodeReferenceElement.class); if (possibleAnnotation instanceof GrAnnotation && possibleAnnotation.getParent() == lastParent) { return true; // don't process class members while resolving annotation which annotates // current class } } for (final PsiTypeParameter typeParameter : grType.getTypeParameters()) { if (!processElement(processor, typeParameter, state)) return false; } NameHint nameHint = processor.getHint(NameHint.KEY); String name = nameHint == null ? null : nameHint.getName(state); ClassHint classHint = processor.getHint(ClassHint.KEY); final PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY); final PsiElementFactory factory = JavaPsiFacade.getElementFactory(place.getProject()); boolean processInstanceMethods = (shouldProcessMethods(classHint) || shouldProcessProperties(classHint)) && shouldProcessInstanceMembers(grType, lastParent); LanguageLevel level = PsiUtil.getLanguageLevel(place); if (shouldProcessProperties(classHint)) { Map<String, CandidateInfo> fieldsMap = CollectClassMembersUtil.getAllFields(grType); if (name != null) { CandidateInfo fieldInfo = fieldsMap.get(name); if (fieldInfo != null) { if (!processField( grType, processor, state, place, processInstanceMethods, substitutor, factory, level, fieldInfo)) { return false; } } else if (grType.isTrait() && lastParent != null) { PsiField field = findFieldByName(grType, name, false, true); if (field != null && field.hasModifierProperty(PsiModifier.PUBLIC)) { if (!processField( grType, processor, state, place, processInstanceMethods, substitutor, factory, level, new CandidateInfo(field, PsiSubstitutor.EMPTY))) { return false; } } } } else { for (CandidateInfo info : fieldsMap.values()) { if (!processField( grType, processor, state, place, processInstanceMethods, substitutor, factory, level, info)) { return false; } } if (grType.isTrait() && lastParent != null) { for (PsiField field : CollectClassMembersUtil.getFields(grType, true)) { if (field.hasModifierProperty(PsiModifier.PUBLIC)) { if (!processField( grType, processor, state, place, processInstanceMethods, substitutor, factory, level, new CandidateInfo(field, PsiSubstitutor.EMPTY))) { return false; } } } } } } if (shouldProcessMethods(classHint)) { Map<String, List<CandidateInfo>> methodsMap = CollectClassMembersUtil.getAllMethods(grType, true); boolean isPlaceGroovy = place.getLanguage() == GroovyFileType.GROOVY_LANGUAGE; if (name == null) { for (List<CandidateInfo> list : methodsMap.values()) { for (CandidateInfo info : list) { if (!processMethod( grType, processor, state, place, processInstanceMethods, substitutor, factory, level, isPlaceGroovy, info)) { return false; } } } } else { List<CandidateInfo> byName = methodsMap.get(name); if (byName != null) { for (CandidateInfo info : byName) { if (!processMethod( grType, processor, state, place, processInstanceMethods, substitutor, factory, level, isPlaceGroovy, info)) { return false; } } } } } final GrTypeDefinitionBody body = grType.getBody(); if (body != null) { if (shouldProcessClasses(classHint)) { for (PsiClass innerClass : getInnerClassesForResolve(grType, lastParent, place)) { final String innerClassName = innerClass.getName(); if (nameHint != null && !innerClassName.equals(nameHint.getName(state))) { continue; } if (!processor.execute(innerClass, state)) { return false; } } } } return true; }
public static PsiClassType createBaseClassType(GrTypeDefinition grType) { if (grType.isEnum()) { return TypesUtil.createTypeByFQClassName(CommonClassNames.JAVA_LANG_ENUM, grType); } return TypesUtil.getJavaLangObject(grType); }
@Override public void collectMethods( @NotNull GrTypeDefinition typeDefinition, Collection<PsiMethod> collector) { if (typeDefinition.getName() == null) return; PsiModifierList modifierList = typeDefinition.getModifierList(); if (modifierList == null) return; final PsiAnnotation tupleConstructor = modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_TUPLE_CONSTRUCTOR); final boolean immutable = modifierList.findAnnotation(IMMUTABLE) != null || modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_IMMUTABLE) != null; final PsiAnnotation canonical = modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_CANONICAL); if (!immutable && canonical == null && tupleConstructor == null) { return; } if (tupleConstructor != null && typeDefinition.getCodeConstructors().length > 0 && !PsiUtil.getAnnoAttributeValue(tupleConstructor, "force", false)) { return; } final GrLightMethodBuilder fieldsConstructor = new GrLightMethodBuilder(typeDefinition.getManager(), typeDefinition.getName()); fieldsConstructor.setConstructor(true).setNavigationElement(typeDefinition); Set<String> excludes = new HashSet<String>(); if (tupleConstructor != null) { for (String s : PsiUtil.getAnnoAttributeValue(tupleConstructor, "excludes", "").split(",")) { final String name = s.trim(); if (StringUtil.isNotEmpty(name)) { excludes.add(name); } } } if (tupleConstructor != null) { final boolean superFields = PsiUtil.getAnnoAttributeValue(tupleConstructor, "includeSuperFields", false); final boolean superProperties = PsiUtil.getAnnoAttributeValue(tupleConstructor, "includeSuperProperties", false); if (superFields || superProperties) { addParametersForSuper( typeDefinition, fieldsConstructor, superFields, superProperties, new HashSet<PsiClass>(), excludes); } } addParameters( typeDefinition, fieldsConstructor, tupleConstructor == null || PsiUtil.getAnnoAttributeValue(tupleConstructor, "includeProperties", true), tupleConstructor != null ? PsiUtil.getAnnoAttributeValue(tupleConstructor, "includeFields", false) : canonical == null, !immutable, excludes); collector.add(fieldsConstructor.setContainingClass(typeDefinition)); collector.add( new GrLightMethodBuilder(typeDefinition.getManager(), typeDefinition.getName()) .addParameter("args", CommonClassNames.JAVA_UTIL_MAP, false) .setConstructor(true) .setContainingClass(typeDefinition)); }
private static void startTemplate( GrTypeParameterList oldTypeParameterList, final Project project, final GrTypeDefinition psiClass, final GrTypeDefinition targetClass, boolean includeClassName) { PsiElementFactory jfactory = JavaPsiFacade.getElementFactory(project); final GroovyPsiElementFactory elementFactory = GroovyPsiElementFactory.getInstance(project); GrCodeReferenceElement ref = elementFactory.createCodeReferenceElementFromClass(psiClass); try { if (psiClass.isInterface()) { GrImplementsClause clause = targetClass.getImplementsClause(); if (clause == null) { clause = (GrImplementsClause) targetClass.addAfter( elementFactory.createImplementsClause(), targetClass.getNameIdentifierGroovy()); } ref = (GrCodeReferenceElement) clause.add(ref); } else { GrExtendsClause clause = targetClass.getExtendsClause(); if (clause == null) { clause = (GrExtendsClause) targetClass.addAfter( elementFactory.createExtendsClause(), targetClass.getNameIdentifierGroovy()); } ref = (GrCodeReferenceElement) clause.add(ref); } if (psiClass.hasTypeParameters() || includeClassName) { final Editor editor = CodeInsightUtil.positionCursor( project, targetClass.getContainingFile(), targetClass.getLBrace()); final TemplateBuilderImpl templateBuilder = editor == null || ApplicationManager.getApplication().isUnitTestMode() ? null : (TemplateBuilderImpl) TemplateBuilderFactory.getInstance().createTemplateBuilder(targetClass); if (includeClassName && templateBuilder != null) { templateBuilder.replaceElement(targetClass.getNameIdentifier(), targetClass.getName()); } if (oldTypeParameterList != null) { for (PsiTypeParameter parameter : oldTypeParameterList.getTypeParameters()) { final PsiElement param = ref.getTypeArgumentList() .add(elementFactory.createTypeElement(jfactory.createType(parameter))); if (templateBuilder != null) { templateBuilder.replaceElement(param, param.getText()); } } } final GrTypeParameterList typeParameterList = targetClass.getTypeParameterList(); assert typeParameterList != null; typeParameterList.replace(oldTypeParameterList); if (templateBuilder != null) { templateBuilder.setEndVariableBefore(ref); final Template template = templateBuilder.buildTemplate(); template.addEndVariable(); final PsiFile containingFile = targetClass.getContainingFile(); PsiDocumentManager.getInstance(project) .doPostponedOperationsAndUnblockDocument(editor.getDocument()); final TextRange textRange = targetClass.getTextRange(); final int startClassOffset = textRange.getStartOffset(); editor.getDocument().deleteString(textRange.getStartOffset(), textRange.getEndOffset()); CreateFromUsageBaseFix.startTemplate( editor, template, project, new TemplateEditingAdapter() { @Override public void templateFinished(Template template, boolean brokenOff) { chooseAndImplement( psiClass, project, PsiTreeUtil.getParentOfType( containingFile.findElementAt(startClassOffset), GrTypeDefinition.class), editor); } }, getTitle(psiClass)); } } } catch (IncorrectOperationException e) { LOG.error(e); } }
public ChangeExtendsImplementsQuickFix(@NotNull GrTypeDefinition aClass) { myClass = aClass; myExtendsClause = aClass.getExtendsClause(); myImplementsClause = aClass.getImplementsClause(); }
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { return myClass.isValid() && myClass.getManager().isInProject(file); }