diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyImportOptimizer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyImportOptimizer.java index 01de3d6043e7..2897b649fd43 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyImportOptimizer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyImportOptimizer.java @@ -23,6 +23,7 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.util.containers.CollectionFactory; +import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.containers.HashSet; import gnu.trove.TObjectIntHashMap; import gnu.trove.TObjectIntProcedure; @@ -30,7 +31,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.*; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; -import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; @@ -38,8 +38,6 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import java.util.*; -import static org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil.isImportToJavaOrJavax; - /** * @author ven */ @@ -52,7 +50,7 @@ public class GroovyImportOptimizer implements ImportOptimizer { public static Set findUsedImports(GroovyFile file) { Set usedImports = new HashSet(); - processFile(file, null, null, usedImports, null, null); + processFile(file, null, null, usedImports, null, null, null, null); return usedImports; } @@ -65,7 +63,9 @@ public class GroovyImportOptimizer implements ImportOptimizer { @Nullable final Set staticallyImportedMembers, @Nullable final Set usedImports, @Nullable final Set implicitlyImported, - @Nullable final Set innerClasses) { + @Nullable final Set innerClasses, + @Nullable final Map aliased, + @Nullable final Map annotations) { if (!(file instanceof GroovyFile)) return; ((GroovyFile)file).accept(new GroovyRecursiveElementVisitor() { @@ -91,7 +91,8 @@ public class GroovyImportOptimizer implements ImportOptimizer { if (usedImports != null) { usedImports.add(importStatement); } - if (!importStatement.isAliasedImport()) { + + if (!importStatement.isAliasedImport() && !isAnnotatedImport(importStatement)) { String importedName = null; if (importStatement.isOnDemand()) { @@ -123,6 +124,22 @@ public class GroovyImportOptimizer implements ImportOptimizer { if (importedName == null) return; + final String importRef = getImportReferenceText(importStatement); + + if (annotations != null) { + if (isAnnotatedImport(importStatement)) { + annotations.put(importRef, importStatement.getAnnotationList().getText()); + } + } + + + if (importStatement.isAliasedImport()) { + if (aliased != null) { + aliased.put(importRef, importedName); + } + return; + } + if (importStatement.isStatic()) { if (staticallyImportedMembers != null) { staticallyImportedMembers.add(importedName); @@ -183,12 +200,15 @@ public class GroovyImportOptimizer implements ImportOptimizer { if (document != null) { documentManager.commitDocument(document); } - final Set importedClasses = new LinkedHashSet(); + final Set simplyImportedClasses = new LinkedHashSet(); final Set staticallyImportedMembers = new LinkedHashSet(); final Set usedImports = new HashSet(); - final Set implicitlyImported = new LinkedHashSet(); - final HashSet innerClasses = new HashSet(); - processFile(myFile, importedClasses, staticallyImportedMembers, usedImports, implicitlyImported, innerClasses); + final Set implicitlyImportedClasses = new LinkedHashSet(); + final Set innerClasses = new HashSet(); + Map aliasImported = ContainerUtilRt.newHashMap(); + Map annotatedImports = ContainerUtilRt.newHashMap(); + + processFile(myFile, simplyImportedClasses, staticallyImportedMembers, usedImports, implicitlyImportedClasses, innerClasses, aliasImported, annotatedImports); final List oldImports = PsiUtil.getValidImportStatements(file); if (myRemoveUnusedOnly) { for (GrImportStatement oldImport : oldImports) { @@ -199,48 +219,23 @@ public class GroovyImportOptimizer implements ImportOptimizer { return; } - Map annotations = new HashMap(); - - // Getting aliased imports - GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(file.getProject()); - ArrayList aliased = new ArrayList(); - for (GrImportStatement oldImport : oldImports) { - if (oldImport.isAliasedImport() && usedImports.contains(oldImport)) { - aliased.add(factory.createImportStatementFromText(oldImport.getText())); - } - else { - String importReference = getImportReferenceText(oldImport); - GrModifierList annotationList = oldImport.getAnnotationList(); - if (importReference != null && annotationList != null) { - annotations.put(importReference, annotationList.getText()); - } - } - } - // Add new import statements - GrImportStatement[] newImports = prepare(importedClasses, staticallyImportedMembers, implicitlyImported, innerClasses); - if (oldImports.isEmpty() && newImports.length == 0 && aliased.isEmpty()) { + GrImportStatement[] newImports = prepare(usedImports, simplyImportedClasses, staticallyImportedMembers, implicitlyImportedClasses, innerClasses, aliasImported, annotatedImports); + if (oldImports.isEmpty() && newImports.length == 0 && aliasImported.isEmpty()) { return; } - GroovyFile tempFile = (GroovyFile)PsiFileFactory.getInstance(file.getProject()).createFileFromText("a.groovy", ""); + GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(file.getProject()); + + GroovyFile tempFile = factory.createGroovyFile("", false, null); - for (GrImportStatement aliasedImport : aliased) { - tempFile.addImport(aliasedImport); - } for (GrImportStatement newImport : newImports) { - String imported = getImportReferenceText(newImport); - String annos = annotations.get(imported); - if (imported != null && StringUtil.isNotEmpty(annos)) { - newImport = factory.createImportStatementFromText(annos + " " + newImport.getText()); - } - tempFile.addImport(newImport); } - String oldText = oldImports.isEmpty() ? "" : - myFile.getText().substring(oldImports.get(0).getTextRange().getStartOffset(), - oldImports.get(oldImports.size() - 1).getTextRange().getEndOffset()); + final int startOffset = oldImports.get(0).getTextRange().getStartOffset(); + final int endOffset = oldImports.get(oldImports.size() - 1).getTextRange().getEndOffset(); + String oldText = oldImports.isEmpty() ? "" : myFile.getText().substring(startOffset, endOffset); if (tempFile.getText().trim().equals(oldText)) { return; } @@ -249,26 +244,18 @@ public class GroovyImportOptimizer implements ImportOptimizer { file.addImport(statement); } - file.removeImport(file.addImport(factory.createImportStatementFromText("import xxxx"))); //to remove trailing whitespaces - for (GrImportStatement importStatement : oldImports) { file.removeImport(importStatement); } } - @Nullable - private String getImportReferenceText(GrImportStatement statement) { - GrCodeReferenceElement importReference = statement.getImportReference(); - if (importReference != null) { - return statement.getText().substring(importReference.getStartOffsetInParent()); - } - return null; - } - - private GrImportStatement[] prepare(Set importedClasses, + private GrImportStatement[] prepare(final Set usedImports, + Set importedClasses, Set staticallyImportedMembers, Set implicitlyImported, - Set innerClasses) { + Set innerClasses, + Map aliased, + final Map annotations) { final Project project = myFile.getProject(); final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(project); final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project); @@ -277,7 +264,12 @@ public class GroovyImportOptimizer implements ImportOptimizer { TObjectIntHashMap classCountMap = new TObjectIntHashMap(); for (String importedClass : importedClasses) { - if (implicitlyImported.contains(importedClass) || innerClasses.contains(importedClass)) continue; + if (implicitlyImported.contains(importedClass) || + innerClasses.contains(importedClass) || + aliased.containsKey(importedClass) || + annotations.containsKey(importedClass)) { + continue; + } final String packageName = StringUtil.getPackageName(importedClass); @@ -286,7 +278,10 @@ public class GroovyImportOptimizer implements ImportOptimizer { } for (String importedMember : staticallyImportedMembers) { + if (aliased.containsKey(importedMember) || annotations.containsKey(importedMember)) continue; + final String className = StringUtil.getPackageName(importedMember); + if (!classCountMap.containsKey(className)) classCountMap.put(className, 0); classCountMap.increment(className); } @@ -295,8 +290,13 @@ public class GroovyImportOptimizer implements ImportOptimizer { final List result = new ArrayList(); packageCountMap.forEachEntry(new TObjectIntProcedure() { public boolean execute(String s, int i) { - if (i >= settings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND) { - result.add(factory.createImportStatementFromText(s, false, true, null)); + if (i >= settings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND || settings.PACKAGES_TO_USE_IMPORT_ON_DEMAND.contains(s)) { + final GrImportStatement imp = factory.createImportStatementFromText(s, false, true, null); + String annos = annotations.get(s + ".*"); + if (annos != null) { + imp.getAnnotationList().replace(factory.createModifierList(annos)); + } + result.add(imp); final PsiPackage aPackage = JavaPsiFacade.getInstance(myFile.getProject()).findPackage(s); if (aPackage != null) { for (PsiClass clazz : aPackage.getClasses(myFile.getResolveScope())) { @@ -311,7 +311,12 @@ public class GroovyImportOptimizer implements ImportOptimizer { classCountMap.forEachEntry(new TObjectIntProcedure() { public boolean execute(String s, int i) { if (i >= settings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND) { - result.add(factory.createImportStatementFromText(s, true, true, null)); + final GrImportStatement imp = factory.createImportStatementFromText(s, true, true, null); + String annos = annotations.get(s + ".*"); + if (annos != null) { + imp.getAnnotationList().replace(factory.createModifierList(annos)); + } + result.add(imp); } return true; } @@ -320,43 +325,45 @@ public class GroovyImportOptimizer implements ImportOptimizer { List explicated = CollectionFactory.arrayList(); for (String importedClass : importedClasses) { final String parentName = StringUtil.getPackageName(importedClass); - if (packageCountMap.get(parentName) >= settings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND) continue; - if (implicitlyImported.contains(importedClass) && - !onDemandImportedSimpleClassNames.contains(StringUtil.getShortName(importedClass))) { - continue; + if (!annotations.containsKey(importedClass) && !aliased.containsKey(importedClass)) { + if (packageCountMap.get(parentName) >= settings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND || + settings.PACKAGES_TO_USE_IMPORT_ON_DEMAND.contains(parentName)) { + continue; + } + if (implicitlyImported.contains(importedClass) && + !onDemandImportedSimpleClassNames.contains(StringUtil.getShortName(importedClass))) { + continue; + } } - explicated.add(factory.createImportStatementFromText(importedClass, false, false, null)); + final GrImportStatement imp = factory.createImportStatementFromText(importedClass, false, false, null); + String annos = annotations.get(importedClass); + if (annos != null) { + imp.getAnnotationList().replace(factory.createModifierList(annos)); + } + explicated.add(imp); } for (String importedMember : staticallyImportedMembers) { final String className = StringUtil.getPackageName(importedMember); - if (classCountMap.get(className) >= settings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND) continue; + if (!annotations.containsKey(importedMember) && !aliased.containsKey(importedMember)) { + if (classCountMap.get(className) >= settings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND) continue; + } result.add(factory.createImportStatementFromText(importedMember, true, false, null)); } - final Comparator comparator = new Comparator() { - public int compare(GrImportStatement statement1, GrImportStatement statement2) { - if (settings.LAYOUT_STATIC_IMPORTS_SEPARATELY) { - if (statement1.isStatic() && !statement2.isStatic()) return 1; - if (statement2.isStatic() && !statement1.isStatic()) return -1; + for (GrImportStatement anImport : usedImports) { + if (anImport.isAliasedImport() || isAnnotatedImport(anImport)) { + if (anImport.isStatic()) { + result.add(anImport); } - - if (!statement1.isStatic() && !statement2.isStatic()) { - if (isImportToJavaOrJavax(statement1) && !isImportToJavaOrJavax(statement2)) return 1; - if (!isImportToJavaOrJavax(statement1) && isImportToJavaOrJavax(statement2)) return -1; + else { + explicated.add(anImport); } - - - final GrCodeReferenceElement ref1 = statement1.getImportReference(); - final GrCodeReferenceElement ref2 = statement2.getImportReference(); - String name1 = ref1 != null ? PsiUtil.getQualifiedReferenceText(ref1) : null; - String name2 = ref2 != null ? PsiUtil.getQualifiedReferenceText(ref2) : null; - if (name1 == null) return name2 == null ? 0 : -1; - if (name2 == null) return 1; - return name1.compareTo(name2); } - }; + } + + final Comparator comparator = getComparator(settings); Collections.sort(result, comparator); Collections.sort(explicated, comparator); @@ -364,4 +371,36 @@ public class GroovyImportOptimizer implements ImportOptimizer { return explicated.toArray(new GrImportStatement[explicated.size()]); } } + + private static boolean isAnnotatedImport(GrImportStatement anImport) { + return !StringUtil.isEmptyOrSpaces(anImport.getAnnotationList().getText()); + } + + public static Comparator getComparator(final CodeStyleSettings settings) { + return new Comparator() { + public int compare(GrImportStatement statement1, GrImportStatement statement2) { + if (settings.LAYOUT_STATIC_IMPORTS_SEPARATELY) { + if (statement1.isStatic() && !statement2.isStatic()) return 1; + if (statement2.isStatic() && !statement1.isStatic()) return -1; + } + + final GrCodeReferenceElement ref1 = statement1.getImportReference(); + final GrCodeReferenceElement ref2 = statement2.getImportReference(); + String name1 = ref1 != null ? PsiUtil.getQualifiedReferenceText(ref1) : null; + String name2 = ref2 != null ? PsiUtil.getQualifiedReferenceText(ref2) : null; + if (name1 == null) return name2 == null ? 0 : -1; + if (name2 == null) return 1; + return name1.compareTo(name2); + } + }; + } + + @Nullable + private static String getImportReferenceText(GrImportStatement statement) { + GrCodeReferenceElement importReference = statement.getImportReference(); + if (importReference != null) { + return statement.getText().substring(importReference.getStartOffsetInParent()); + } + return null; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java index 4c9e7f7037c8..370d44a05dfe 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java @@ -28,6 +28,7 @@ import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocMemberReference; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocReferenceElement; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocTag; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrLabel; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature; import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; @@ -64,6 +65,8 @@ public abstract class GroovyPsiElementFactory implements JVMElementFactory { public abstract GrBlockStatement createBlockStatementFromText(String text, @Nullable PsiElement context); + public abstract GrModifierList createModifierList(String text); + public static GroovyPsiElementFactory getInstance(Project project) { return ServiceManager.getService(project, GroovyPsiElementFactory.class); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java index 8c5f23028ba9..94edbd7e2b70 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java @@ -17,12 +17,18 @@ package org.jetbrains.plugins.groovy.lang.psi.impl; import com.intellij.extapi.psi.PsiFileBase; -import com.intellij.lang.ASTNode; +import com.intellij.lang.FileASTNode; import com.intellij.lang.Language; import com.intellij.openapi.fileTypes.FileType; -import com.intellij.psi.*; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.FileViewProvider; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.codeStyle.PackageEntry; +import com.intellij.psi.codeStyle.PackageEntryTable; import com.intellij.psi.stubs.StubElement; -import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IFileElementType; import com.intellij.reference.SoftReference; import com.intellij.util.IncorrectOperationException; @@ -31,7 +37,10 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; -import org.jetbrains.plugins.groovy.lang.psi.*; +import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; +import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrTopLevelDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; @@ -41,6 +50,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMe import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrReflectedMethod; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.GrTopStatement; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ControlFlowBuilder; @@ -48,6 +58,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import static org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil.*; + /** * @author ilyas */ @@ -135,43 +147,40 @@ public abstract class GroovyFileBaseImpl extends PsiFileBase implements GroovyFi } public void removeImport(GrImportStatement importStatement) throws IncorrectOperationException { - PsiElement before = importStatement.getPrevSibling(); - while (before instanceof PsiWhiteSpace || hasElementType(before, GroovyTokenTypes.mNLS)) { + PsiElement before = importStatement; + while (isWhiteSpace(before.getPrevSibling())) { before = before.getPrevSibling(); } - PsiElement rangeStart = importStatement; - if (before != null && !(before instanceof PsiImportStatement) && before != importStatement.getPrevSibling()) { - rangeStart = before.getNextSibling(); - final PsiElement el = addBefore(GroovyPsiElementFactory.getInstance(getProject()).createLineTerminator(2), rangeStart); - rangeStart=el.getNextSibling(); + if (hasElementType(before.getPrevSibling(), GroovyTokenTypes.mSEMI)) before = before.getPrevSibling(); + if (isWhiteSpace(before.getPrevSibling())) before = before.getPrevSibling(); + + PsiElement after = importStatement; + if (isWhiteSpace(after.getNextSibling())) after = after.getNextSibling(); + if (hasElementType(after.getNextSibling(), GroovyTokenTypes.mSEMI)) after = after.getNextSibling(); + while (isWhiteSpace(after.getNextSibling())) after = after.getNextSibling(); + + + if (before == null) before = importStatement; + + PsiElement anchor_before = before.getPrevSibling(); + PsiElement anchor_after = after.getNextSibling(); + if (before == after) { + importStatement.delete(); + } + else { + deleteChildRange(before, after); } - PsiElement rangeEnd = importStatement; - while (true) { - final PsiElement next = rangeEnd.getNextSibling(); - if (!(next instanceof PsiWhiteSpace) && !hasElementType(next, GroovyTokenTypes.mSEMI)) { - break; - } - rangeEnd = next; + if (anchor_before instanceof GrImportStatement && anchor_after instanceof GrImportStatement) { + addLineFeedAfter((GrImportStatement)anchor_before); } - final PsiElement last = hasElementType(rangeEnd.getNextSibling(), GroovyTokenTypes.mNLS) ? rangeEnd.getNextSibling() : rangeEnd; - if (rangeStart != null && last != null) { - deleteChildRange(rangeStart, last); + else if (anchor_before != null && anchor_after != null) { + String text = anchor_after instanceof GrTopStatement && anchor_before instanceof GrTopStatement ? "\n\n" : "\n"; + getNode().addLeaf(GroovyTokenTypes.mNLS, text, anchor_after.getNode()); } } - private static boolean hasElementType(PsiElement next, final IElementType type) { - if (next == null) { - return false; - } - final ASTNode astNode = next.getNode(); - if (astNode != null && astNode.getElementType() == type) { - return true; - } - return false; - } - public void removeElements(PsiElement[] elements) throws IncorrectOperationException { for (PsiElement element : elements) { if (element.isValid()) { @@ -246,8 +255,108 @@ public abstract class GroovyFileBaseImpl extends PsiFileBase implements GroovyFi @Override public void deleteChildRange(PsiElement first, PsiElement last) throws IncorrectOperationException { if (last instanceof GrTopStatement) { - PsiImplUtil.deleteStatementTail(this, last); + deleteStatementTail(this, last); } super.deleteChildRange(first, last); } + + protected void addLineFeedBefore(GrImportStatement result) { + final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(getProject()).getCurrentSettings(); + final PackageEntryTable layoutTable = settings.IMPORT_LAYOUT_TABLE; + final PackageEntry[] entries = layoutTable.getEntries(); + + PsiElement prev = result.getPrevSibling(); + while (isWhiteSpace(prev)) { + prev = prev.getPrevSibling(); + } + if (hasElementType(prev, GroovyTokenTypes.mSEMI)) prev = prev.getPrevSibling(); + if (isWhiteSpace(prev)) prev = prev.getPrevSibling(); + + if (prev instanceof GrImportStatement) { + final int idx_before = getPackageEntryIdx(entries, (GrImportStatement)prev); + final int idx = getPackageEntryIdx(entries, result); + final int spaceCount = getMaxSpaceCount(entries, idx_before, idx); + + //skip space and semicolon after import + if (isWhiteSpace(prev.getNextSibling()) && hasElementType(prev.getNextSibling().getNextSibling(), GroovyTokenTypes.mSEMI)) prev = prev.getNextSibling().getNextSibling(); + final FileASTNode node = getNode(); + while (isWhiteSpace(prev.getNextSibling())) { + node.removeChild(prev.getNextSibling().getNode()); + } + node.addLeaf(GroovyTokenTypes.mNLS, StringUtil.repeat("\n", spaceCount + 1), result.getNode()); + } + } + + protected void addLineFeedAfter(GrImportStatement result) { + final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(getProject()).getCurrentSettings(); + final PackageEntryTable layoutTable = settings.IMPORT_LAYOUT_TABLE; + final PackageEntry[] entries = layoutTable.getEntries(); + + PsiElement next = result.getNextSibling(); + if (isWhiteSpace(next)) next = next.getNextSibling(); + if (hasElementType(next, GroovyTokenTypes.mSEMI)) next = next.getNextSibling(); + while (isWhiteSpace(next)) { + next = next.getNextSibling(); + } + if (next instanceof GrImportStatement) { + final int idx_after = getPackageEntryIdx(entries, (GrImportStatement)next); + final int idx = getPackageEntryIdx(entries, result); + final int spaceCount = getMaxSpaceCount(entries, idx, idx_after); + + + final FileASTNode node = getNode(); + while (isWhiteSpace(next.getPrevSibling())) { + node.removeChild(next.getPrevSibling().getNode()); + } + node.addLeaf(GroovyTokenTypes.mNLS, StringUtil.repeat("\n", spaceCount + 1), next.getNode()); + } + } + + protected static int getPackageEntryIdx(PackageEntry[] entries, GrImportStatement statement) { + final GrCodeReferenceElement reference = statement.getImportReference(); + if (reference == null) return -1; + final String packageName = StringUtil.getPackageName(reference.getCanonicalText()); + final boolean isStatic = statement.isStatic(); + + int best = -1; + int allOtherStatic = -1; + int allOther = -1; + PackageEntry bestEntry = null; + for (int i = 0, length = entries.length; i < length; i++) { + PackageEntry entry = entries[i]; + if (entry.isBetterMatchForPackageThan(bestEntry, packageName, isStatic)) { + best = i; + bestEntry = entry; + } + else if (entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY) { + allOtherStatic = i; + } + else if (entry == PackageEntry.ALL_OTHER_IMPORTS_ENTRY) { + allOther = i; + } + } + if (best >= 0) return best; + + if (isStatic && allOtherStatic != -1) return allOtherStatic; + return allOther; + } + + private static int getMaxSpaceCount(PackageEntry[] entries, int b1, int b2) { + int start = Math.min(b1, b2); + int end = Math.max(b1, b2); + + int max = 0; + int cur = 0; + for (int i = start; i < end; i++) { + if (entries[i] == PackageEntry.BLANK_LINE_ENTRY) { + cur++; + } + else { + max = Math.max(max, cur); + cur = 0; + } + } + max = Math.max(max, cur); + return max; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java index ff55fbefb67b..8fd357385038 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java @@ -18,12 +18,9 @@ package org.jetbrains.plugins.groovy.lang.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; -import com.intellij.psi.codeStyle.CodeStyleManager; -import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.codeStyle.*; import com.intellij.psi.impl.ElementBase; import com.intellij.psi.scope.DelegatingScopeProcessor; import com.intellij.psi.scope.PsiScopeProcessor; @@ -38,6 +35,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.GroovyIcons; import org.jetbrains.plugins.groovy.extensions.GroovyScriptTypeDetector; +import org.jetbrains.plugins.groovy.lang.editor.GroovyImportOptimizer; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; @@ -61,11 +59,10 @@ import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint; import javax.swing.*; import java.util.ArrayList; +import java.util.Comparator; import java.util.LinkedHashSet; import java.util.List; -import static org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil.isImportToJavaOrJavax; - /** * Implements all abstractions related to Groovy file * @@ -193,7 +190,7 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { PsiElement lastParent, PsiElement place, PsiScopeProcessor importProcessor, - GrImportStatement[] importStatements, + GrImportStatement[] importStatements, boolean shouldProcessOnDemand) { for (int i = importStatements.length - 1; i >= 0; i--) { final GrImportStatement imp = importStatements[i]; @@ -324,11 +321,9 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { public GrImportStatement addImportForClass(PsiClass aClass) { try { // Calculating position - Project project = aClass.getProject(); - GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project); + GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(getProject()); GrImportStatement importStatement = factory.createImportStatementFromText(aClass.getQualifiedName(), false, false, null); - PsiElement anchor = getAnchorToInsertImportAfter(); - return (GrImportStatement)addAfter(importStatement, anchor); + return addImport(importStatement); } catch (IncorrectOperationException e) { LOG.error(e); @@ -337,81 +332,57 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { } @Nullable - private PsiElement getAnchorToInsertImportAfter() { + private PsiElement getAnchorToInsertImportAfter(GrImportStatement statement) { + final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(getProject()).getCurrentSettings(); + final PackageEntryTable layoutTable = settings.IMPORT_LAYOUT_TABLE; + final PackageEntry[] entries = layoutTable.getEntries(); + GrImportStatement[] importStatements = getImportStatements(); - if (importStatements.length > 0) { - return importStatements[importStatements.length - 1]; - } - else if (getPackageDefinition() != null) { - return getPackageDefinition(); - } - else if (getShellComment() != null) { + if (importStatements.length == 0) { + final GrPackageDefinition definition = getPackageDefinition(); + if (definition != null) { + return definition; + } + return getShellComment(); } - return null; - } + final Comparator comparator = GroovyImportOptimizer.getComparator(settings); + final int idx = getPackageEntryIdx(entries, statement); + + PsiElement anchor = null; + + for (GrImportStatement importStatement : importStatements) { + final int i = getPackageEntryIdx(entries, importStatement); + if (i < idx) { + anchor = importStatement; + } + else if (i > idx) { + break; + } + else if (comparator.compare(statement, importStatement) > 0) { + anchor = importStatement; + } + else { + break; + } + } + + if (anchor == null) anchor = getPackageDefinition(); + if (anchor == null) anchor = getShellComment(); + if (anchor == null && importStatements.length > 0) anchor = importStatements[0].getPrevSibling(); + return anchor; + } public GrImportStatement addImport(GrImportStatement statement) throws IncorrectOperationException { - PsiElement anchor = getAnchorToInsertImportAfter(); + PsiElement anchor = getAnchorToInsertImportAfter(statement); final PsiElement result = addAfter(statement, anchor); - if (anchor != null) { - int lineFeedCount = 0; - - if (isAddLineFeed(statement, anchor)) { - lineFeedCount++; - } - - final PsiElement prev = result.getPrevSibling(); - if (prev instanceof PsiWhiteSpace) { - lineFeedCount += StringUtil.getOccurrenceCount(prev.getText(), '\n'); - } - if (lineFeedCount > 0) { - getNode().addLeaf(GroovyTokenTypes.mNLS, StringUtil.repeatSymbol('\n', lineFeedCount), result.getNode()); - } - if (prev instanceof PsiWhiteSpace) { - prev.delete(); - } - } - - GrImportStatement importStatement = (GrImportStatement)result; - PsiElement next = importStatement.getNextSibling(); - if (next != null) { - ASTNode node = next.getNode(); - if (node != null && GroovyTokenTypes.mNLS == node.getElementType()) { - next.replace(GroovyPsiElementFactory.getInstance(statement.getProject()).createLineTerminator(2)); - } - } - return importStatement; - } - - private static boolean isAddLineFeed(GrImportStatement statement, PsiElement anchor) { - if (!(anchor instanceof GrImportStatement)) { - return true; - } - - final GrImportStatement _anchor = (GrImportStatement)anchor; - - //aliases - if (statement.isAliasedImport() || _anchor.isAliasedImport()) { - return _anchor.isAliasedImport() ^ statement.isAliasedImport(); - } - - //static imports - if (CodeStyleSettingsManager.getSettings(statement.getProject()).LAYOUT_STATIC_IMPORTS_SEPARATELY) { - if (statement.isStatic() || _anchor.isStatic()) { - return statement.isStatic() ^ _anchor.isStatic(); - } - } - - //imports to std lib - if (isImportToJavaOrJavax(statement) || isImportToJavaOrJavax(_anchor)) { - return isImportToJavaOrJavax(statement) ^ isImportToJavaOrJavax(_anchor); - } - - return false; + final GrImportStatement gImport = (GrImportStatement)result; + addLineFeedBefore(gImport); + addLineFeedAfter(gImport); + return gImport; } public boolean isScript() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index 993e6af531cb..06b02bbf27df 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -41,6 +41,7 @@ import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocTag; import org.jetbrains.plugins.groovy.lang.psi.*; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrLabel; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature; import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; @@ -685,6 +686,12 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { return (GrBlockStatement)branch; } + @Override + public GrModifierList createModifierList(String text) { + final GrMethod method = createMethodFromText(text + " void foo()"); + return method.getModifierList(); + } + public GrImportStatement createImportStatementFromText(String qName, boolean isStatic, boolean isOnDemand, String alias) { final String text = "import " + (isStatic ? "static " : "") + qName + (isOnDemand ? ".*" : "") + (alias != null && alias.length() > 0 ? " as " + alias : ""); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java index ca7ef37880cd..d3fa456b17db 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java @@ -30,6 +30,7 @@ import com.intellij.psi.impl.source.tree.AstBufferUtil; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureUtil; import com.intellij.psi.util.PsiTreeUtil; @@ -65,8 +66,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrReflectedMethod; -import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic.GrAdditiveExpressionImpl; @@ -691,15 +690,20 @@ public class PsiImplUtil { return type; } - - public static boolean isImportToJavaOrJavax(GrImportStatement statement) { - final GrCodeReferenceElement ref = statement.getImportReference(); - if (ref==null) return false; - final String text = ref.getText(); - return text.startsWith("java.") || text.startsWith("javax."); - } public static boolean isWhiteSpace(PsiElement element) { - return element != null && TokenSets.WHITE_SPACES_SET.contains(element.getNode().getElementType()); + return hasElementType(element, TokenSets.WHITE_SPACES_SET); + } + + public static boolean hasElementType(PsiElement next, final IElementType type) { + if (next == null) return false; + final ASTNode astNode = next.getNode(); + return astNode != null && astNode.getElementType() == type; + } + + public static boolean hasElementType(PsiElement next, final TokenSet set) { + if (next == null) return false; + final ASTNode astNode = next.getNode(); + return astNode != null && set.contains(astNode.getElementType()); } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy index 740d0b58e8ca..ed7aab357926 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy @@ -1,286 +1,286 @@ -/* - * Copyright 2000-2010 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.completion; - - -import com.intellij.codeInsight.completion.CompletionType -import com.intellij.codeInsight.completion.StaticallyImportable -import com.intellij.codeInsight.lookup.LookupElement -import com.intellij.codeInsight.lookup.LookupElementPresentation -import com.intellij.codeInsight.lookup.LookupManager -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase -import org.jetbrains.annotations.NotNull -import org.jetbrains.annotations.Nullable -import org.jetbrains.plugins.groovy.util.TestUtils - -/** - * @author Maxim.Medvedev - */ -public class GroovyClassNameCompletionTest extends LightCodeInsightFixtureTestCase { - private boolean old; - - @Override - protected String getBasePath() { - return TestUtils.getTestDataPath() + "groovy/completion/classNameCompletion"; - } - - private void doTest() throws Exception { - addClassToProject("a", "FooBar"); - myFixture.configureByFile(getTestName(false) + ".groovy"); - complete() - myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); - } - - private void addClassToProject(@Nullable String packageName, @NotNull String name) throws IOException { - myFixture.addClass("package $packageName; public class $name {}"); - } - - public void testInFieldDeclaration() throws Exception {doTest();} - public void testInParameter() throws Exception {doTest();} - public void testInImport() throws Exception {doTest();} - - public void testWhenClassExistsInSamePackage() throws Exception { - addClassToProject("a", "FooBar") - myFixture.configureByFile(getTestName(false) + ".groovy") - complete() - def lookup = LookupManager.getActiveLookup(myFixture.editor) - lookup.currentItem = lookup.items[1] - myFixture.type('\n') - myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); - } - - public void testInComment() throws Exception {doTest();} - public void testInTypeElementPlace() throws Exception {doTest();} - public void testWhenImportExists() throws Exception{doTest();} - - public void testFinishByDot() throws Exception{ - addClassToProject("a", "FooBar"); - myFixture.configureByText("a.groovy", "FBa") - complete() - myFixture.type '.'.charAt(0) - myFixture.checkResult "a.FooBar.a" - } - - private LookupElement[] complete() { - myFixture.complete(CompletionType.BASIC, 2) - } - - public void testDelegateBasicToClassName() throws Exception{ - addClassToProject("a", "FooBarGooDoo"); - myFixture.configureByText("a.groovy", "FBGDa") - myFixture.complete(CompletionType.BASIC, 2) - myFixture.type '.'.charAt(0) - myFixture.checkResult "a.FooBarGooDoo.a" - } - - public void testDelegateBasicToClassNameAutoinsert() throws Exception{ - addClassToProject("a", "FooBarGooDoo"); - myFixture.configureByText("a.groovy", "FBGD") - myFixture.complete(CompletionType.BASIC, 2) - myFixture.checkResult "a.FooBarGooDoo" - } - - public void testImportedStaticMethod() throws Exception { - myFixture.addFileToProject("b.groovy", """ -class Foo { - static def abcmethod1(int a) {} - static def abcmethod2(int a) {} -}""") - myFixture.configureByText("a.groovy", """def foo() { - abcme -}""") - def item = complete()[0] - - LookupElementPresentation presentation = renderElement(item) - assert "Foo.abcmethod1" == presentation.itemText - assert presentation.tailText == "(int a)" - - ((StaticallyImportable) item).shouldBeImported = true - myFixture.type('\n') - myFixture.checkResult """import static Foo.abcmethod1 - -def foo() { - abcmethod1() -}""" - - } - - public void testImportedStaticField() throws Exception { - myFixture.addFileToProject("b.groovy", """ -class Foo { - static def abcfield1 - static def abcfield2 -}""") - myFixture.configureByText("a.groovy", """def foo() { - abcfi -}""") - def item = complete()[0] - ((StaticallyImportable) item).shouldBeImported = true - myFixture.type('\n') - myFixture.checkResult """import static Foo.abcfield1 - -def foo() { - abcfield1 -}""" - - } - - public void testImportedInterfaceConstant() throws Exception { - myFixture.addFileToProject("b.groovy", """ -interface Foo { - static def abcfield1 = 2 - static def abcfield2 = 3 -}""") - myFixture.configureByText("a.groovy", """def foo() { - abcfi -}""") - def item = complete()[0] - ((StaticallyImportable) item).shouldBeImported = true - myFixture.type('\n') - myFixture.checkResult """import static Foo.abcfield1 - -def foo() { - abcfield1 -}""" - - } - - public void testQualifiedStaticMethod() throws Exception { - myFixture.addFileToProject("foo/b.groovy", """package foo -class Foo { - static def abcmethod(int a) {} -}""") - myFixture.configureByText("a.groovy", """def foo() { - abcme -}""") - complete() - myFixture.checkResult """import foo.Foo - -def foo() { - Foo.abcmethod() -}""" - - } - - public void testQualifiedStaticMethodIfThereAreAlreadyStaticImportsFromThatClass() throws Exception { - myFixture.addFileToProject("foo/b.groovy", """package foo -class Foo { - static def abcMethod() {} - static def anotherMethod() {} -}""") - myFixture.configureByText("a.groovy", """ -import static foo.Foo.anotherMethod - -anotherMethod() -abcmex""") - def element = assertOneElement(complete()[0]) - - LookupElementPresentation presentation = renderElement(element) - assert "abcMethod" == presentation.itemText - assert presentation.tailText == "() in Foo (foo)" - - myFixture.type('\t') - myFixture.checkResult """ -import static foo.Foo.anotherMethod -import static foo.Foo.abcMethod - -anotherMethod() -abcMethod()""" - - } - - private LookupElementPresentation renderElement(LookupElement element) { - return LookupElementPresentation.renderElement(element) - } - - public void testNewClassName() { - addClassToProject("foo", "Fxoo") - myFixture.configureByText("a.groovy", "new Fxo\n") - myFixture.complete(CompletionType.BASIC, 2) - myFixture.checkResult """import foo.Fxoo - -new Fxoo()\n""" - - } - - public void testNewImportedClassName() { - myFixture.configureByText("a.groovy", "new ArrayIndexOut\n") - myFixture.completeBasic() - myFixture.checkResult "new ArrayIndexOutOfBoundsException()\n" - } - - public void testOnlyAnnotationsAfterAt() { - myFixture.addClass "class AbcdClass {}; @interface AbcdAnno {}" - myFixture.configureByText "a.groovy", "@Abcd" - complete() - assert myFixture.lookupElementStrings[0] == 'AbcdAnno' - } - - public void testOnlyExceptionsInCatch() { - myFixture.addClass "class AbcdClass {}; class AbcdException extends Throwable {}" - myFixture.configureByText "a.groovy", "try {} catch (Abcd" - complete() - assert myFixture.lookupElementStrings[0] == 'AbcdException' - } - - public void testClassNameInMultilineString() { - myFixture.configureByText "a.groovy", 'def s = """a\nAIOOBE\na"""' - complete() - myFixture.checkResult 'def s = """a\njava.lang.ArrayIndexOutOfBoundsException\na"""' - } - - public void testDoubleClass() { - myFixture.addClass "package foo; public class Zooooooo {}" - myFixture.configureByText("a.groovy", """import foo.Zooooooo -Zoooox""") - assertOneElement(myFixture.completeBasic()) - } - - public void testClassOnlyOnce() { - myFixture.addClass('class FooBarGoo {}') - myFixture.configureByText('a.groovy', 'FoBaGo') - assert !complete() - myFixture.checkResult('''FooBarGoo''') - } - - public void testMethodFromTheSameClass() { - myFixture.configureByText("a.groovy", """ -class A { - static void foo() {} - - static void goo() { - f - } -} -""") - def items = complete() - def fooItem = items.find { renderElement(it).itemText == 'foo' } - LookupManager.getActiveLookup(myFixture.editor).currentItem = fooItem - myFixture.type '\n' - myFixture.checkResult ''' -class A { - static void foo() {} - - static void goo() { - foo() - } -} -''' - } - - - -} +/* + * Copyright 2000-2010 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.completion; + + +import com.intellij.codeInsight.completion.CompletionType +import com.intellij.codeInsight.completion.StaticallyImportable +import com.intellij.codeInsight.lookup.LookupElement +import com.intellij.codeInsight.lookup.LookupElementPresentation +import com.intellij.codeInsight.lookup.LookupManager +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import org.jetbrains.annotations.NotNull +import org.jetbrains.annotations.Nullable +import org.jetbrains.plugins.groovy.util.TestUtils + +/** + * @author Maxim.Medvedev + */ +public class GroovyClassNameCompletionTest extends LightCodeInsightFixtureTestCase { + private boolean old; + + @Override + protected String getBasePath() { + return TestUtils.getTestDataPath() + "groovy/completion/classNameCompletion"; + } + + private void doTest() throws Exception { + addClassToProject("a", "FooBar"); + myFixture.configureByFile(getTestName(false) + ".groovy"); + complete() + myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); + } + + private void addClassToProject(@Nullable String packageName, @NotNull String name) throws IOException { + myFixture.addClass("package $packageName; public class $name {}"); + } + + public void testInFieldDeclaration() throws Exception {doTest();} + public void testInParameter() throws Exception {doTest();} + public void testInImport() throws Exception {doTest();} + + public void testWhenClassExistsInSamePackage() throws Exception { + addClassToProject("a", "FooBar") + myFixture.configureByFile(getTestName(false) + ".groovy") + complete() + def lookup = LookupManager.getActiveLookup(myFixture.editor) + lookup.currentItem = lookup.items[1] + myFixture.type('\n') + myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); + } + + public void testInComment() throws Exception {doTest();} + public void testInTypeElementPlace() throws Exception {doTest();} + public void testWhenImportExists() throws Exception{doTest();} + + public void testFinishByDot() throws Exception{ + addClassToProject("a", "FooBar"); + myFixture.configureByText("a.groovy", "FBa") + complete() + myFixture.type '.'.charAt(0) + myFixture.checkResult "a.FooBar.a" + } + + private LookupElement[] complete() { + myFixture.complete(CompletionType.BASIC, 2) + } + + public void testDelegateBasicToClassName() throws Exception{ + addClassToProject("a", "FooBarGooDoo"); + myFixture.configureByText("a.groovy", "FBGDa") + myFixture.complete(CompletionType.BASIC, 2) + myFixture.type '.'.charAt(0) + myFixture.checkResult "a.FooBarGooDoo.a" + } + + public void testDelegateBasicToClassNameAutoinsert() throws Exception{ + addClassToProject("a", "FooBarGooDoo"); + myFixture.configureByText("a.groovy", "FBGD") + myFixture.complete(CompletionType.BASIC, 2) + myFixture.checkResult "a.FooBarGooDoo" + } + + public void testImportedStaticMethod() throws Exception { + myFixture.addFileToProject("b.groovy", """ +class Foo { + static def abcmethod1(int a) {} + static def abcmethod2(int a) {} +}""") + myFixture.configureByText("a.groovy", """def foo() { + abcme +}""") + def item = complete()[0] + + LookupElementPresentation presentation = renderElement(item) + assert "Foo.abcmethod1" == presentation.itemText + assert presentation.tailText == "(int a)" + + ((StaticallyImportable) item).shouldBeImported = true + myFixture.type('\n') + myFixture.checkResult """import static Foo.abcmethod1 + +def foo() { + abcmethod1() +}""" + + } + + public void testImportedStaticField() throws Exception { + myFixture.addFileToProject("b.groovy", """ +class Foo { + static def abcfield1 + static def abcfield2 +}""") + myFixture.configureByText("a.groovy", """def foo() { + abcfi +}""") + def item = complete()[0] + ((StaticallyImportable) item).shouldBeImported = true + myFixture.type('\n') + myFixture.checkResult """import static Foo.abcfield1 + +def foo() { + abcfield1 +}""" + + } + + public void testImportedInterfaceConstant() throws Exception { + myFixture.addFileToProject("b.groovy", """ +interface Foo { + static def abcfield1 = 2 + static def abcfield2 = 3 +}""") + myFixture.configureByText("a.groovy", """def foo() { + abcfi +}""") + def item = complete()[0] + ((StaticallyImportable) item).shouldBeImported = true + myFixture.type('\n') + myFixture.checkResult """import static Foo.abcfield1 + +def foo() { + abcfield1 +}""" + + } + + public void testQualifiedStaticMethod() throws Exception { + myFixture.addFileToProject("foo/b.groovy", """package foo +class Foo { + static def abcmethod(int a) {} +}""") + myFixture.configureByText("a.groovy", """def foo() { + abcme +}""") + complete() + myFixture.checkResult """import foo.Foo + +def foo() { + Foo.abcmethod() +}""" + + } + + public void testQualifiedStaticMethodIfThereAreAlreadyStaticImportsFromThatClass() throws Exception { + myFixture.addFileToProject("foo/b.groovy", """package foo +class Foo { + static def abcMethod() {} + static def anotherMethod() {} +}""") + myFixture.configureByText("a.groovy", """ +import static foo.Foo.anotherMethod + +anotherMethod() +abcmex""") + def element = assertOneElement(complete()[0]) + + LookupElementPresentation presentation = renderElement(element) + assert "abcMethod" == presentation.itemText + assert presentation.tailText == "() in Foo (foo)" + + myFixture.type('\t') + myFixture.checkResult """\ +import static foo.Foo.abcMethod +import static foo.Foo.anotherMethod + +anotherMethod() +abcMethod()""" + + } + + private LookupElementPresentation renderElement(LookupElement element) { + return LookupElementPresentation.renderElement(element) + } + + public void testNewClassName() { + addClassToProject("foo", "Fxoo") + myFixture.configureByText("a.groovy", "new Fxo\n") + myFixture.complete(CompletionType.BASIC, 2) + myFixture.checkResult """import foo.Fxoo + +new Fxoo()\n""" + + } + + public void testNewImportedClassName() { + myFixture.configureByText("a.groovy", "new ArrayIndexOut\n") + myFixture.completeBasic() + myFixture.checkResult "new ArrayIndexOutOfBoundsException()\n" + } + + public void testOnlyAnnotationsAfterAt() { + myFixture.addClass "class AbcdClass {}; @interface AbcdAnno {}" + myFixture.configureByText "a.groovy", "@Abcd" + complete() + assert myFixture.lookupElementStrings[0] == 'AbcdAnno' + } + + public void testOnlyExceptionsInCatch() { + myFixture.addClass "class AbcdClass {}; class AbcdException extends Throwable {}" + myFixture.configureByText "a.groovy", "try {} catch (Abcd" + complete() + assert myFixture.lookupElementStrings[0] == 'AbcdException' + } + + public void testClassNameInMultilineString() { + myFixture.configureByText "a.groovy", 'def s = """a\nAIOOBE\na"""' + complete() + myFixture.checkResult 'def s = """a\njava.lang.ArrayIndexOutOfBoundsException\na"""' + } + + public void testDoubleClass() { + myFixture.addClass "package foo; public class Zooooooo {}" + myFixture.configureByText("a.groovy", """import foo.Zooooooo +Zoooox""") + assertOneElement(myFixture.completeBasic()) + } + + public void testClassOnlyOnce() { + myFixture.addClass('class FooBarGoo {}') + myFixture.configureByText('a.groovy', 'FoBaGo') + assert !complete() + myFixture.checkResult('''FooBarGoo''') + } + + public void testMethodFromTheSameClass() { + myFixture.configureByText("a.groovy", """ +class A { + static void foo() {} + + static void goo() { + f + } +} +""") + def items = complete() + def fooItem = items.find { renderElement(it).itemText == 'foo' } + LookupManager.getActiveLookup(myFixture.editor).currentItem = fooItem + myFixture.type '\n' + myFixture.checkResult ''' +class A { + static void foo() {} + + static void goo() { + foo() + } +} +''' + } + + + +} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/move/GroovyMoveClassToInnerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/move/GroovyMoveClassToInnerTest.groovy index 751d0267b6e5..140ce4d0f3cc 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/move/GroovyMoveClassToInnerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/move/GroovyMoveClassToInnerTest.groovy @@ -48,13 +48,27 @@ public class GroovyMoveClassToInnerTest extends GroovyMoveTestBase { } public void testInsertInnerClassImport() throws Exception { - CodeStyleSettingsManager.getSettings(myFixture.project).INSERT_INNER_CLASS_IMPORTS = true; - doTest("pack2.A", "pack1.Class1"); + final settings = CodeStyleSettingsManager.getSettings(myFixture.project) + def oldValue = settings.INSERT_INNER_CLASS_IMPORTS + settings.INSERT_INNER_CLASS_IMPORTS = true; + try { + doTest("pack2.A", "pack1.Class1"); + } + finally { + settings.INSERT_INNER_CLASS_IMPORTS = oldValue + } } public void testSimultaneousMove() throws Exception { - CodeStyleSettingsManager.instance.currentSettings.INSERT_INNER_CLASS_IMPORTS = false - doTest("pack2.A", "pack1.Class1", "pack0.Class0"); + final settings = CodeStyleSettingsManager.instance.currentSettings + final oldValue = settings.INSERT_INNER_CLASS_IMPORTS + settings.INSERT_INNER_CLASS_IMPORTS = false + try { + doTest("pack2.A", "pack1.Class1", "pack0.Class0"); + } + finally { + settings.INSERT_INNER_CLASS_IMPORTS = oldValue + } } public void testMoveMultiple1() throws Exception { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy index aab4fbe077f3..ec1999b9d22f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy @@ -24,8 +24,8 @@ import com.intellij.openapi.fileEditor.impl.TrailingSpacesStripper import com.intellij.psi.codeStyle.CodeStyleSettings import com.intellij.psi.codeStyle.CodeStyleSettingsManager import com.intellij.psi.impl.source.PostprocessReformattingAspect -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl +import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.bugs.GroovyAccessibilityInspection import org.jetbrains.plugins.groovy.lang.editor.GroovyImportOptimizer import org.jetbrains.plugins.groovy.util.TestUtils @@ -33,84 +33,83 @@ import org.jetbrains.plugins.groovy.util.TestUtils /** * @author ilyas */ -public class OptimizeImportsTest extends LightCodeInsightFixtureTestCase { +public class OptimizeImportsTest extends LightGroovyTestCase { + + final String basePath = "${TestUtils.testDataPath}optimizeImports/" @Override - protected String getBasePath() { - return "${TestUtils.testDataPath}optimizeImports/"; - } - - @Override protected void setUp() { + protected void setUp() { super.setUp() CodeInsightSettings.instance.OPTIMIZE_IMPORTS_ON_THE_FLY = true ((CodeInsightTestFixtureImpl)myFixture).canChangeDocumentDuringHighlighting(true) } - @Override protected void tearDown() { + @Override + protected void tearDown() { CodeInsightSettings.instance.OPTIMIZE_IMPORTS_ON_THE_FLY = false super.tearDown() } - public void testNewline() throws Throwable { + public void testNewline() { doTest(); } - public void testAliased() throws Throwable { + public void testAliased() { doTest(); } - public void testSimpleOptimize() throws Throwable { + public void testSimpleOptimize() { doTest(); } - public void testCommented() throws Throwable { + public void testCommented() { doTest(); } - public void testOptimizeExists() throws Throwable { + public void testOptimizeExists() { doTest(); } - public void testOptimizeAlias() throws Throwable { + public void testOptimizeAlias() { doTest(); } - public void testFoldImports() throws Throwable { + public void testFoldImports() { doTest(); } - public void testFoldImports2() throws Throwable { + public void testFoldImports2() { doTest(); } - public void testUntypedCall() throws Throwable { + public void testUntypedCall() { doTest(); } - public void testFoldImports3() throws Throwable { + public void testFoldImports3() { doTest(); } - public void testFoldImports4() throws Throwable { + public void testFoldImports4() { doTest(); } - public void testFoldImports5() throws Throwable { + public void testFoldImports5() { doTest(); } - public void testFixPoint() throws Throwable { + public void testFixPoint() { doTest(); } - public void testPreserveImportAnnotations() throws Throwable { doTest(); } + public void testPreserveImportAnnotations() { doTest(); } - public void testUtilListMasked() throws Throwable { + public void testUtilListMasked() { myFixture.addClass("package java.awt; public class List {}"); doTest(); } - public void testExtraLineFeed() throws Throwable { + public void testExtraLineFeed() { myFixture.addClass("package groovy.io; public class EncodingAwareBufferedWriter {}"); myFixture.addClass("package groovy.io; public class PlatformLineWriter {}"); myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(false) + ".groovy", "foo/bar.groovy")); @@ -119,37 +118,37 @@ public class OptimizeImportsTest extends LightCodeInsightFixtureTestCase { myFixture.checkResultByFile(getTestName(false) + ".groovy"); } - public void testSemicolons() throws Throwable { + public void testSemicolons() { doTest(); } - public void testSameFile() throws Throwable { + public void testSameFile() { doTest(); } - public void testJavaUtilString() throws Throwable { doTest(); } + public void testJavaUtilString() { doTest(); } - public void testSamePackage() throws Throwable { + public void testSamePackage() { myFixture.addClass("package foo; public class Bar {}"); myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(false) + ".groovy", "foo/Foo.groovy")); doOptimizeImports(); myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); } - public void testQualifiedUsage() throws Throwable { + public void testQualifiedUsage() { myFixture.addClass("package foo; public class Bar {}"); doTest(); } - public void testFileHeader() throws Throwable { + public void testFileHeader() { doTest(); } - public void testRemoveImplicitlyImported() throws Throwable { doTest(); } - public void testRemoveImplicitlyDemandImported() throws Throwable { doTest(); } - public void testDontRemoveRedImports() throws Throwable { doTest(); } + public void testRemoveImplicitlyImported() { doTest(); } + public void testRemoveImplicitlyDemandImported() { doTest(); } + public void testDontRemoveRedImports() { doTest(); } - public void testRemoveSamePackaged() throws Throwable { + public void testRemoveSamePackaged() { myFixture.addClass("package foo.bar; public class Aaaa {}"); myFixture.addClass("package foo.bar; public class Bbbb {}"); myFixture.addClass("package foo.bar; public class Zzzz {}"); @@ -182,7 +181,7 @@ class Fooxx { }"""); } - private void doTest() throws Throwable { + private void doTest() { CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()).clone(); CodeStyleSettingsManager.getInstance(getProject()).setTemporarySettings(settings); settings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND = 3; @@ -235,7 +234,7 @@ class Fooxx { myFixture.checkResult "import foo.Foo\n\ndef foo() { \n Foo f}" } - public void testUnusedImportsForImportsOnDemand() throws Exception { + public void testUnusedImportsForImportsOnDemand() { myFixture.enableInspections(new GroovyAccessibilityInspection()) myFixture.testHighlighting(true, false, false, getTestName(false) + ".groovy") myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); @@ -249,7 +248,7 @@ class Fooxx { myFixture.addClass("package test; public class Alias{public static void test(){}}") myFixture.addClass("package test; public class Alias2{public static void test2(){}}") - myFixture.configureByText('__a.groovy', ''' + myFixture.configureByText('__a.groovy', '''\ package pack @@ -276,12 +275,9 @@ aliased2() doOptimizeImports() - myFixture.checkResult(''' + myFixture.checkResult('''\ package pack -import static test.Alias.test as aliased -import static test.Alias2.test2 as aliased2 - import foo.Bar import foo.Foo @@ -290,6 +286,8 @@ import java.test2.Test2 import static foo.Bar.foo0 import static java.test.Test.foo +import static test.Alias.test as aliased +import static test.Alias2.test2 as aliased2 new Foo() new Bar() diff --git a/plugins/groovy/testdata/optimizeImports/Aliased_after.groovy b/plugins/groovy/testdata/optimizeImports/Aliased_after.groovy index d73da0751467..7dde07cae235 100644 --- a/plugins/groovy/testdata/optimizeImports/Aliased_after.groovy +++ b/plugins/groovy/testdata/optimizeImports/Aliased_after.groovy @@ -1,9 +1,8 @@ package org.gradle -import java.sql.Connection as Con -import java.sql.Clob as CB - import java.sql.Blob +import java.sql.Clob as CB +import java.sql.Connection as Con Blob blob = null CB cb = null diff --git a/plugins/groovy/testdata/optimizeImports/Commented_after.groovy b/plugins/groovy/testdata/optimizeImports/Commented_after.groovy index 02265809dc36..70fba0b96995 100644 --- a/plugins/groovy/testdata/optimizeImports/Commented_after.groovy +++ b/plugins/groovy/testdata/optimizeImports/Commented_after.groovy @@ -1,5 +1,4 @@ -import javax.swing.JFrame - +import javax.swing.* // preved! def frame = new JFrame() \ No newline at end of file diff --git a/plugins/groovy/testdata/optimizeImports/FileHeader_after.groovy b/plugins/groovy/testdata/optimizeImports/FileHeader_after.groovy index ba53b02f78ab..e605c9089fab 100644 --- a/plugins/groovy/testdata/optimizeImports/FileHeader_after.groovy +++ b/plugins/groovy/testdata/optimizeImports/FileHeader_after.groovy @@ -2,6 +2,7 @@ * asdf lsd */ + import java.sql.Blob Blob blob = null \ No newline at end of file diff --git a/plugins/groovy/testdata/optimizeImports/FoldImports2_after.groovy b/plugins/groovy/testdata/optimizeImports/FoldImports2_after.groovy index 05585b061653..e797b88819d7 100644 --- a/plugins/groovy/testdata/optimizeImports/FoldImports2_after.groovy +++ b/plugins/groovy/testdata/optimizeImports/FoldImports2_after.groovy @@ -1,5 +1,4 @@ -import javax.swing.JDialog -import javax.swing.JTable +import javax.swing.* def table = new JTable() def dialog = new JDialog() \ No newline at end of file diff --git a/plugins/groovy/testdata/optimizeImports/FoldImports3_after.groovy b/plugins/groovy/testdata/optimizeImports/FoldImports3_after.groovy index 199b80cfade0..a11c61c73d4a 100644 --- a/plugins/groovy/testdata/optimizeImports/FoldImports3_after.groovy +++ b/plugins/groovy/testdata/optimizeImports/FoldImports3_after.groovy @@ -1,6 +1,5 @@ -import javax.swing.JButton as JB - import javax.swing.* +import javax.swing.JButton as JB def frame = new JFrame() def table = new JTable() diff --git a/plugins/groovy/testdata/optimizeImports/FoldImports4_after.groovy b/plugins/groovy/testdata/optimizeImports/FoldImports4_after.groovy index 199b80cfade0..a11c61c73d4a 100644 --- a/plugins/groovy/testdata/optimizeImports/FoldImports4_after.groovy +++ b/plugins/groovy/testdata/optimizeImports/FoldImports4_after.groovy @@ -1,6 +1,5 @@ -import javax.swing.JButton as JB - import javax.swing.* +import javax.swing.JButton as JB def frame = new JFrame() def table = new JTable() diff --git a/plugins/groovy/testdata/optimizeImports/FoldImports5_after.groovy b/plugins/groovy/testdata/optimizeImports/FoldImports5_after.groovy index 229d78216dd7..8efa35ff586a 100644 --- a/plugins/groovy/testdata/optimizeImports/FoldImports5_after.groovy +++ b/plugins/groovy/testdata/optimizeImports/FoldImports5_after.groovy @@ -1,5 +1,5 @@ -import java.security.Policy import javax.swing.* +import java.security.Policy def frame = new JFrame() def table = new JTable() diff --git a/plugins/groovy/testdata/optimizeImports/OptimizeExists_after.groovy b/plugins/groovy/testdata/optimizeImports/OptimizeExists_after.groovy index 90dbf23a5c5e..5130cf16e8d6 100644 --- a/plugins/groovy/testdata/optimizeImports/OptimizeExists_after.groovy +++ b/plugins/groovy/testdata/optimizeImports/OptimizeExists_after.groovy @@ -1,3 +1,3 @@ -import javax.swing.JFrame +import javax.swing.* def frame = new JFrame() \ No newline at end of file diff --git a/plugins/groovy/testdata/optimizeImports/UtilListMasked_after.groovy b/plugins/groovy/testdata/optimizeImports/UtilListMasked_after.groovy index 275c7f581fb4..41db33bcd244 100644 --- a/plugins/groovy/testdata/optimizeImports/UtilListMasked_after.groovy +++ b/plugins/groovy/testdata/optimizeImports/UtilListMasked_after.groovy @@ -1,5 +1,5 @@ -import java.util.List import java.awt.* +import java.util.List Component a Container c diff --git a/plugins/groovy/testdata/refactoring/move/moveScript/moveScriptBasic/after/b/Script.groovy b/plugins/groovy/testdata/refactoring/move/moveScript/moveScriptBasic/after/b/Script.groovy index 91396140c85b..9231eb1b254c 100644 --- a/plugins/groovy/testdata/refactoring/move/moveScript/moveScriptBasic/after/b/Script.groovy +++ b/plugins/groovy/testdata/refactoring/move/moveScript/moveScriptBasic/after/b/Script.groovy @@ -1,7 +1,7 @@ -package b; +package b -import b.B import a.A; +import b.B; def a = new A().foo(); print a; diff --git a/plugins/groovy/testdata/refactoring/move/moveScript/multiMove/after/b/B.groovy b/plugins/groovy/testdata/refactoring/move/moveScript/multiMove/after/b/B.groovy index 96b71118a3e3..523a404dfccd 100644 --- a/plugins/groovy/testdata/refactoring/move/moveScript/multiMove/after/b/B.groovy +++ b/plugins/groovy/testdata/refactoring/move/moveScript/multiMove/after/b/B.groovy @@ -1,5 +1,4 @@ -package b; - +package b class B { def fooB(int i) { diff --git a/plugins/groovy/testdata/refactoring/move/moveScript/multiMove/after/b/Script.groovy b/plugins/groovy/testdata/refactoring/move/moveScript/multiMove/after/b/Script.groovy index a79526e626da..677c40a5374c 100644 --- a/plugins/groovy/testdata/refactoring/move/moveScript/multiMove/after/b/Script.groovy +++ b/plugins/groovy/testdata/refactoring/move/moveScript/multiMove/after/b/Script.groovy @@ -1,7 +1,6 @@ -package b; +package b - -import a.A; +import a.A def a = new A().foo(); print a; diff --git a/plugins/groovy/testdata/refactoring/move/moveScript/updateReferences/after/b/B.groovy b/plugins/groovy/testdata/refactoring/move/moveScript/updateReferences/after/b/B.groovy index 96b71118a3e3..523a404dfccd 100644 --- a/plugins/groovy/testdata/refactoring/move/moveScript/updateReferences/after/b/B.groovy +++ b/plugins/groovy/testdata/refactoring/move/moveScript/updateReferences/after/b/B.groovy @@ -1,5 +1,4 @@ -package b; - +package b class B { def fooB(int i) { diff --git a/plugins/groovy/testdata/refactoring/move/moveScript/updateReferences/after/b/Script.groovy b/plugins/groovy/testdata/refactoring/move/moveScript/updateReferences/after/b/Script.groovy index 0d27a1e93bcb..3daab62a8bf3 100644 --- a/plugins/groovy/testdata/refactoring/move/moveScript/updateReferences/after/b/Script.groovy +++ b/plugins/groovy/testdata/refactoring/move/moveScript/updateReferences/after/b/Script.groovy @@ -1,7 +1,7 @@ -package b; +package b -import b.B import a.A; +import b.B; def a = new A().foo(); print a;