/* * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jetbrains.plugins.groovy.refactoring.convertToJava; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiModifier; import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMembersDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; import java.util.Collection; /** * @author Maxim.Medvedev */ public class ClassGenerator { private final ClassNameProvider classNameProvider; private final ClassItemGenerator classItemGenerator; public ClassGenerator(ClassNameProvider classNameProvider, ClassItemGenerator classItemGenerator) { this.classNameProvider = classNameProvider; this.classItemGenerator = classItemGenerator; } private void writePackageStatement(StringBuilder text, GrPackageDefinition packageDefinition) { if (packageDefinition != null) { ModifierListGenerator.writeModifiers(text, packageDefinition.getAnnotationList(), ModifierListGenerator.JAVA_MODIFIERS, classItemGenerator.generateAnnotations()); text.append("package "); text.append(packageDefinition.getPackageName()); text.append(';'); text.append('\n'); text.append('\n'); } } public void writeTypeDefinition(StringBuilder text, @NotNull final PsiClass typeDefinition, boolean toplevel, boolean insertPackageSmst) { final boolean isScript = typeDefinition instanceof GroovyScriptClass; final GroovyFile containingFile = (GroovyFile)typeDefinition.getContainingFile(); if (insertPackageSmst) { writePackageStatement(text, containingFile.getPackageDefinition()); } GenerationUtil.writeDocComment(text, typeDefinition, true); boolean isEnum = typeDefinition.isEnum(); boolean isAnnotationType = typeDefinition.isAnnotationType(); boolean isInterface = typeDefinition.isInterface(); ModifierListGenerator.writeClassModifiers(text, typeDefinition.getModifierList(), typeDefinition.isInterface(), typeDefinition.isEnum(), toplevel, classItemGenerator.generateAnnotations()); if (isAnnotationType) { text.append('@'); } if (isInterface) { text.append("interface"); } else if (isEnum) { text.append("enum"); } else { text.append("class"); } text.append(' ').append(typeDefinition.getName()); GenerationUtil.writeTypeParameters(text, typeDefinition, classNameProvider); text.append(' '); if (isScript) { text.append("extends ").append(GroovyCommonClassNames.GROOVY_LANG_SCRIPT).append(' '); } else if (!isEnum && !isAnnotationType) { classItemGenerator.writeExtendsList(text, typeDefinition); classItemGenerator.writeImplementsList(text, typeDefinition); } text.append("{\n"); writeMembers(text, typeDefinition); text.append('}'); } public void writeMembers(StringBuilder text, PsiClass typeDefinition) { if (typeDefinition instanceof GrEnumTypeDefinition) { final GrEnumConstant[] enumConstants = ((GrEnumTypeDefinition)typeDefinition).getEnumConstants(); for (GrEnumConstant constant : enumConstants) { classItemGenerator.writeEnumConstant(text, constant); text.append(','); } if (enumConstants.length > 0) { //text.removeFromTheEnd(1).append(";\n"); text.delete(text.length() - 1, text.length()); } text.append(";\n"); } writeAllMethods(text, classItemGenerator.collectMethods(typeDefinition), typeDefinition); if (typeDefinition instanceof GrTypeDefinition) { for (GrMembersDeclaration declaration : ((GrTypeDefinition)typeDefinition).getMemberDeclarations()) { if (declaration instanceof GrVariableDeclaration) { classItemGenerator.writeVariableDeclarations(text, (GrVariableDeclaration)declaration); } } for (PsiClass inner : typeDefinition.getInnerClasses()) { writeTypeDefinition(text, inner, false, false); text.append('\n'); } } classItemGenerator.writePostponed(text, typeDefinition); } private void writeAllMethods(StringBuilder text, Collection<PsiMethod> methods, PsiClass aClass) { for (PsiMethod method : methods) { if (!shouldBeGenerated(method)) continue; if (method.isConstructor()) { classItemGenerator.writeConstructor(text, method, aClass.isEnum()); } else { classItemGenerator.writeMethod(text, method); text.append('\n'); } } } private static boolean shouldBeGenerated(PsiMethod method) { for (PsiMethod psiMethod : method.findSuperMethods()) { if (!psiMethod.hasModifierProperty(PsiModifier.ABSTRACT)) { final PsiType type = method.getReturnType(); final PsiType superType = psiMethod.getReturnType(); if (type != null && superType != null && !superType.isAssignableFrom(type)) { return false; } } } return true; } }