From 8ed5a44898c10a98e4307893ae67d9083b442c4f Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 10 Aug 2010 15:23:48 +0400 Subject: [PATCH 01/36] CVS: correct Process usage for local & ext commections; no OsProcessHandler for this case --- .../connections/ConnectionOnProcess.java | 158 ++++++++++++++---- 1 file changed, 130 insertions(+), 28 deletions(-) diff --git a/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/connections/ConnectionOnProcess.java b/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/connections/ConnectionOnProcess.java index 7cf272c64afc..8b034c972ab8 100644 --- a/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/connections/ConnectionOnProcess.java +++ b/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/connections/ConnectionOnProcess.java @@ -17,18 +17,19 @@ package com.intellij.cvsSupport2.connections; import com.intellij.cvsSupport2.errorHandling.ErrorRegistry; import com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.execution.process.OSProcessHandler; -import com.intellij.execution.process.ProcessEvent; -import com.intellij.execution.process.ProcessListener; -import com.intellij.execution.process.ProcessOutputTypes; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.Key; +import com.intellij.openapi.vfs.encoding.EncodingManager; import com.intellij.util.EnvironmentUtil; +import com.intellij.util.concurrency.Semaphore; import org.netbeans.lib.cvsclient.connection.AuthenticationException; import org.netbeans.lib.cvsclient.connection.IConnection; import org.netbeans.lib.cvsclient.io.IStreamLogger; import java.io.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; /** * author: lesya @@ -47,13 +48,20 @@ public abstract class ConnectionOnProcess implements IConnection { private boolean myContainsError = false; protected final StringBuffer myErrorText = new StringBuffer(); + private Future myStdErrFuture; + private ReadProcessThread myErrThread; + private Semaphore myWaitSemaphore; + private Future myWaitForThreadFuture; - protected ConnectionOnProcess(String repository, ErrorRegistry errorRegistry) { + protected ConnectionOnProcess(String repository, ErrorRegistry errorRegistry) { myRepository = repository; myErrorRegistry = errorRegistry; } public synchronized void close() throws IOException { + myWaitForThreadFuture.cancel(true); + myWaitSemaphore.up(); + try { if (myInputStream != null && !myContainsError) { myInputStream.close(); @@ -75,6 +83,16 @@ public abstract class ConnectionOnProcess implements IConnection { } } + try { + myErrThread.setProcessTerminated(true); + myStdErrFuture.get(); + } + catch (InterruptedException e) { + // + } + catch (ExecutionException e) { + LOG.error(e); + } } finally { try { @@ -118,34 +136,22 @@ public abstract class ConnectionOnProcess implements IConnection { try { commandLine.setEnvParams(EnvironmentUtil.getEnviromentProperties()); myProcess = commandLine.createProcess(); - final OSProcessHandler processHandler = new OSProcessHandler(myProcess, commandLine.getCommandLineString()) { - protected Reader createProcessOutReader() { - return new InputStreamReader(new ByteArrayInputStream(new byte[0])); + myErrThread = new ReadProcessThread( + new BufferedReader(new InputStreamReader(myProcess.getErrorStream(), EncodingManager.getInstance().getDefaultCharset()))) { + protected void textAvailable(String s) { + myErrorText.append(s); + myErrorRegistry.registerError(s); + myContainsError = true; } }; - - processHandler.addProcessListener(new ProcessListener() { - public void startNotified(ProcessEvent event) { - } + final Application application = ApplicationManager.getApplication(); + myStdErrFuture = application.executeOnPooledThread(myErrThread); - public void processTerminated(ProcessEvent event) { - } - - public void processWillTerminate(ProcessEvent event, boolean willBeDestroyed) { - } - - public void onTextAvailable(ProcessEvent event, Key outputType) { - if (outputType == ProcessOutputTypes.STDERR) { - myErrorText.append(event.getText()); - myErrorRegistry.registerError(event.getText()); - myContainsError = true; - } - } - }); - myInputStream = myProcess.getInputStream(); myOutputStream = myProcess.getOutputStream(); + + waitForProcess(application); } catch (Exception e) { closeInternal(); @@ -153,6 +159,23 @@ public abstract class ConnectionOnProcess implements IConnection { } } + private void waitForProcess(Application application) { + myWaitSemaphore = new Semaphore(); + myWaitSemaphore.down(); + myWaitForThreadFuture = application.executeOnPooledThread(new Runnable() { + public void run() { + try { + myProcess.waitFor(); + } + catch (InterruptedException ignored) { + } + finally { + myWaitSemaphore.up(); + } + } + }); + } + protected void closeInternal() { try { close(); @@ -166,4 +189,83 @@ public abstract class ConnectionOnProcess implements IConnection { return myProcess != null; } + private abstract static class ReadProcessThread implements Runnable { + private final Reader myReader; + private boolean skipLF = false; + + private boolean myIsProcessTerminated = false; + private final char[] myBuffer = new char[8192]; + + public ReadProcessThread(final Reader reader) { + myReader = reader; + } + + public synchronized void setProcessTerminated(boolean isProcessTerminated) { + myIsProcessTerminated = isProcessTerminated; + } + + public void run() { + try { + while (readAvailable()) { + try { + Thread.sleep(50L); + } + catch (InterruptedException ignore) { + } + } + } + catch (Exception e) { + LOG.error(e); + } + } + + private synchronized boolean readAvailable() throws IOException { + char[] buffer = myBuffer; + StringBuilder token = new StringBuilder(); + while (myReader.ready()) { + int n = myReader.read(buffer); + if (n <= 0) break; + + for (int i = 0; i < n; i++) { + char c = buffer[i]; + if (skipLF && c != '\n') { + token.append('\r'); + } + + if (c == '\r') { + skipLF = true; + } + else { + skipLF = false; + token.append(c); + } + + if (c == '\n') { + textAvailable(token.toString()); + token.setLength(0); + } + } + } + + if (token.length() != 0) { + textAvailable(token.toString()); + token.setLength(0); + } + + if (myIsProcessTerminated) { + try { + myReader.close(); + } + catch (IOException e1) { + // supressed + } + + return false; + } + + return true; + } + + protected abstract void textAvailable(final String s); + } } From c336fa7fafb026c1ccd8400d1431cfca7a717efd Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Wed, 11 Aug 2010 12:59:33 +0400 Subject: [PATCH 02/36] IDEA-48975 Inspection "Access to unresolved expression" false positive for method access from number conversion to primitive types --- .../expressions/types/GrTypeCastExpressionImpl.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrTypeCastExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrTypeCastExpressionImpl.java index 32ac228df70e..850303e44dba 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrTypeCastExpressionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrTypeCastExpressionImpl.java @@ -17,16 +17,16 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.types; import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiType; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; +import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrTypeCastExpression; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrExpressionImpl; -import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; -import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; /** * @author ilyas @@ -47,7 +47,7 @@ public class GrTypeCastExpressionImpl extends GrExpressionImpl implements GrType public PsiType getType() { GrTypeElement typeElement = getCastTypeElement(); - if (typeElement != null) return typeElement.getType(); + if (typeElement != null) return TypesUtil.boxPrimitiveType(typeElement.getType(), getManager(), getResolveScope()); return null; } From 1314259c5361431053545440e2ca4c0a683d1b3b Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 10 Aug 2010 21:18:10 +0400 Subject: [PATCH 03/36] moved to community, dropped obsolete tests --- .../testData/psi/cls/1/TestClass.class | Bin 0 -> 384 bytes .../testData/psi/cls/2/TestClass.class | Bin 0 -> 365 bytes .../testData/psi/gt-tokens/test1.txt | 14 + .../testData/psi/gt-tokens/test2.txt | 10 + .../impl/bindToElementTest/ReplacingType.java | 5 + .../ReplacingType.java.after | 5 + .../bindToElementTest/SingleClassImport.java | 5 + .../SingleClassImport.java.after | 5 + .../psi/impl/bindToElementTest/prj/p1/A.java | 4 + .../psi/impl/bindToElementTest/prj/p2/A.java | 4 + .../psi/impl/extendsBoundList/addBound.java | 2 + .../impl/extendsBoundList/addBoundInEnd.java | 2 + .../extendsBoundList/addBoundInEnd_after.java | 2 + .../extendsBoundList/addBoundInFront.java | 2 + .../addBoundInFront_after.java | 2 + .../extendsBoundList/addBoundInTheMiddle.java | 2 + .../addBoundInTheMiddle_after.java | 2 + .../impl/extendsBoundList/addBound_after.java | 2 + .../extendsBoundList/removeBoundFromEnd.java | 2 + .../removeBoundFromEnd_after.java | 2 + .../removeBoundFromFront.java | 2 + .../removeBoundFromFront_after.java | 2 + .../removeBoundFromMiddle.java | 2 + .../removeBoundFromMiddle_after.java | 2 + .../psi/optimizeImports/EmptyImportInJsp.jsp | 1 + .../EmptyImportInJsp_after.jsp | 1 + .../psi/optimizeImports/EmptyImportList.java | 5 + .../EmptyImportList_after.java | 2 + .../psi/optimizeImports/IDEADEV10716.java | 9 + .../optimizeImports/IDEADEV10716_after.java | 9 + ...wImportListIsEmptyAndCommentPreserved.java | 6 + ...tListIsEmptyAndCommentPreserved_after.java | 4 + ...ptyAndJavaDocWithInvalidCodePreserved.java | 8 + ...JavaDocWithInvalidCodePreserved_after.java | 6 + .../psi/optimizeImports/SCR18364.java | 8 + .../psi/optimizeImports/SCR18364_after.java | 8 + .../testData/psi/optimizeImports/SCR6138.java | 8 + .../psi/optimizeImports/SCR6138_after.java | 8 + .../psi/optimizeImports/StaticImports1.java | 8 + .../optimizeImports/StaticImports1_after.java | 7 + .../StaticImportsToOptimize.java | 11 + .../StaticImportsToOptimize2.java | 9 + .../StaticImportsToOptimize2_after.java | 7 + .../StaticImportsToOptimize_after.java | 7 + .../optimizeImports/UnresolvedImports.java | 11 + .../optimizeImports/UnresolvedImports2.java | 12 + .../UnresolvedImports2_after.java | 10 + .../UnresolvedImports_after.java | 5 + .../psi/optimizeImports/UsageInCustomTag.jsp | 4 + .../UsageInCustomTag_after.jsp | 4 + .../testData/psi/repositoryUse/cls/cls.ipr | 113 + .../psi/repositoryUse/cls/cls_old.ipr | 109 + .../repositoryUse/cls/java/lang/Boolean.class | Bin 0 -> 607 bytes .../repositoryUse/cls/java/lang/Byte.class | Bin 0 -> 1345 bytes .../cls/java/lang/Character$Subset.class | Bin 0 -> 330 bytes .../java/lang/Character$UnicodeBlock.class | Bin 0 -> 2563 bytes .../cls/java/lang/Character.class | Bin 0 -> 4028 bytes .../repositoryUse/cls/java/lang/Class.class | Bin 0 -> 2374 bytes .../cls/java/lang/ClassLoader.class | Bin 0 -> 1856 bytes .../cls/java/lang/Comparable.class | Bin 0 -> 235 bytes .../repositoryUse/cls/java/lang/Double.class | Bin 0 -> 1554 bytes .../repositoryUse/cls/java/lang/Enum.class | Bin 0 -> 1173 bytes .../repositoryUse/cls/java/lang/Float.class | Bin 0 -> 1487 bytes .../repositoryUse/cls/java/lang/Integer.class | Bin 0 -> 1573 bytes .../cls/java/lang/Iterable.class | Bin 0 -> 264 bytes .../repositoryUse/cls/java/lang/Long.class | Bin 0 -> 1586 bytes .../repositoryUse/cls/java/lang/Object.class | Bin 0 -> 560 bytes .../repositoryUse/cls/java/lang/Short.class | Bin 0 -> 1355 bytes .../cls/java/lang/SimpleIterator.class | Bin 0 -> 260 bytes .../repositoryUse/cls/java/lang/String.class | Bin 0 -> 2732 bytes .../cls/java/lang/ThreadLocal.class | Bin 0 -> 338 bytes .../repositoryUse/cls/java/lang/Void.class | Bin 0 -> 215 bytes .../cls/java/lang/ref/PhantomReference.class | Bin 0 -> 385 bytes .../cls/java/lang/ref/Reference.class | Bin 0 -> 468 bytes .../cls/java/lang/ref/ReferenceQueue.class | Bin 0 -> 516 bytes .../cls/java/lang/ref/SoftReference.class | Bin 0 -> 428 bytes .../cls/java/lang/ref/WeakReference.class | Bin 0 -> 375 bytes .../java/lang/reflect/AccessibleObject.class | Bin 0 -> 332 bytes .../cls/java/lang/reflect/Array.class | Bin 0 -> 1640 bytes .../cls/java/lang/reflect/Constructor.class | Bin 0 -> 1037 bytes .../cls/java/lang/reflect/Field.class | Bin 0 -> 1539 bytes .../java/lang/reflect/InvocationHandler.class | Bin 0 -> 284 bytes .../reflect/InvocationTargetException.class | Bin 0 -> 337 bytes .../cls/java/lang/reflect/Member.class | Bin 0 -> 313 bytes .../cls/java/lang/reflect/Method.class | Bin 0 -> 807 bytes .../cls/java/lang/reflect/Modifier.class | Bin 0 -> 834 bytes .../cls/java/lang/reflect/Proxy.class | Bin 0 -> 698 bytes .../java/lang/reflect/ReflectPermission.class | Bin 0 -> 237 bytes .../UndeclaredThrowableException.class | Bin 0 -> 340 bytes .../cls/java/text/MessageFormat$Field.class | Bin 0 -> 425 bytes .../cls/java/text/MessageFormat.class | Bin 0 -> 1457 bytes .../cls/java/util/AbstractCollection.class | Bin 0 -> 1103 bytes .../cls/java/util/AbstractList.class | Bin 0 -> 1348 bytes .../cls/java/util/AbstractMap.class | Bin 0 -> 1106 bytes .../java/util/AbstractSequentialList.class | Bin 0 -> 718 bytes .../cls/java/util/AbstractSet.class | Bin 0 -> 422 bytes .../cls/java/util/ArrayList.class | Bin 0 -> 1329 bytes .../repositoryUse/cls/java/util/Arrays.class | Bin 0 -> 1993 bytes .../cls/java/util/Collection.class | Bin 0 -> 841 bytes .../cls/java/util/Collections.class | Bin 0 -> 4895 bytes .../cls/java/util/Comparator.class | Bin 0 -> 295 bytes .../cls/java/util/Dictionary.class | Bin 0 -> 627 bytes .../cls/java/util/Enumeration.class | Bin 0 -> 269 bytes .../repositoryUse/cls/java/util/HashMap.class | Bin 0 -> 1163 bytes .../repositoryUse/cls/java/util/HashSet.class | Bin 0 -> 744 bytes .../cls/java/util/Hashtable.class | Bin 0 -> 1408 bytes .../cls/java/util/IdentityHashMap.class | Bin 0 -> 1154 bytes .../cls/java/util/Iterator.class | Bin 0 -> 334 bytes .../cls/java/util/LinkedHashMap.class | Bin 0 -> 643 bytes .../cls/java/util/LinkedHashSet.class | Bin 0 -> 457 bytes .../cls/java/util/LinkedList.class | Bin 0 -> 1485 bytes .../repositoryUse/cls/java/util/List.class | Bin 0 -> 1425 bytes .../cls/java/util/ListIterator.class | Bin 0 -> 506 bytes .../cls/java/util/Map$Entry.class | Bin 0 -> 480 bytes .../psi/repositoryUse/cls/java/util/Map.class | Bin 0 -> 947 bytes .../psi/repositoryUse/cls/java/util/Set.class | Bin 0 -> 829 bytes .../cls/java/util/SortedMap.class | Bin 0 -> 669 bytes .../cls/java/util/SortedSet.class | Bin 0 -> 634 bytes .../repositoryUse/cls/java/util/Stack.class | Bin 0 -> 406 bytes .../repositoryUse/cls/java/util/TreeMap.class | Bin 0 -> 1642 bytes .../repositoryUse/cls/java/util/TreeSet.class | Bin 0 -> 1439 bytes .../repositoryUse/cls/java/util/Vector.class | Bin 0 -> 2551 bytes .../cls/java/util/WeakHashMap.class | Bin 0 -> 989 bytes .../cls/java/util/jar/JarFile.class | Bin 0 -> 785 bytes .../cls/java/util/logging/LogManager.class | Bin 0 -> 790 bytes .../repositoryUse/cls/pack/Annotated.class | Bin 0 -> 525 bytes .../repositoryUse/cls/pack/Annotation.class | Bin 0 -> 232 bytes .../cls/pack/MyClass$Inner.class | Bin 0 -> 335 bytes .../psi/repositoryUse/cls/pack/MyClass.class | Bin 0 -> 955 bytes .../psi/repositoryUse/cls/pack/MyEnum.class | Bin 0 -> 1267 bytes .../repositoryUse/cls/pack/Parametrized.class | Bin 0 -> 344 bytes .../psi/repositoryUse/cls/pack/Variance.class | Bin 0 -> 753 bytes .../repositoryUse/cls/src/pack/MyClass.java | 23 + .../cls/src/pack/Parametrized.java | 7 + .../repositoryUse/cls/src/pack/Variance.java | 12 + .../cls/sun/reflect/LangReflectAccess.class | Bin 0 -> 1429 bytes .../sun/security/util/SecurityConstants.class | Bin 0 -> 1757 bytes .../ClassWithGenericParameters.java | 6 + .../innerClassesScanner/NewInsideNew.java | 6 + .../scr17094/classes/a/a/a/a/e/f/i.class | Bin 0 -> 761 bytes .../classes1/com/intellij/util/d/bw.class | Bin 0 -> 7667 bytes .../com/intellij/internal/a/b/a/i.class | Bin 0 -> 1675 bytes .../psi/repositoryUse/src/MyClass1.java | 21 + .../psi/repositoryUse/src/StressClass.java | 2789 +++++++++++++++++ .../src/pack/AssertParentId.java | 10 + .../psi/repositoryUse/src/pack/MyClass2.java | 29 + .../repositoryUse/src/pack/MyInterface1.java | 6 + .../src15/annotated/AnnotatedClass.java | 9 + .../src15/annotated/package-info.java | 4 + .../src15/annotations/AnnotationType.java | 3 + .../annotations/DeprecatedAnnotation.java | 5 + .../src15/enumImplements/MyEnum.java | 5 + .../src15/enums/OurBaseInterface.java | 4 + .../repositoryUse/src15/enums/OurEnum.java | 4 + .../src15/enums/OurEnumWithConstants.java | 5 + .../OurEnumWithConstantsAndStaticFields.java | 7 + .../OurEnumWithConstantsAndStaticFields2.java | 39 + .../OurEnumWithInitializedConstants.java | 12 + .../src15/staticImports/StaticImports.java | 20 + .../psi/shortenClassRefs/SCR22368.java | 5 + .../psi/shortenClassRefs/SCR22368_after.java | 7 + .../psi/shortenClassRefs/SCR37254.java | 18 + .../psi/shortenClassRefs/SCR37254_after.java | 18 + .../types/assignableSubinheritor/empty.txt | 0 .../testData/psi/types/boundedParams/A.java | 7 + .../psi/types/complexInheritance/A.java | 9 + .../psi/types/listListInheritance/A.java | 15 + .../psi/types/methodTypeParameter/A.java | 10 + .../testData/psi/types/rawArrayTypes/A.java | 9 + .../psi/types/rawTypeExtension/A.java | 7 + .../psi/types/rawTypeInMethodArg/A.java | 9 + .../testData/psi/types/rawTypes/A.java | 9 + .../psi/types/simpleRawTypeInMethodArg/A.java | 9 + .../testData/psi/types/simpleStuff/A.java | 9 + .../psi/types/spaceInTypeParameterList/A.java | 7 + .../types/src/test/AbstractCollection.java | 2 + .../psi/types/src/test/Collection.java | 9 + .../psi/types/src/test/CollectionUtil.java | 6 + .../testData/psi/types/src/test/IntList.java | 5 + .../psi/types/src/test/IntListList.java | 4 + .../testData/psi/types/src/test/Iterator.java | 5 + .../testData/psi/types/src/test/List.java | 23 + .../testData/psi/types/src/test/ListList.java | 4 + .../testData/psi/types/src/test/SubList.java | 4 + .../psi/types/substWithInheritor/A.java | 9 + .../psi/types/typesInGenericClass/A.java | 9 + .../wildcardTypesAssignable/usages/Base.java | 4 + .../usages/Intermediate.java | 4 + .../wildcardTypesAssignable/usages/Leaf.java | 4 + .../roots/impl/ProjectLibrariesTest.java | 104 + .../intellij/psi/ClsRepositoryUseTest.java | 666 ++++ .../com/intellij/psi/GenericsTestCase.java | 39 + .../com/intellij/psi/OptimizeImportsTest.java | 75 + .../psi/PsiConcurrencyStressTest.java | 186 ++ .../com/intellij/psi/SCR17094Test.java | 59 + .../intellij/psi/Src15RepositoryUseTest.java | 332 ++ .../intellij/psi/SrcRepositoryUseTest.java | 829 +++++ .../testSrc/com/intellij/psi/TypesTest.java | 436 +++ .../cache/impl/InnerClassesScannerTest.java | 118 + .../psi/impl/cache/impl/SCR17650Test.java | 71 + .../psi/impl/source/parsing/GTTokensTest.java | 40 + .../source/tree/java/BindToElementTest.java | 87 + .../tree/java/BindToGenericClassTest.java | 53 + .../tree/java/ExtendsBoundListTest.java | 90 + .../tree/java/JavadocParamTagsTest.java | 185 ++ .../tree/java/ReferenceParameterListTest.java | 68 + .../tree/java/ShortenClassReferencesTest.java | 79 + 207 files changed, 7263 insertions(+) create mode 100644 java/java-tests/testData/psi/cls/1/TestClass.class create mode 100644 java/java-tests/testData/psi/cls/2/TestClass.class create mode 100644 java/java-tests/testData/psi/gt-tokens/test1.txt create mode 100644 java/java-tests/testData/psi/gt-tokens/test2.txt create mode 100644 java/java-tests/testData/psi/impl/bindToElementTest/ReplacingType.java create mode 100644 java/java-tests/testData/psi/impl/bindToElementTest/ReplacingType.java.after create mode 100644 java/java-tests/testData/psi/impl/bindToElementTest/SingleClassImport.java create mode 100644 java/java-tests/testData/psi/impl/bindToElementTest/SingleClassImport.java.after create mode 100644 java/java-tests/testData/psi/impl/bindToElementTest/prj/p1/A.java create mode 100644 java/java-tests/testData/psi/impl/bindToElementTest/prj/p2/A.java create mode 100644 java/java-tests/testData/psi/impl/extendsBoundList/addBound.java create mode 100644 java/java-tests/testData/psi/impl/extendsBoundList/addBoundInEnd.java create mode 100644 java/java-tests/testData/psi/impl/extendsBoundList/addBoundInEnd_after.java create mode 100644 java/java-tests/testData/psi/impl/extendsBoundList/addBoundInFront.java create mode 100644 java/java-tests/testData/psi/impl/extendsBoundList/addBoundInFront_after.java create mode 100644 java/java-tests/testData/psi/impl/extendsBoundList/addBoundInTheMiddle.java create mode 100644 java/java-tests/testData/psi/impl/extendsBoundList/addBoundInTheMiddle_after.java create mode 100644 java/java-tests/testData/psi/impl/extendsBoundList/addBound_after.java create mode 100644 java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromEnd.java create mode 100644 java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromEnd_after.java create mode 100644 java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromFront.java create mode 100644 java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromFront_after.java create mode 100644 java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromMiddle.java create mode 100644 java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromMiddle_after.java create mode 100644 java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp.jsp create mode 100644 java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp_after.jsp create mode 100644 java/java-tests/testData/psi/optimizeImports/EmptyImportList.java create mode 100644 java/java-tests/testData/psi/optimizeImports/EmptyImportList_after.java create mode 100644 java/java-tests/testData/psi/optimizeImports/IDEADEV10716.java create mode 100644 java/java-tests/testData/psi/optimizeImports/IDEADEV10716_after.java create mode 100644 java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndCommentPreserved.java create mode 100644 java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndCommentPreserved_after.java create mode 100644 java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndJavaDocWithInvalidCodePreserved.java create mode 100644 java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndJavaDocWithInvalidCodePreserved_after.java create mode 100644 java/java-tests/testData/psi/optimizeImports/SCR18364.java create mode 100644 java/java-tests/testData/psi/optimizeImports/SCR18364_after.java create mode 100644 java/java-tests/testData/psi/optimizeImports/SCR6138.java create mode 100644 java/java-tests/testData/psi/optimizeImports/SCR6138_after.java create mode 100644 java/java-tests/testData/psi/optimizeImports/StaticImports1.java create mode 100644 java/java-tests/testData/psi/optimizeImports/StaticImports1_after.java create mode 100644 java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize.java create mode 100644 java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize2.java create mode 100644 java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize2_after.java create mode 100644 java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize_after.java create mode 100644 java/java-tests/testData/psi/optimizeImports/UnresolvedImports.java create mode 100644 java/java-tests/testData/psi/optimizeImports/UnresolvedImports2.java create mode 100644 java/java-tests/testData/psi/optimizeImports/UnresolvedImports2_after.java create mode 100644 java/java-tests/testData/psi/optimizeImports/UnresolvedImports_after.java create mode 100644 java/java-tests/testData/psi/optimizeImports/UsageInCustomTag.jsp create mode 100644 java/java-tests/testData/psi/optimizeImports/UsageInCustomTag_after.jsp create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/cls.ipr create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/cls_old.ipr create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Boolean.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Byte.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Character$Subset.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Character$UnicodeBlock.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Character.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Class.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/ClassLoader.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Comparable.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Double.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Enum.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Float.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Integer.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Iterable.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Long.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Object.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Short.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/SimpleIterator.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/String.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/ThreadLocal.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/Void.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/PhantomReference.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/Reference.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/ReferenceQueue.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/SoftReference.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/WeakReference.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/AccessibleObject.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Array.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Constructor.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Field.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/InvocationHandler.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/InvocationTargetException.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Member.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Method.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Modifier.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Proxy.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/ReflectPermission.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/UndeclaredThrowableException.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/text/MessageFormat$Field.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/text/MessageFormat.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/AbstractCollection.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/AbstractList.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/AbstractMap.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/AbstractSequentialList.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/AbstractSet.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/ArrayList.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/Arrays.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/Collection.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/Collections.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/Comparator.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/Dictionary.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/Enumeration.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/HashMap.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/HashSet.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/Hashtable.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/IdentityHashMap.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/Iterator.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/LinkedHashMap.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/LinkedHashSet.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/LinkedList.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/List.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/ListIterator.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/Map$Entry.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/Map.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/Set.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/SortedMap.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/SortedSet.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/Stack.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/TreeMap.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/TreeSet.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/Vector.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/WeakHashMap.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/jar/JarFile.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/java/util/logging/LogManager.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/pack/Annotated.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/pack/Annotation.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/pack/MyClass$Inner.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/pack/MyClass.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/pack/MyEnum.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/pack/Parametrized.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/pack/Variance.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/src/pack/MyClass.java create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/src/pack/Parametrized.java create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/src/pack/Variance.java create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/sun/reflect/LangReflectAccess.class create mode 100644 java/java-tests/testData/psi/repositoryUse/cls/sun/security/util/SecurityConstants.class create mode 100644 java/java-tests/testData/psi/repositoryUse/innerClassesScanner/ClassWithGenericParameters.java create mode 100644 java/java-tests/testData/psi/repositoryUse/innerClassesScanner/NewInsideNew.java create mode 100644 java/java-tests/testData/psi/repositoryUse/scr17094/classes/a/a/a/a/e/f/i.class create mode 100644 java/java-tests/testData/psi/repositoryUse/scr17094/classes1/com/intellij/util/d/bw.class create mode 100644 java/java-tests/testData/psi/repositoryUse/scr17094/classes2/com/intellij/internal/a/b/a/i.class create mode 100644 java/java-tests/testData/psi/repositoryUse/src/MyClass1.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src/StressClass.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src/pack/AssertParentId.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src/pack/MyClass2.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src/pack/MyInterface1.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src15/annotated/AnnotatedClass.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src15/annotated/package-info.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src15/annotations/AnnotationType.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src15/annotations/DeprecatedAnnotation.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src15/enumImplements/MyEnum.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src15/enums/OurBaseInterface.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnum.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithConstants.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithConstantsAndStaticFields.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithConstantsAndStaticFields2.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithInitializedConstants.java create mode 100644 java/java-tests/testData/psi/repositoryUse/src15/staticImports/StaticImports.java create mode 100644 java/java-tests/testData/psi/shortenClassRefs/SCR22368.java create mode 100644 java/java-tests/testData/psi/shortenClassRefs/SCR22368_after.java create mode 100644 java/java-tests/testData/psi/shortenClassRefs/SCR37254.java create mode 100644 java/java-tests/testData/psi/shortenClassRefs/SCR37254_after.java create mode 100644 java/java-tests/testData/psi/types/assignableSubinheritor/empty.txt create mode 100644 java/java-tests/testData/psi/types/boundedParams/A.java create mode 100644 java/java-tests/testData/psi/types/complexInheritance/A.java create mode 100644 java/java-tests/testData/psi/types/listListInheritance/A.java create mode 100644 java/java-tests/testData/psi/types/methodTypeParameter/A.java create mode 100644 java/java-tests/testData/psi/types/rawArrayTypes/A.java create mode 100644 java/java-tests/testData/psi/types/rawTypeExtension/A.java create mode 100644 java/java-tests/testData/psi/types/rawTypeInMethodArg/A.java create mode 100644 java/java-tests/testData/psi/types/rawTypes/A.java create mode 100644 java/java-tests/testData/psi/types/simpleRawTypeInMethodArg/A.java create mode 100644 java/java-tests/testData/psi/types/simpleStuff/A.java create mode 100644 java/java-tests/testData/psi/types/spaceInTypeParameterList/A.java create mode 100644 java/java-tests/testData/psi/types/src/test/AbstractCollection.java create mode 100644 java/java-tests/testData/psi/types/src/test/Collection.java create mode 100644 java/java-tests/testData/psi/types/src/test/CollectionUtil.java create mode 100644 java/java-tests/testData/psi/types/src/test/IntList.java create mode 100644 java/java-tests/testData/psi/types/src/test/IntListList.java create mode 100644 java/java-tests/testData/psi/types/src/test/Iterator.java create mode 100644 java/java-tests/testData/psi/types/src/test/List.java create mode 100644 java/java-tests/testData/psi/types/src/test/ListList.java create mode 100644 java/java-tests/testData/psi/types/src/test/SubList.java create mode 100644 java/java-tests/testData/psi/types/substWithInheritor/A.java create mode 100644 java/java-tests/testData/psi/types/typesInGenericClass/A.java create mode 100644 java/java-tests/testData/psi/types/wildcardTypesAssignable/usages/Base.java create mode 100644 java/java-tests/testData/psi/types/wildcardTypesAssignable/usages/Intermediate.java create mode 100644 java/java-tests/testData/psi/types/wildcardTypesAssignable/usages/Leaf.java create mode 100644 java/java-tests/testSrc/com/intellij/openapi/roots/impl/ProjectLibrariesTest.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/ClsRepositoryUseTest.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/GenericsTestCase.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/SCR17094Test.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/Src15RepositoryUseTest.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/SrcRepositoryUseTest.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/TypesTest.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/InnerClassesScannerTest.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/SCR17650Test.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/impl/source/parsing/GTTokensTest.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/BindToElementTest.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/BindToGenericClassTest.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ExtendsBoundListTest.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/JavadocParamTagsTest.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ReferenceParameterListTest.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ShortenClassReferencesTest.java diff --git a/java/java-tests/testData/psi/cls/1/TestClass.class b/java/java-tests/testData/psi/cls/1/TestClass.class new file mode 100644 index 0000000000000000000000000000000000000000..efe92eeb61b9283bc5297652b78fac100532bd46 GIT binary patch literal 384 zcmZ8c%TB{E5S;BRCA2gIet;Vfi6~sDxK!d4(L<}=oy4@RoLEX+{)-b52R?w0s#pgU zpqHK9@yzb{bN~JUAjY|mE>1m!9?l5fvywWGV?vm0#fylvDA&=#R;pazx6gNk!BmyX zJ`lQ>S1UqqW^zfGB&w88yCRjq3p-VMrMNa}$E!!1Ht~Gm8s!_;cXO3DM_{gE#0HUc&W= u*@%%C``2%v*T&#;9W&{<9H}+mG&6ID#^8^UTH}P}9Ry#so*tj9k#DH(z(0wL@d_$4I?#%>2, a > > 3, a >>> 4 +------------------------------ +PsiIdentifier:a +PsiJavaToken:GTGT +PsiJavaToken:INTEGER_LITERAL +PsiJavaToken:COMMA +PsiIdentifier:a +PsiJavaToken:GT +PsiJavaToken:GT +PsiJavaToken:INTEGER_LITERAL +PsiJavaToken:COMMA +PsiIdentifier:a +PsiJavaToken:GTGTGT +PsiJavaToken:INTEGER_LITERAL diff --git a/java/java-tests/testData/psi/gt-tokens/test2.txt b/java/java-tests/testData/psi/gt-tokens/test2.txt new file mode 100644 index 000000000000..20d81219e337 --- /dev/null +++ b/java/java-tests/testData/psi/gt-tokens/test2.txt @@ -0,0 +1,10 @@ +a >>>= b >>= 3 +------------------ +PsiIdentifier:a +PsiJavaToken:GTGTGTEQ +PsiIdentifier:b +PsiJavaToken:GT +PsiJavaToken:LT +PsiIdentifier:xyz +PsiJavaToken:GTGTEQ +PsiJavaToken:INTEGER_LITERAL diff --git a/java/java-tests/testData/psi/impl/bindToElementTest/ReplacingType.java b/java/java-tests/testData/psi/impl/bindToElementTest/ReplacingType.java new file mode 100644 index 000000000000..adb70cfdde86 --- /dev/null +++ b/java/java-tests/testData/psi/impl/bindToElementTest/ReplacingType.java @@ -0,0 +1,5 @@ +import p1.A; + +class C { + I i = null; +} diff --git a/java/java-tests/testData/psi/impl/bindToElementTest/ReplacingType.java.after b/java/java-tests/testData/psi/impl/bindToElementTest/ReplacingType.java.after new file mode 100644 index 000000000000..98b8f45ada59 --- /dev/null +++ b/java/java-tests/testData/psi/impl/bindToElementTest/ReplacingType.java.after @@ -0,0 +1,5 @@ +import p1.A; + +class C { + p2.A i = null; +} diff --git a/java/java-tests/testData/psi/impl/bindToElementTest/SingleClassImport.java b/java/java-tests/testData/psi/impl/bindToElementTest/SingleClassImport.java new file mode 100644 index 000000000000..adb70cfdde86 --- /dev/null +++ b/java/java-tests/testData/psi/impl/bindToElementTest/SingleClassImport.java @@ -0,0 +1,5 @@ +import p1.A; + +class C { + I i = null; +} diff --git a/java/java-tests/testData/psi/impl/bindToElementTest/SingleClassImport.java.after b/java/java-tests/testData/psi/impl/bindToElementTest/SingleClassImport.java.after new file mode 100644 index 000000000000..98b8f45ada59 --- /dev/null +++ b/java/java-tests/testData/psi/impl/bindToElementTest/SingleClassImport.java.after @@ -0,0 +1,5 @@ +import p1.A; + +class C { + p2.A i = null; +} diff --git a/java/java-tests/testData/psi/impl/bindToElementTest/prj/p1/A.java b/java/java-tests/testData/psi/impl/bindToElementTest/prj/p1/A.java new file mode 100644 index 000000000000..5ec3bffd2be3 --- /dev/null +++ b/java/java-tests/testData/psi/impl/bindToElementTest/prj/p1/A.java @@ -0,0 +1,4 @@ +package p1; + +class A { +} diff --git a/java/java-tests/testData/psi/impl/bindToElementTest/prj/p2/A.java b/java/java-tests/testData/psi/impl/bindToElementTest/prj/p2/A.java new file mode 100644 index 000000000000..ba9dcda09ee9 --- /dev/null +++ b/java/java-tests/testData/psi/impl/bindToElementTest/prj/p2/A.java @@ -0,0 +1,4 @@ +package p2; + +class A { +} diff --git a/java/java-tests/testData/psi/impl/extendsBoundList/addBound.java b/java/java-tests/testData/psi/impl/extendsBoundList/addBound.java new file mode 100644 index 000000000000..a653e3caf546 --- /dev/null +++ b/java/java-tests/testData/psi/impl/extendsBoundList/addBound.java @@ -0,0 +1,2 @@ +class X { +} diff --git a/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInEnd.java b/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInEnd.java new file mode 100644 index 000000000000..c648f0112189 --- /dev/null +++ b/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInEnd.java @@ -0,0 +1,2 @@ +class X { +} diff --git a/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInEnd_after.java b/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInEnd_after.java new file mode 100644 index 000000000000..037433b14cd3 --- /dev/null +++ b/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInEnd_after.java @@ -0,0 +1,2 @@ +class X { +} diff --git a/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInFront.java b/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInFront.java new file mode 100644 index 000000000000..c648f0112189 --- /dev/null +++ b/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInFront.java @@ -0,0 +1,2 @@ +class X { +} diff --git a/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInFront_after.java b/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInFront_after.java new file mode 100644 index 000000000000..a96ff676fa23 --- /dev/null +++ b/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInFront_after.java @@ -0,0 +1,2 @@ +class X { +} diff --git a/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInTheMiddle.java b/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInTheMiddle.java new file mode 100644 index 000000000000..c648f0112189 --- /dev/null +++ b/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInTheMiddle.java @@ -0,0 +1,2 @@ +class X { +} diff --git a/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInTheMiddle_after.java b/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInTheMiddle_after.java new file mode 100644 index 000000000000..068eba289751 --- /dev/null +++ b/java/java-tests/testData/psi/impl/extendsBoundList/addBoundInTheMiddle_after.java @@ -0,0 +1,2 @@ +class X { +} diff --git a/java/java-tests/testData/psi/impl/extendsBoundList/addBound_after.java b/java/java-tests/testData/psi/impl/extendsBoundList/addBound_after.java new file mode 100644 index 000000000000..9a6175390de3 --- /dev/null +++ b/java/java-tests/testData/psi/impl/extendsBoundList/addBound_after.java @@ -0,0 +1,2 @@ +class X { +} diff --git a/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromEnd.java b/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromEnd.java new file mode 100644 index 000000000000..ab9aafabfd1e --- /dev/null +++ b/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromEnd.java @@ -0,0 +1,2 @@ +public class X { +} diff --git a/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromEnd_after.java b/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromEnd_after.java new file mode 100644 index 000000000000..427564cb13f1 --- /dev/null +++ b/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromEnd_after.java @@ -0,0 +1,2 @@ +public class X { +} diff --git a/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromFront.java b/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromFront.java new file mode 100644 index 000000000000..ab9aafabfd1e --- /dev/null +++ b/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromFront.java @@ -0,0 +1,2 @@ +public class X { +} diff --git a/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromFront_after.java b/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromFront_after.java new file mode 100644 index 000000000000..34963a2e36db --- /dev/null +++ b/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromFront_after.java @@ -0,0 +1,2 @@ +public class X { +} diff --git a/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromMiddle.java b/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromMiddle.java new file mode 100644 index 000000000000..3a6ce9352341 --- /dev/null +++ b/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromMiddle.java @@ -0,0 +1,2 @@ +public class X { +} diff --git a/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromMiddle_after.java b/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromMiddle_after.java new file mode 100644 index 000000000000..ab9aafabfd1e --- /dev/null +++ b/java/java-tests/testData/psi/impl/extendsBoundList/removeBoundFromMiddle_after.java @@ -0,0 +1,2 @@ +public class X { +} diff --git a/java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp.jsp b/java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp.jsp new file mode 100644 index 000000000000..9062b95b1832 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp.jsp @@ -0,0 +1 @@ +<%@ page autoFlush="true" import="java.util.List" %> diff --git a/java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp_after.jsp b/java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp_after.jsp new file mode 100644 index 000000000000..1edc87122114 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp_after.jsp @@ -0,0 +1 @@ +<%@ page autoFlush="true" %> diff --git a/java/java-tests/testData/psi/optimizeImports/EmptyImportList.java b/java/java-tests/testData/psi/optimizeImports/EmptyImportList.java new file mode 100644 index 000000000000..5d2e47d04293 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/EmptyImportList.java @@ -0,0 +1,5 @@ +import java.util.List; +import java.util.ArrayList; + +class A { +} diff --git a/java/java-tests/testData/psi/optimizeImports/EmptyImportList_after.java b/java/java-tests/testData/psi/optimizeImports/EmptyImportList_after.java new file mode 100644 index 000000000000..2e2439c32d01 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/EmptyImportList_after.java @@ -0,0 +1,2 @@ +class A { +} diff --git a/java/java-tests/testData/psi/optimizeImports/IDEADEV10716.java b/java/java-tests/testData/psi/optimizeImports/IDEADEV10716.java new file mode 100644 index 000000000000..baf6e40ff92f --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/IDEADEV10716.java @@ -0,0 +1,9 @@ +import IdeaBug.Anno; + +class IdeaBug { + @interface Anno { } +} + +@Anno +public class IdeaBugUser extends IdeaBug { +} diff --git a/java/java-tests/testData/psi/optimizeImports/IDEADEV10716_after.java b/java/java-tests/testData/psi/optimizeImports/IDEADEV10716_after.java new file mode 100644 index 000000000000..baf6e40ff92f --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/IDEADEV10716_after.java @@ -0,0 +1,9 @@ +import IdeaBug.Anno; + +class IdeaBug { + @interface Anno { } +} + +@Anno +public class IdeaBugUser extends IdeaBug { +} diff --git a/java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndCommentPreserved.java b/java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndCommentPreserved.java new file mode 100644 index 000000000000..fbf0eb888a32 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndCommentPreserved.java @@ -0,0 +1,6 @@ +import java.util.List; +// This is a comment +import java.util.ArrayList; + +public class Test { +} diff --git a/java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndCommentPreserved_after.java b/java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndCommentPreserved_after.java new file mode 100644 index 000000000000..5d7dab500043 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndCommentPreserved_after.java @@ -0,0 +1,4 @@ +// This is a comment + +public class Test { +} diff --git a/java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndJavaDocWithInvalidCodePreserved.java b/java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndJavaDocWithInvalidCodePreserved.java new file mode 100644 index 000000000000..5b56eefb5a69 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndJavaDocWithInvalidCodePreserved.java @@ -0,0 +1,8 @@ +import java.util.List; + +/** + * @deprecated + */ +/ +public class Foo { +} diff --git a/java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndJavaDocWithInvalidCodePreserved_after.java b/java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndJavaDocWithInvalidCodePreserved_after.java new file mode 100644 index 000000000000..05484534465e --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/NewImportListIsEmptyAndJavaDocWithInvalidCodePreserved_after.java @@ -0,0 +1,6 @@ +/** + * @deprecated + */ +/ +public class Foo { +} diff --git a/java/java-tests/testData/psi/optimizeImports/SCR18364.java b/java/java-tests/testData/psi/optimizeImports/SCR18364.java new file mode 100644 index 000000000000..29dd658c0cf5 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/SCR18364.java @@ -0,0 +1,8 @@ +import java.util.List; + +class A { + B create; +} + +interface B { +} diff --git a/java/java-tests/testData/psi/optimizeImports/SCR18364_after.java b/java/java-tests/testData/psi/optimizeImports/SCR18364_after.java new file mode 100644 index 000000000000..29dd658c0cf5 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/SCR18364_after.java @@ -0,0 +1,8 @@ +import java.util.List; + +class A { + B create; +} + +interface B { +} diff --git a/java/java-tests/testData/psi/optimizeImports/SCR6138.java b/java/java-tests/testData/psi/optimizeImports/SCR6138.java new file mode 100644 index 000000000000..ab919b6cff27 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/SCR6138.java @@ -0,0 +1,8 @@ +import javax.swing.*; + +class Foo{ + { + JComponent component; + component.new AccessibleJComponent(); + } +} diff --git a/java/java-tests/testData/psi/optimizeImports/SCR6138_after.java b/java/java-tests/testData/psi/optimizeImports/SCR6138_after.java new file mode 100644 index 000000000000..ab919b6cff27 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/SCR6138_after.java @@ -0,0 +1,8 @@ +import javax.swing.*; + +class Foo{ + { + JComponent component; + component.new AccessibleJComponent(); + } +} diff --git a/java/java-tests/testData/psi/optimizeImports/StaticImports1.java b/java/java-tests/testData/psi/optimizeImports/StaticImports1.java new file mode 100644 index 000000000000..2d394eae01c9 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/StaticImports1.java @@ -0,0 +1,8 @@ +import java.util.List; +import static java.util.Arrays.sort; + +class Foo { + { + sort(new Integer[0]); + } +} diff --git a/java/java-tests/testData/psi/optimizeImports/StaticImports1_after.java b/java/java-tests/testData/psi/optimizeImports/StaticImports1_after.java new file mode 100644 index 000000000000..5ddfe61e6325 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/StaticImports1_after.java @@ -0,0 +1,7 @@ +import static java.util.Arrays.sort; + +class Foo { + { + sort(new Integer[0]); + } +} diff --git a/java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize.java b/java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize.java new file mode 100644 index 000000000000..0f17b4c530b6 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize.java @@ -0,0 +1,11 @@ +import java.util.List; +import static java.util.Arrays.sort; +import static java.util.Arrays.asList; +import static java.util.Arrays.invalid; +import static invalid.*; + +class Foo { + { + sort(new Integer[0]); + } +} diff --git a/java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize2.java b/java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize2.java new file mode 100644 index 000000000000..a54d90724e98 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize2.java @@ -0,0 +1,9 @@ +import java.util.List; +import static java.util.Arrays.sort; +import static invalid.*; + +class Foo { + { + sort(new long[0]); + } +} diff --git a/java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize2_after.java b/java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize2_after.java new file mode 100644 index 000000000000..105a37daa58e --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize2_after.java @@ -0,0 +1,7 @@ +import static java.util.Arrays.sort; + +class Foo { + { + sort(new long[0]); + } +} diff --git a/java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize_after.java b/java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize_after.java new file mode 100644 index 000000000000..5ddfe61e6325 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/StaticImportsToOptimize_after.java @@ -0,0 +1,7 @@ +import static java.util.Arrays.sort; + +class Foo { + { + sort(new Integer[0]); + } +} diff --git a/java/java-tests/testData/psi/optimizeImports/UnresolvedImports.java b/java/java-tests/testData/psi/optimizeImports/UnresolvedImports.java new file mode 100644 index 000000000000..321ed9760e22 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/UnresolvedImports.java @@ -0,0 +1,11 @@ +import xxxx.ddd; +import com.XXX; +import yyy.com.*; +import static zzz.yyy.com.AAA.*; +import static zzz.yyy.com.BBB; + +class Foo { + { + + } +} diff --git a/java/java-tests/testData/psi/optimizeImports/UnresolvedImports2.java b/java/java-tests/testData/psi/optimizeImports/UnresolvedImports2.java new file mode 100644 index 000000000000..effe7401d4c6 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/UnresolvedImports2.java @@ -0,0 +1,12 @@ +import xxxx.ddd; +import com.XXX; +import yyy.com.*; +import static zzz.yyy.com.AAA.*; +import static zzz.yyy.com.BBB; + +class Foo { + { + // maybe it's from yyy.com.* + ZZZ z = null; + } +} diff --git a/java/java-tests/testData/psi/optimizeImports/UnresolvedImports2_after.java b/java/java-tests/testData/psi/optimizeImports/UnresolvedImports2_after.java new file mode 100644 index 000000000000..0e98663d8f3b --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/UnresolvedImports2_after.java @@ -0,0 +1,10 @@ +import yyy.com.*; + +import static zzz.yyy.com.AAA.*; + +class Foo { + { + // maybe it's from yyy.com.* + ZZZ z = null; + } +} diff --git a/java/java-tests/testData/psi/optimizeImports/UnresolvedImports_after.java b/java/java-tests/testData/psi/optimizeImports/UnresolvedImports_after.java new file mode 100644 index 000000000000..aa0ccb8a41f3 --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/UnresolvedImports_after.java @@ -0,0 +1,5 @@ +class Foo { + { + + } +} diff --git a/java/java-tests/testData/psi/optimizeImports/UsageInCustomTag.jsp b/java/java-tests/testData/psi/optimizeImports/UsageInCustomTag.jsp new file mode 100644 index 000000000000..92dfb608cd5d --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/UsageInCustomTag.jsp @@ -0,0 +1,4 @@ + +<%@ page import="java.util.List" %> + + diff --git a/java/java-tests/testData/psi/optimizeImports/UsageInCustomTag_after.jsp b/java/java-tests/testData/psi/optimizeImports/UsageInCustomTag_after.jsp new file mode 100644 index 000000000000..92dfb608cd5d --- /dev/null +++ b/java/java-tests/testData/psi/optimizeImports/UsageInCustomTag_after.jsp @@ -0,0 +1,4 @@ + +<%@ page import="java.util.List" %> + + diff --git a/java/java-tests/testData/psi/repositoryUse/cls/cls.ipr b/java/java-tests/testData/psi/repositoryUse/cls/cls.ipr new file mode 100644 index 000000000000..ae1982b95664 --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/cls/cls.ipr @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/java-tests/testData/psi/repositoryUse/cls/cls_old.ipr b/java/java-tests/testData/psi/repositoryUse/cls/cls_old.ipr new file mode 100644 index 000000000000..b6b15b394dfc --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/cls/cls_old.ipr @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Boolean.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Boolean.class new file mode 100644 index 0000000000000000000000000000000000000000..05d27b08b8c31c2821c7d62a52ed0de0a1e86740 GIT binary patch literal 607 zcmZ`$%TB^T6g|VMyi|~f;(KS=h^{dvN+dBM!B`}b-GBp>Oj>OV3qQ?;AK*tB@3ak6 z#Wc<7J#*&Vb8kPt-ai1G<3z)uh9eEf42j;u<1Is}Gvf>1kldOyZfsi$ZZ#Q_?dy&~ zr-|OvJwY)dYDw<8BuQPGmg!xQMjzDs3>7^hGCaq$CQZfXU%2Cn(E1yH=U@>>!p3@xv`l%TU&%O_p?e%H3(pehzZo(d^=N z&ZYZnn(lBWMqX0|&rXE5964*)b7v&lrX+)WNS~>-(`Nr{pP{hg0!s?!Q>NW8gky4P zzVV?HxBx?p-Z(uqB#@+^Ttg~E4QZ-#be=($z7*yNGst7ZuQ##f*98b$>6szfV;R2j5VRjS2t& literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Byte.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Byte.class new file mode 100644 index 0000000000000000000000000000000000000000..2a30d250bbbce6b12f2b40ae10fa11cb7463a635 GIT binary patch literal 1345 zcmZ`&TT|0e5dKbEDJ}PlDBe&3Z9%zsmjX&F%-~dTrr1$moYOY6VM2mQ%D|KUAfJ8k z!SUH2C4T25(opI{&St;;cK18G$?rcuegarPK8cky1Xh!Hk;F@Z)SJz%Pvy1ZyLADP z7w9WEw&zRRFH5Uw#7|C6zADn%`+yW@l`jH`oeyuBFjU-=hjQMMc748JNzcoXTQcjm z^qa0BFxehojsW>%-^i^pquX~%zH8cbfs2`ZHbMztQj&*C&GxRq$XSLi!lnn(^$g{x z8s{ryd9(ETQPnu`P2MkwHG#1XyiG-%?ih#^4VzAN;6>Gkw62;_b!rsWwQSm^zsl+H z4(0y{C7!DA9(w!&@r;)4H5@nCh=xiWni;N01DnjU9J}7idd&;(T8@llZ3y(#oMy#} z6n`Z!nu&@&9eH;{dW}LL-1yv-me;0uyRv6g{ap4Vdsm%(Zot@a)PmY4m8H5fOZk^c zJP~vlD4Mph)!eTb?vA8Df#IT4l~!50rt(8D;Wtdm7;Nt#5Ib5>Ijzqz>_Kg%W7}^S zzFFl4@~&B{v-(nm8MMtskb=IA>f7;qO_!XeTQxRJr8A|rJg52!^tak8v=?)jr`i@8 zwBpEHP^*`~L<8;-j#{nPIji~Murd=fmzaRFU?Px6n9p__gx;-~5NpqKGJ9q-2| z;{zC^m%h6sEPkgS*;hkkxhoGuqCEynDE>ea;pb6rAw_r?E(Eg>#6}reFPw2RDmny^n literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Character$Subset.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Character$Subset.class new file mode 100644 index 0000000000000000000000000000000000000000..b4c03105cf6f343fe95e53b7df0ddfd8b9ee04f6 GIT binary patch literal 330 zcmZXQPiw+J5XIk^*2MT<>&084hvZUwSG)uYLZOF%hu+q>m`K>*?#2)2!4J?6Rh&jN z(6Y?FVfMY@$A15u&H&ypcF}V&Bs3S9%IuOb2|o7XC}z1(yIE{?rgrmi%?5cWMQ;8W zJ~w-r*m?Lx@KRyYsMtz^6ND=s*y5TeJO$zZtpq8zBJI?9DHk^u*G=!!=e*Q5I$JcH2SUjQEXI9$LGk7!ov!mG3e TpS6K@b$2je^*KrCqL0=E$pTI~ literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Character$UnicodeBlock.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Character$UnicodeBlock.class new file mode 100644 index 0000000000000000000000000000000000000000..7de10cebeed575020f9a0017fd0b4961fd3ab08e GIT binary patch literal 2563 zcmai#X;<7f6ozGzVTO)hE?K&_q-kYaV~dd`SC)b4rcTHtrRBgmK>FkQ zp+BHMs;93!m#vV~4>ON!U0+G>UG(=qfBwZ7d&FL}*)MIj5wXdbS2FR6JEI-v6<0JvF?OU zMe6zKS8>FqWXXMFQ%R$%h+VHro=Bbf!lbe*h4o4}CoHBG5>v!dhsjj(#7ZX7JHE#=NQjLY{eP|-10a~UP#3%*F57^MywqRopFUxC#!8y z_wvzj1=bG3ma(#r6SN#Jq=FYGRGroMu*bFLDW)b0u6Q56B4X!V&hgbb#SKiHjD-uE z=w!m!tl7_G&UIERzrqWc%>P%bG{xbJ=2&W~IoC)d=oqoNOlV-x~4mIhda1nC{lZ9lZcX0AX&J${Pa%qt|8gcLRxZ}uzFpN!U3eyb{rT8Lc zOXw0yC0(DQJr3)*M$B#~W^Fauv_Mt^~chd1{dpZWkN5k-`wLM5IvNP0k&p!NRDb z&X@}|fBC3rbFR7v)q3spnv_*@6$(i;&iyKilj|lNuU`aRWHGp2lc~!a^}4lEqbKs& zsY;PZ9@2iiLVMt-|8dl46Sa0FHNMAQ+eM#i6aykDTrLfA6T>7I*7Ssk*xduw6MTpk zq&<((7&3`MMXm(Zn}lqcEDvp=q+(R)XaxSSc;N8TK|UVq9!qCu&ruH!LA%(Obe<-Q zCh>T*^!Ss_?alqCsG@tvE{AG=cXRvY^8M9_jqSXER`-(o$EII z)b63#gK+J%8Q$IgzY7T4J$@hIQEqP!cayEb-rjI8VmHomP`!G#H{1{DK!dq6tk`3Q z)8Kln**rVP&SNysTEuZ;o7f>v5HAoXi5H1)5T}UK#2Mlx;w*8Fc$s*Gc$IjKc%3*; zyg^(b-Xty(-z455-X^|9Tq3?ryhFT8e24fh@gDI$@jc@E#1Duc5+4vB5+4yC6F(w; zO#FoSDe*Jn=fp3FUlP9}E)$;+za~B=H9#PL#wIVvneZ1yK_X zu_S&+w8V<&h&6GQxJF!WIEH-fv+t3q6YK}}BRIx>YW{y_&%jwcN6fPUGIFD literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Character.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Character.class new file mode 100644 index 0000000000000000000000000000000000000000..155067c1deecf9ed78ff450320e44c3a427dc238 GIT binary patch literal 4028 zcmai1X?xU060Y{aFt)*9Fkk|N<%$gnklkdDK-g$BvMrdA21#QuITU#;+k#C}nS9euc%b$Ms(Z@t|mOd!Z zKZi)rzY6s40{y2z|1HoxK_m56&SXAnxB6 zG~mqFV6d}t-Mj6bX?m^YGf52R1P#><#kTbsLo35WNzjgZt)^M3Vry*dD%bE5I8m*dTeOlKn=3xMvH=WrYZV)aE({SyYqUy$sTUD$}aTHk1np7HYDqUFo1e2)(C)IP>Q$xUmh~CkagBPllty2~X{LK&8##8Hpk2~v#!_mty%V+zDyXL6SY}1;XB26kHm$1SNVG%HaLv-^ z6i0LGwkD}DWZVAhU9l6iMFFyPJUnl zjzA1e#a8lzd*LiiNp6*Wh!DYIQ}fkQx`he&R}mr7GSBG!JlX5k4|LCVojV|C0;zL! zB8hYZIV-JhnKex@vdR)P`Nan7g(7I`|Cr+Pp()5J z+!%ZsPj}T5IajzSRotw!wE3F(_;LUERTA`I&Qr<6F)P-*YiM=HQYwOuOsWg=&CWmb2zWy$Gz-BNl;3Yps$C5?zg$L}5Oh4}sMpY((=1Cb zqc`Rq_GbSJ9QGP^9LmeObK~kYvxe@}En+wA3TO}KgH{kT-Zp)@`E}`Z@ z@V33;MP4KJBed>f10Z=F1ocl&p*Xj$cnW9GH7oQxapK-O1RJ0y@3#7#dnDFp3u zupG#z4w}CdwERT`05^V&4WW~CR5Qv9M}qc6yjUHBT^x3e##2^b^jmST6!?)Hdl6RI zo#$%_y$>O#Z}Ns2dp8+MCt;0sYkj#DM&3db+a8X?+#w(fAo(H0Av=V@#qSS)WnPMc#bxZeXa~zJFJ6nF*Eh~enIJr412jlqqX`GOfOpbZcYGJ{ zZidH!_t0LOEzABO%VhL1o$%J4Dh#~D5W{UL@Y zp-(Y<68b5IABO%2!>6I2VfZZcM;ZPy^sg}d81%;({wj2NmYw~79r`yIeggVAhR;KP zlHm)`zsc}Z&=rPD&{c-Z&^3mqq0cZp3teaUBJ@iPSD;rJHlUjf*Pvf!*n(~|>_D$G zEb~3bu*~-rhGo95GA#2w&#=t*HHKxrpJrI*`x%C1zMo}S=KDE@Wxid8Wxk(hSmxVf zSmt|yVVUm+!!qBC49k4`49k2kF}w_Yh2baY7-}P+>$oXJxTlRwDh%bEOPCV!O4AJb2g z^?sVkpJnnDdNtvHPQOUxFEjgJW%AdV{7oi*o7w%2exKO?f&Q4tKPBTrw!`G_pu6-M zI@0SHdlEgUPuiS3^$Cd&sqY>@AH9L!EjTcO*_-&?lN!-q=&wNXsNSNtG5$`1-c5e{ c={?9k`WyW{k^i8rkYiw^rvj2wgdC#c=RhbwVE_OC literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Class.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Class.class new file mode 100644 index 0000000000000000000000000000000000000000..b5d94add03bf6ec09421bcc4e3c1b4b0153688c9 GIT binary patch literal 2374 zcmb7FTYD2X5FK&bTqw6fD5YEq4cLWXT6&>4xP%0^p-D)yh6nm2b`>L7ul#9c+VrRO zp+BHMs$Y+!wO78-uYK@0^5~q=nbBzWufPBJlZfupi-@)(+KK2HqhqTwm!`$&aIOA= z(VS7S(K7EcI$Nu6z2Wb8Bjb6u;k`{p(Z13Kw`b$QqWU*Ehmi#IcZLNCtph=BQi(ItfjL`esszDXui@?^JAGqCJ zEql_)ci4@(!uZ;qz$(a-(S@;U2U}450l@K~FLYun%IL#stj!CkU7ozl@`*s@>H*{a*>e}aGuF|aB?z<{K(~Ur3}pnURWwrz(7B;_Mk`^5ln*9s;9-2l zSFf=bF$`Fy8_{z{uCuCS7~QM=w;(}oNbCOpXALWIW^~^o9o=!&1R@>YbqE~Y==qRc z<$;^CP3iln3=y`LNQY%y3SdD_csAJB6NMV+M64CKAHngg>ocleUYb;m&AdM_9*UwY z1`%v01syVe-MKK0=X+bA*h6=J>E+-@tqr0 zuRQ)B3=QX+2+Qbdg>>84TkftSP&(lZFUMTIyrM>9R!%U=0ZvQe}K@3!p zK6U@E(RF7(vwp-|rW?-Qq?)t!692iyfp?2;2P#*vzC(=(&s}8ib=%xlO4VOteUH8> zu{NWxvB&5e`Zn<0cfRlFK^ei~tj}lO1acKhs><0252rM>rZj#3UQLf?Xj+@0>G8j4 eTBi+HohQ_G_6PdW*-d*3$iSyYH6DsJ}^`={Abe{YFBVOWkjMGOHW<6doom_sY}=j+uRE> z>l~FL3jOnLjwRc*$=mdCTo={2h?Hn2#TdkNx?5}^5~|^~0wE)Ym9(EjtINAbr<9p- zJ<<|tpK^$0Q!p&rcKzcCgmS;`*J(DRmI=jLz1k*Lp6_l4aa%~P8&SeAHomzXG$rMJ!DJzeSh_V&Doju89=w9g7g0on4sFcZE%5Be2o^*R$ia-&soLZY? z%Na_SKFnx3IKx?|BZBqXqS_uNV8d|cW0_ja_-xr{%tVN zy=%#!wrb-fQ{>GE8TlLZbHY&eLOf z(1VPhFQM8A#KFh_r-V_AS)7~D$ao5w7(j}cq&Ou^ z_4{Kb!g5A4jTw{GEN+o3Vh;0`kK2^@9iwq@cR-V;>aBq$)LY w$w&vwSh1p%DM|&8iQ!-sPmFwuHIfT(>3^b@&+)>@mx+9ZPB&i@I)pd>03s9kDgXcg literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Comparable.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Comparable.class new file mode 100644 index 0000000000000000000000000000000000000000..18539eceb4c0831892dd5dd1710047a17b549850 GIT binary patch literal 235 zcmX^0Z`VEs1_lEL9(D#Ub_Q-n2F~RC+=9fS)R25e22l;4ti-ZJ{hY+SbbbG%tkmQZ zYfVp}n&8azyu^~yqEto(HjR)Fu%L!bh!v)CJ4_))2Cm@z(xT*4x6B-%0sPKj3lo!a zQuRQ#F*1lCEJesMG6*1qA#Pz~WME`q0y>|8fsuugfti5?$Y%xem>AfA7{X#_-~fwo F0sxr-ImQ40 literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Double.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Double.class new file mode 100644 index 0000000000000000000000000000000000000000..9e1ecbed60bb231eaa30b275984ab0371cfa0f8c GIT binary patch literal 1554 zcmZ`(OIOoC6uwhRA0S#DqTmA+(H4}4Z!Msu4-A$RY3UI+oS}p^oRDCWBCPmBu3fnB zxc1NJ(v|wnB+wMJ=QKCp{l5E{J2UzI`^#4%nx?fVt#lEiw^3S+QkhZjN~x?=lxluM zQ45NyRMr`>9HXABWjZc5-6}VlTIA>_!tq0ZnqSPc1w{UwkR2*lBS*iEwejW5yNzn5 zxR#F`{rDq)jN;3R>N`ChF-GCa`br+ji#vRuPZ`{-Ph}16IBDq1dfnu1)7BV`o#tl) zj-1upG_>?QVq&gUc5U6PGrE|}r2-<)4M}ugEUdK6=uYx19}MyHGV017)U-WU$7G^Z zIg|QC*S*JWNAsXi{Ubdl+^IX57M6|%-y^y1DCV|q>Mqt9nH4Yd9$EcQ4){BgB6J`b zZ1-e^@y$b5liMeS3#j2VEZf^r>B9cUbbpJbL&3NW%dEGemJqdVSUeC_VAQ=OXWf!v zJ+TIN8d+;gw6A?=a>F^*cWHA+tGQ{>al(tQSVa_D&|OHy7*MSLm|5i?TVz5sC3F?* zc&y>%QVLb$HES2+)+*MiYMw5g!jhuC1~X6Qa>CQLC&zukANKmcP}EILZSHPrc7@|i zG3qN?HEvY7tqbfs!)`-I=Y4_w^{X-p9Za_~eid<^4^6kBxq1zQTCnx4I`Rk4u~#@9 z$eNXF6qSQIzm_=fU1h6j*R+BzdhPazNpY1h>eh|&{O9N;y=wD&1#ymA(pE)ABQ3Y5 zELip~cTX+@&ET`pfq$4HG(??vV&=HpA&LQa1#mZTPXM0>P6Ti-aDM;~01wh7l8Cewxy8D{8#v=8Z#w2$eDv`>Bh89j$APA@1e?W}L-XkO~D8?bT8&;n6{ zVRy2aW)8kNOfV$4@riH5K2zuuK#1~qiV+iJ1w02m5iQbdAdyO;CGc+~D#~ZbAK)^n Iz#%IA1u;)oB>(^b literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Enum.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Enum.class new file mode 100644 index 0000000000000000000000000000000000000000..cc85236ba2a7cf396c8bc1bb030f59b0ad98fbc9 GIT binary patch literal 1173 zcmZ`&%Tg0T6g@qJ3<=2l;R_W-O+X1Mx)5X`6{@I8L6xCcSZXqf&&xx{X&hUfXyhkn?0)2~5{c z<(aIw(rZ@gCeU7UQ^59vhW4Z@Aoc|ETiVlRTVTF4=)6}x5*RUl5-TuUDi1o5LwyaU z+ZCA0avU6=D#vV=Ka-**yR99+K}kcUGP4dluJ6&hN|;6n6szZs>KN^NT^kz$1;=l9 zWS|axfthTMsu#95Bf>&mH$7>>fTa1-VKoNxC$g>G3-;kscWAU*sp+m^9~K6{Eyis} z9XgY4s18m9HqvDMxWW3fEs6CARJW?{Gma6OaBpAdOW=%e`b=d?5f}}WYzdAL&Cn?k~ zJkwG}J8baBKsTCX|8irU8S0cGgY3kw841dkul-70QKzfFMOQ4pSog!gQM)>-q!3A5 zi{@Eiyg$|vI)-^Hu%14eg*8`y|i6ET%ET+gYA- z+~@eQKCZWkSh&N}UEJ&0_sO$}2R-{CBOhI1SelF&9#hp5GJGJ1#l5hy`Um1CtRFG$ mGS@swK)Fx3&L>WIhUc{CjuOheUx}^Nc(qbVFYuDKg|+`kZXr_u literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Float.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Float.class new file mode 100644 index 0000000000000000000000000000000000000000..3819020cd91c0c751ce6732a12a4c31bcb6d19ad GIT binary patch literal 1487 zcmZuxOIOoS7@S+8wIDAARK)kIh>G~uB3ep|(b{rs?NK+JO9^c_CBY;`S>X?I?ZSnJ zwLeOndlPAjESky8_ucO?N&5TG&tCxUVkwC?y$~oS@ivK)!0=MJVph#se%UM)%#vCC zC?E;~{W;h11L*`c*=k$H&NuMXa4El-?MgQGbfBjsOUBNw%1OP=eps$$i|_Ns&d%PR z63kL0a0DS>R6j1|S**A&x8!t7I*sXEOZt9B;8@^R0?&3D0;B1|WGo|;nUdU61C`eV zuBHEv$Bz_Rt_*mhH~+P6Z3Z?MN}?<<(p`B!ZBu%_rJ3q}NNw73#P+!=cVLZAEN%Oy zvt~PXUOE;yVI&viHhTlr1b3!jFTDs;<^ z9*-7GTHSJ;M(5OPo?25TbR@3Ox9YZ6TCw5_tkjf#Gv}_VEv(ON+42v}U0zwY>On?L zJfKTfUDFBX?SP5O3pO8)^mp>herSLbs-&tL`D&!iNzRa}yBoCIs=CU7nAJKhqsk?t z6ndU6=muRz{u_vyMmYFj(RQp-dt=4&s*(!|oG7|=*{Vs;Ry-1oplNgH_}dpY6-a!& zs}6Nu%cu$Gt!z6%(+cc54Vw4t)dtI_Dt5z>LEGbfCUz>EA+F@~wrYskSYFt6PQ9TO zx9!!ff~}_R)%qPZg}`8E7%d;iQ#=zG>d0X?+Srjg?F24#|0FQOZ?=a& z14nTNM|h?8{7@4(MxKiCUh=*eKTh5s;{)V_F+M~-j1#Oi&N?SC!n+hkF~$z3cyAC- zYvqiNjN|Nq$OO*m$a#%i1{cW{UW)K?*9n0MT+xy95uU_V&9C9Q#v4d$oWxCyQ@Ew^ zHtuMg=6|H>FcZb^;XY{!5AaaqqX-}4iO%EGAf}MPEHEVabe_}AIcm@8U_!-iPVGYc rK;k<|0xx(~7K3Roc^wOrki|TiDwV?m<9W>r`kKHZF@aYwHNO4}z2`m( literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Integer.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Integer.class new file mode 100644 index 0000000000000000000000000000000000000000..081442cbd07cc597fb511b8e0345c665ab5d4b3b GIT binary patch literal 1573 zcmZ`(NmCO+6#hDiWC09YZ~?^?5>OU*37{l^#EM{5Fr{9s&ZJ3(8fI|Pq2Q!H$g>9z zmS=yI__{M;h7bLOIS=%E_Y_AW!Zi{eay z?QR*Sx=4c!`$`%`cSp~XX`6C|_CSjA1@#dhuN+IE7s(J#XL8h8qwct^-D;{tvp2nE zYl6CpTaI1xqux@~uI2DR6umdSRi|080uNtf7)b}qJzZR^&Kvc-Q>7Q8M|^E^tI<*M zc4bc(GMo8KnQB6M17KL}GO57E+Jg!vZF7{WDh!=7ZaDk2bFt%eY`m>in>@4Oc0I&L zT6HIjrY*Lb`xW8taB7=jsOT8nDs$IVwns)}-K6G*yA;U~I+|Bu{*Cd{s4H`9%es)J zL1pJ$vs$AB%K>F8b2h-_bx$hwMOP|Oa+x_co zHtuN8UEI@nACnrVkk**Nw8j}c(3r$SjkBI^j=sODqXmq6IOgFajgN^BR>{;(fB}Wi zXo}BCwM_F1DfRTsAF!VY{U9TR7j&utgJdu19BqlPh%8wu=@Nx9tZ3_%K11HPUt^W* H5OV(k&NgW> literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Iterable.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Iterable.class new file mode 100644 index 0000000000000000000000000000000000000000..5fa7be44d17326d095099b7ab6f2454eb512a459 GIT binary patch literal 264 zcmX^0Z`VEs1_lEL9(D#Ub_Q-n29C^<)S|?a{31pM84XRJti-ZJ{hY+Sbp7DW+=84` zPpGUlBLin}W_n&?Noi3kBZDFyr8XfU)^F1rd{!Wj QiGdA>AuM(V4zLI(00OE-DF6Tf literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Long.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Long.class new file mode 100644 index 0000000000000000000000000000000000000000..e3cfd99922049484d1208964618daa45efbd6b8b GIT binary patch literal 1586 zcmZ`(+foxj5IqwDVS`-4RlK1hnt*aqyarJchy){86-=ow)?~9JOD#LNnNaYgALO$S zK3G2cQEJcZhHM~iRi@KtPEU8A-r3)Oe*6Tmh}SXX;$V0c!)6S52IEbB`%`JH@NR>F zZ87v`gmw-73R)ax0$-aeSOOeNt>%$4%N;a;qb&Uy2=5 za;M1~kRoHd+&gIk#v%9WmddPhollfckreTbW79g6HVF~~`C}c3iWfUlQtj+9%yeM1 z^`U!ZxYdCdZX}?Mw6_d8_QykE%VC@Qqk?;|I0Ljoc z^k#{KNBvd?3$|-*Hx9~{x64ThhT(!Rxl`hvt^5Ft%9>664xKHDA#%K^Vp{hn$e}LK zi7RWCv`rdy#8DMHkgV=TOj$FajbI7%G$dt}=9ql^| zH*k}7l$~yip-YV!y>lCPv`r$V?JVZBy^DL=&SOE_1bvRxNlO9mJ|2*7V3~6I_F-Tj zX&%i47-BS=r=;RD!k&|U5yhFE`vvwLk#FQgkfv1$45F>jI_{H*zDk}t`UPIn{+jkO PdW{5fXR%Ix1RMVV32$tg literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Object.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Object.class new file mode 100644 index 0000000000000000000000000000000000000000..ef0091628dfc16b2e9b3bf082d813a5052de3982 GIT binary patch literal 560 zcmZWm%TB^T6g?w_%0uPpTM`o&?MB>VObpQkVswFF;ckEdhDrWxTY+ zf;MT+?ddu9-ZS&{{qYIl0(BdQ44F&mNpr=Ja@-!n=2)1P;$g^8aooEpf8hTNV znHY`Xrp|*#Q7p6Loo>(^9*MR)mntO*QPu3eH|Dv{9T)&p2*ss5kWBX*9DbC@Hh$d zocEQ$DHz?u;wezIffT?>u#hICkg(|w9S5=m7IMhbSAjT-aEsn;>_m>@(pg$!8I=`f a6(y8W`^Ti#7z?}PPWtary-%|?aPR}lsdgOz literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Short.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Short.class new file mode 100644 index 0000000000000000000000000000000000000000..afb2d9db8dafe89106ea53eb801fd9357983f398 GIT binary patch literal 1355 zcmZ`&OH&g;5dLNp$pbKefZ_`ufC(rM-x@$6LKRj3tAZ)@Vof$fvedGRyAujd`hz@s z@L+lNM~OYNtGju4$aMPaucy1e>HYQl`wsw%SWjUk3x?GcUZn7nA+x=;^Rc>Ce!IcI zDhz`q*YPEHWR=@3kvKd1LhQ`;+Pi?106w2FB=_FGp@iY`0YByoHg_5eC7b(xk+>DB z;c(gV1jAHkd^rYGnyx2{tCW(KZbf>Q(_k3OR|;{ChKZ6r;+`*biXwGW3eA)Ug_Fcb{RVCnbKp?vi1;2eGZwkT=>fKnVBMh3VEwlD=ijvE(XA zNW|)YW+6ONJC#De0Yf5RSf}ZHbyoz@9BC_jC(YTSEZcP&5#=>y?b|MoWo6hYTZS*W`AUdzSJ;Fe#fB^$}mbV3!z-lSP#jZDm+Qt>vjB zn?hP9y}`O?)f;quF~$t)#*vbqM-}e9w%Ll?@=UR5sZO)Hg?Uw(As02E;Q`EJfng|u zgK8vH1V!Z-CL=gtZo1wfm;d$~OY~JH=$E8(0_V_2|5NmZ8%UF%iTPRb`!PWAK^;Gj zQHtjmXH@u%8*rcWc3?Kz6%8(97WJJm1$ literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/SimpleIterator.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/SimpleIterator.class new file mode 100644 index 0000000000000000000000000000000000000000..ca7ad3d7d7f39207bea02dde7da52af6adfdf56c GIT binary patch literal 260 zcmX^0Z`VEs1_lELK6VBkb_QNX2KJ1^V!zai5=I7Q4b3P<29`W9M?^!@Co8cmQ9ma! zFJ0e1DJwO(#F~+TGdMFnFR`SwD3y_cRYNl*1SqCq6Jmv_)(%sMk%22XzqBYh)h#mz zs9!iZGq)fo)w3kED6u5JNDpKkBZCCOR#bUL1_6W=#6fI~42%p+K>si>FtGqVz`(-5 Z0Hj$N*nr~fAW;SmAcn9w8MweA+yG4IK6?NF literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/String.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/String.class new file mode 100644 index 0000000000000000000000000000000000000000..08bd0d3bc20b2fd89f661bda9ccb24e2b8db38b6 GIT binary patch literal 2732 zcmaJ@-&Y$&6uz5=Y)HT&g%oVnsfxFRaY_!~Mcein{xwYEZLPPVIyH8Hu1%S;2|9Wf2IuV!;)sylcUL0 z^SUgmN(-`%Tdrfu9WLvridFV%PErVJYiE+D+N6}yaL7t|zoxh}b3Z=!2DCd*w68 zI3Dp1uKzldURRYn zf;KMN;R%w(8J zt~HaX=!Lzr-89s+vu7ljcFe@n&eKc$*Dleo8udAWmq`>{IPqz%crdcb`MTN^0pIAK z9P((J9s1adlX^dPStOK9%B<`P?7T@+!I{&A^A?Jt9+|U1cDWQD9*OV>`A;Ok{`hrTK@-~l|8_?86G%VcK0`SzQ= zKdv_b6ZCxqK6(t^T&Fr;FgQHiGPJDH(rl$E6vKdrtE0Tg$jCH_*1MyM^BF^ZqmxwT zMMe>qheD9&Bq}F7TO9K8mVMph6t#rU#k3q*lr4tF=2T>{T53bb0&&Qc+^yw literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Void.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/Void.class new file mode 100644 index 0000000000000000000000000000000000000000..389a83e75c12541805bf4ab2a9a01532824e4c9d GIT binary patch literal 215 zcmX^0Z`VEs1_lELUUmj09Qr^L7%L|vPAuy#JqHU=bXgiVrxbQ&fv`S zyu^~yqEto(WpsHPB!RH}%oJ-opbj>h%)HDJJ4Oa(4b3n{2Cm@z(xT*4x6B-%37jBR zdLUaE8Tb&EfkYV@1P}uLNm;4MB@BiPj0{Xbr!q1~GB7i+0BKerkBNZ|EY8lr0hZ$g Hi*W$}ddV?w literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/PhantomReference.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/PhantomReference.class new file mode 100644 index 0000000000000000000000000000000000000000..33abd12896e1ae34bd33c1952e5fc324ab63536a GIT binary patch literal 385 zcmX^0Z`VEs1_lELes%_4b_PC12IlnC5=I6Q4Nae{#Ii*FoW#6zegCAa)Z`LtMh4E{ z%=Em(lG377Mg~?5&5#hF7@JLIUS^3MBZIL9rWPcTqSQ3~pwzU~qSU= literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/Reference.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/Reference.class new file mode 100644 index 0000000000000000000000000000000000000000..97ff09797f5f39a4d3a508b0cad28476d6726339 GIT binary patch literal 468 zcmaJ-yH3ME5S&e78$t*H5~%6U4Mw61mOD}*A&5mmXUxXB$U20v`M4B(03U@|pOF(3 zM05L^nZ2FQuhj>D3!HcudzcWq8JC2y@^6;OdlKY{$%5ObC8y;TVRx=Glay7#1V{OC zEIlX9IVpsw{0Bl`zg?TxiYtD$tw(~#O@rWu+UPPOOw_h|&32VY*2(1`fDKB)i{PFY zT(C*`uHI%@eog-u778G;SQW<84d~B_(RNF2n!i*<$}^qI*~514d2JBkbnVlxZxKf8 zNh9Ao1EC{+1FmFU^yGD<>e$-Dj^yGp`Zn&_2n?{_;)XIA;GnHX!fg}|ab%T_zX6LM BZlnMJ literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/ReferenceQueue.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/ReferenceQueue.class new file mode 100644 index 0000000000000000000000000000000000000000..03e42b9f312e45cea98f8c37ea9cb69032c840d4 GIT binary patch literal 516 zcmaJ;O-sW-6r62q(#Ef9)r%t5Q+lzUO$c~UPz2Ei?=ilHlX(d-`Wx`BpGB@qtMZ3z``vt&qfwBMq literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/SoftReference.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/SoftReference.class new file mode 100644 index 0000000000000000000000000000000000000000..087ec244449d0f51832e37fdd0dab6d9d41cf86a GIT binary patch literal 428 zcmaKo!A^rv5Jm5lwzO5-+SIt{${lRPL{}|g*_Da05cfz10wFXZ4?oU@AK*tBhu4Ne zG~K++ojG?h?|%P$egSyEwTYRDIbrCgMXEf)jrE*`AEA?nMdG}?XB?@G{YDu3X;Or$ zDp_DF2z2xDAGl>NId*m&bIC=-uN7CUU3P6hi@5@Lnl%zugr#M-_~TWCfn^IwcyfdF z-?`UnbuKw*58R*M9 a5Y@v_YqQZKsm7Qz`a+lkd5J6SnEnFuCvB4e literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/WeakReference.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/ref/WeakReference.class new file mode 100644 index 0000000000000000000000000000000000000000..dab0fe9804a0d7e3374df86c4621727f1d0ee945 GIT binary patch literal 375 zcmX^0Z`VEs1_lELK6VBkb_QNX1~!|_yv!0iMg~z0pRB~PME#t^ymWp4q^#8B5^K#c zMh4E{%=Em(lG377pkj@X5U`*z7R5-~i&E3{gHqE{i&FEFQv*v=OH;wRG(p<&DzgD9 zumh_#u?ew4QVMmD9g+}=B@m5_3|ztarA5i9Zkahi=L&_VCT7Fkp$GCFBZD-;mmm{R xlrS=gqsqcHGbl1JGB5#yjsZwAGB7i+07+Ibj}6Rchx0jrDj+hP3|wFp+yGN=W6b~n literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/AccessibleObject.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/AccessibleObject.class new file mode 100644 index 0000000000000000000000000000000000000000..47de3236c80eb46bfdda76ed66c1feabf3315829 GIT binary patch literal 332 zcmaiwy9&ZU5Jm5pXf(bHD=V#%#@H)@g;s(^z(T9Itg;fKWLME&v+x7_C~*_P1sj`r zT+Yl~=J~om01VM~&~VTs)FoF_#<-MX8*_s1Z5D^<5(ROT?1Pl=V$M`xh~@U6h0)qy z5!~68@skqAL^@~@Y%iBc6dH$ME8jD1zN#16o;qja@J{Q@|j=?|c2blvx|GyDJ z%RrxDLf1$kXXjL?+t(?2AQbcu02>upIueR`r%meGg7c%4HJ8yYsyY*DIu=lW1DLK* AZ2$lO literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Array.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Array.class new file mode 100644 index 0000000000000000000000000000000000000000..d24ca714342a835d5ef0cd3183ebfaaa942dc786 GIT binary patch literal 1640 zcmZ{lTXWJt7>3`ql>n_;4=tXnwYGp-tY-_u3hmnggUev3UZbLe8z&2ISf_t$R#FHtk_-oOWjOwAQ;SZ7!$mcB473I4+rqtF%u z&ahSNp4g{$#j}M|X?gZ&R5eR8Qt$AD55g)#{?plje-B+>j0}8a$XTu<>@W(bNTb%@ zQ*-J{=~};EtSvIKP)gJHJ#GtzHBDW!biiOp>O3Tq^hh&7T0=XShqM^7RK*(l0nMl{W6^6S#uRf2 z+N7MN>kDUIk^Q7m$MfyEWjcwUZ9h8n=5DG@hK{76MV&3`Ns-4gPYF{y3%a}mi5U`$ z{nRqe36mJAWm=NSQk}7*TF8=6hM?F|En-f3C7x=T{YkH}samKbp&a#^xT>YvlFD0t z6byLBmFDLgL13Tn$otDsNUw3gk3G7yl{n0>l17p<&9IqDpSfd)?kSI9%l*lx_ncuP z#Z1p5&}#%v^o@&f1}dgdT*DMc{Hzy+z2l}IiKEdJ#V!~w(YFa$qu&KA(o+tXk)f4A z&x;h#k^)-i8t=`7(=iNV)BzG_X literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Constructor.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Constructor.class new file mode 100644 index 0000000000000000000000000000000000000000..0e661eb28721194ff6d1ac99dccb6733bc97087d GIT binary patch literal 1037 zcmb7D(N5Gr6g{)(b}6VJpr9fMC~ZhwePuUm%&JKfQIl!!=d-~oL};`;yP~k z6;IR7@jpa@!2ifFKajEJHZy|ZMXgXb3_HF5sJ0vn`$|NL8>!>m3d4%$*W56y*Q13P zgF{8$@evtXy+Rt;an%mPA`y;~6L~6yNg3umKVTS3f8d7ltT5rX3qc6w*C$a>Uw@6n zg_VgesZH@YG z(tR0XaHsmIgFOe29XxTc&#>VgAJh|kx(9}^8y?oNUL|D2sUpMemr*3rR1TFW75~CH z5~HCoRMs6NnTf<3si=jeenRb-EV7AtI(}9Ro3qz7sb3*6?9}l;_36Irq{0Bh_6#aU zX(b=u%ydLoDN2c$t3shdskjJAiixw4(6&N4m`P1q3G`(W<$57E^oFKvJO@LAzB&5! zT>7rzI-Q!dYrvsh3-i;nOS=Uu62@=?H}mxtmhyGETyJ9~Kd+YfTFJkIyHs(VFqbqo Va1ZzKpw!tUq)>c_En+mV{TnxjBgOy# literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Field.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Field.class new file mode 100644 index 0000000000000000000000000000000000000000..34e96ce812429838e8f59691c599de72ee3a64e6 GIT binary patch literal 1539 zcmZ{kTT|0O7>3^kZQ6n8fKedk~;F&yzmG3 zqa43Y(h|Gdi!_sWpYPpo-+sxTzrTJ1c!@m=I~G1#s50bsUC)j77Cuth^QfK$rThYFwB+8nfiogu!ub7eZesQ-+JoLFhjtR z-*r!25rhoWrE)8&`g(CrRXOo}z$Gm#WZV7HITLnNEuS#tdpzvb{VuWj$WLs^hFlpo zOf{J%QyYfj=byGXk6hmiE$mwOL=rjFd|wLgCH>ScBHF{)MlB)gJswOT>eL+>wtId+ zeHl&KbXY=K-XtK+<2^I&*E=}q4NhVE(0`1c92OT--I1S1#RQYWh^3&r}15qS? zl-8o5>_kzPqT(1$NNtEDIhv5VLh|I225Dm2ipdcZCut($5mvnNL-sGQKvJyJE>sx`)&8f{H dHaF>MWfKS%e+^KTP(hV(jZwC39>KST`UmUVP@Mn( literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/InvocationTargetException.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/InvocationTargetException.class new file mode 100644 index 0000000000000000000000000000000000000000..a0cd1bd34c97c4fb4de921f5c2d2551ae428be60 GIT binary patch literal 337 zcmX^0Z`VEs1_lELK6VBkb_QNX1~!|_yv!0iMh0dL%`ip=2@RjD#Ii*FoW#6z{g8~J z{PM)4oK$O&looa=B=x~1MVWc&V8ue|sU;zaML^QEB0067Br`vckwIKT6G=6~bVdda zphD-w(&AJ`2Cm@z(xT*4x6B+MN6s^^EI&CBq#eyPJ&-dQ8MG0uElN$xNlh-%$Ek&p yK^UPL?komH21W)ZV4yHCurjbPFat3IP=p!CgV1bXnw^0IOmjkME+CJIfg1oH>sm?x literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Member.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Member.class new file mode 100644 index 0000000000000000000000000000000000000000..b249a392fa0d37d033a65ed3f80fe75584e87ba8 GIT binary patch literal 313 zcmY+9%}&Bl5QWcBZ21)s7y1UUvF=@IiwQ|lBfQqf919=7hcZmB3vf00 z=A1J>Kfi}>0QVRN7zMZ@_;0JHWF8S{PUuHvQCU^k52g3)i4%lYJd2XY_gP#s5k?u? zm{YAxUSyG0RYe$2rpZ=)sZgsT3tjVp5Qy_d?U-==PhZ+PDu$jI7UgHY$=S#hZ!(o5 zI?HlzQhv_01iK5~t=Zhw!wEO19fmiWQyc#2gyBhgU2jG4fgc6r4>UP8$kMo6zu48gfchsevO3s#LWgS)za_;!xDX#(8lz-Pq}RQ_;WH zLw^823h`n)i7UgwUhlk_dE>YH`_JtifH!D4cnD6kpQ{>o<&(dAKjGM>3Kd|FF3-a??jPm!-{g`Wp_ z$Zwu5oOmr`Ene5-Dqn~c-@xM-f0C}7sK)!Pl((JgYN)f@Q?8Y{#||2J#{1{IFW|*r DB@*9V literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Modifier.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Modifier.class new file mode 100644 index 0000000000000000000000000000000000000000..44e0fa086959e5bb53376822009d77e588e038a0 GIT binary patch literal 834 zcmYk2+iuf95Qb-+w07DighPRrQ_C^o&=hV#2-i4bCF4Z4u|)4Su2Z(M){?!61Xny4 z7d!wDg_yM$b#M0HZ|0wW4}bpt`V9cb@WzH?8(tIGoPRk9s7HWM0)4L(wPZr3tXSn8 zbP@vgJff+a_zEooy?HcCd@u1oszMhN;>1m;r^q3&F{Pm!C>RphiNA*4r)U<^)7E}K zz)5ET`hzC#1Lh@>8^+WR6E*Y`^FnN=s*RU|9t{&en!27USXgk}lNd)lW$z;6@eysv zQS^=rF5eUAjK(RNc|Bh(3Z4<@j_CLl^RQC!HIq4kZM83Dp2_^I@y3!#<+XV|<$@Ii z2E2~Hi|kuf3jRa6ws@VE1=@->AgP$Bc`jrV5MpE9HmHz!wPYC*&bW(ORxE2>v8;Hr zm8IH>a{{|~yWoPY*`#3NeA1TR;%Hp1sw|&2$Mrv#XMD-?>PR^W>|YL4`Le)wO#V9v z3@@9r#Rc}@5dX)*Ki+{o=rn(~fn>oZvTd+~+%tF!dD~z$-#2)Ge8u1)@>PScAzwH6 z2J)`KH<51{d>eVs;C-Y!2H%ANzT_U<$J_Vd0UR`XsP&=NM_M0ieWLZL)@NErTE|+S SYki^hCA`9X0!O%7F!=}nGKH=H literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Proxy.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/Proxy.class new file mode 100644 index 0000000000000000000000000000000000000000..171a6696401aba6408502ce4f51c7c50550ae113 GIT binary patch literal 698 zcma)4!Ab)$5Pj3uu2!p6tJR}|&|X}xvPBS4EEE(99`uxM^d8V=JpBsB6*X~S&NH1e&+m03uIZcj!^X!R=k zX~O*}v!k^Pgg%Xe(W5lUukY9cp}@1qv&3V8e^!~1G92EOcwOXmiARMQ%NAq9_*}*6 TKV%Ix%U#FDp9o=-@dD~!Z8ybC literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/ReflectPermission.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/ReflectPermission.class new file mode 100644 index 0000000000000000000000000000000000000000..478d0fe19eab306c08abff223dd0a1db7b15db5d GIT binary patch literal 237 zcmX^0Z`VEs1_lELE_MbEb_PyH1~!|_yv!0iMg~z0pRB~PME#t^ymbBGlA_GKbZgBp zMh0~(;@DMk1?QI*C8xS&=A<$*hy|sl<)kK;1f&+_W)>G`=I7~wjAvv}M%YpWQKFBb zl#xLetg1LQxwI&=q*C80u{bjsVHATQ10w?y&?5{$l97R#fd$9{(X3#a4J^(M0C-D5 A%m4rY literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/UndeclaredThrowableException.class b/java/java-tests/testData/psi/repositoryUse/cls/java/lang/reflect/UndeclaredThrowableException.class new file mode 100644 index 0000000000000000000000000000000000000000..6b394d3046956503e01e38105ae00bac7af22b75 GIT binary patch literal 340 zcmX^0Z`VEs1_lELUUmj3~aEGcs@hwKyl1 z7N;^Ya0Ta=7A2>;W##}midf8Xtw>HSD9Oyv(*wDdkpWCW99@)}mXn%XqK{7(BZCye wmqDd@C7HRYa3dKM85kLufZ@Zyzyf4314#xj%?hU37}&uy2bAUn@|YO701f+KLI3~& literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/text/MessageFormat$Field.class b/java/java-tests/testData/psi/repositoryUse/cls/java/text/MessageFormat$Field.class new file mode 100644 index 0000000000000000000000000000000000000000..fa8c4f209a4c9e250cdc9a02aa47c5b8bdb81759 GIT binary patch literal 425 zcmaJ-!A`HW)O^!Q9Tdzgz%cvdd0H<8AONcu_oF6@P` zWE>6&^=qY-y&-h_g*FyC@@6(wIvNgM3C&cBa4Jm_XOhtA57uN)Z*v(~cG(#%1G%s& z(Z<0c_p{_94WzGPo^dxeU#=24=nzi+%|@u@840bi)-t_|g)x%tyM$gjxqc4eG$&Nz zjddns6&3;i!V!+j$&FNmcF7c;I0vD^UrRW~7OIRY{MJxsRE2{EGut`lgPCjQiWb^j PUG53H*k?rr2dnxEP=0Kc literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/text/MessageFormat.class b/java/java-tests/testData/psi/repositoryUse/cls/java/text/MessageFormat.class new file mode 100644 index 0000000000000000000000000000000000000000..c331e6dc74cb3afcf2423289039e49680163f33e GIT binary patch literal 1457 zcmcIk%Wl&^6g|^6ag!EkOOqx*p+KQFkEXy11p#eDrAS3YD(V6R($twau3S5e$0+?Z z7JL97g}5HOv7?v;3l{d7JNGf?K4yOX{_zvQ9$pw|8Q3%MjG=Vs3a`(w-1U7SJ01^1 z5i*otxxTAjGt|tZGya{oJnlQKV6*G zvspK-*+4{)k4D}_k1Hjl&rngpWIgf7lVoVp!H0o7=PEq7*q2UpE_~JX`(n&cH$Nwb zC^1&8#7eWRW=;%^iBJ%rTO1%xH;G3KD6PLSsF_v)1%_(oLv0vn{tRC)`RWuuoSq3= zwG#rlqz|IOK*)4I$t><}F9==b27Ws&?5qdF%YuHU{PIW6Mrbn_CtPyr(Aa#*NBIvd zn@K%B2Av@tY11fl>EkMp4DEumQ@Xko`--ObG*Y5J<4ie}MqGx1;cY%jI`6qg_hPH8 zo&^;uz8aUk&exK9{cdcFQQVr)z;lKrO(Llq!<&Dik{gD!@RXG81wJJ;eL*JbviKHp zkJ>hM$y2rUiD7Zb!(k`rQ;2!f>Js7OAdZbxuVY=ywG`{v&~iiLDw?=Ka)t0FopOuTAkQW?2^ntVj>auw70X+=NB{e@ULf42 i?*Sfa%??bB79MGQj3=oC!C7_ literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/AbstractCollection.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/AbstractCollection.class new file mode 100644 index 0000000000000000000000000000000000000000..65329f14876227df401a29c958e49c73b0de8795 GIT binary patch literal 1103 zcmZ`&T~8B16ur~0ZA%qI3L+ImPqU1&mTldG4s`UhMKR z?Qnpzt#(D=oli!6PhRl84`#g^y4=6yQfNFSGwNF4es*Jn(CUwsmc!f%^89ktf=D!NH#*b)yu6u0o z#vGSnZ9+GTvjywP)Nh-f&iNf!l^A{oyc@%MfA1gsT-OPHpI)GFUGD+TaR{ykmf@eR nekb+~Mv7iy%^5OHuV9xV0lg+0$iYWcHEU{m literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/AbstractList.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/AbstractList.class new file mode 100644 index 0000000000000000000000000000000000000000..efe5b38554773e5886ff3818d3ac3b07a45ca713 GIT binary patch literal 1348 zcmZ`(Nl)8A6n>M<1X7k1C|e73!-1A`Um!xF5tS@OAT@|XZBT$ePooc%eK#T6bdA|r$^S9ZVO;7 zxL#>A$%J_&1OmBd!nRy*G-_;O-t|lYo4YtR3++1nAV|4Tbb|}@j0RG?tq$w z@&fVlfyMlthCG%F2JiwILsn)~|KOXsgM|*eLc=|v4=XEg76 zBhlz#d5k$u&WSG(S3T@qhxa2z+mgxOeIC-nmH0)vWpS4V-{nD_65hN5Waa`w!b+3}yhzkUsa1s|0|<4FA631!?e$X45%&Z(-j}`X28Qi^UL{_@MOydZgqs~33YcMB%_0Q z*xBohmR)}ka+xJ4P_@o_E&HtB0!y5M<=q^XSrU6T1W}3$R5@KG5!cZWC3fa877$cC z2?9nN1tgPx(EQBfmKxOFRM2UFz5)KWPA_?Z;0eb2P29Mu|C&{((kuv}r|s#O1CBNl zm7yAN%4l~2(TRcpGxnnpnEn5x9IXMf6QNA<+Q$=6)OH&Aghn0Jy9%qS>&se#_@40q z5~`Oxz3fC6>N#ZO%ES)`j5bG<`t9>5M4{~{1adN6tOlc%?hjAIs)5v`BSx;%dq4YD z{W-DrENrrcQaq}-QI>e(gC9W2`pJ1J6Yfbo+@ac5tgT*J-TPP)(CKBy#@|A5pHcl5 z(ovnBM$*mVI7+0rD0?%W5u*kC7xA^#$iQz27M_(%eO75%pDVPg&pXArMt6a_hu8wG z!>Z9n>EDO7IhNmozfC)3eizn*qRvBlRL1vU?bGAZe_}9tI+j;jpBMFC6#DA)5*iFT VpjXIR+Gb=!Rj%zdHMGVz{{a4H4HEzW literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/AbstractSequentialList.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/AbstractSequentialList.class new file mode 100644 index 0000000000000000000000000000000000000000..aae94b1423023054838a5e44deaf2cc2defbe10b GIT binary patch literal 718 zcmZ`%TT22#6h5Qon%Oe_~9H5iqY zoah8?z{%3AOn0FPDNM9zve-@Z?!C^#>JD48lGSYYCpzK-ZP*E`*bC!mAfBYccB%=Y zCq7~kXvvkq-kQ6_4E9Qwl$LQ=#VW)I573*021=$?1lmGw# literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/AbstractSet.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/AbstractSet.class new file mode 100644 index 0000000000000000000000000000000000000000..734959c8301a7655f23e3e4bdcb9aa0bd6323b6d GIT binary patch literal 422 zcmZutO-sW-5PjQL(^PBg*Fo^&t@U6$n-D0a1wru;@!)M6mv+mV#bnbT=b=BKKS~@Y zN|een%n_z5>A(gfn3;jgTGwI5ll;{8R zqRW`6_tE5L+dZxzo;{isE|;mRJ)*}+7>B+iuf95FICN+$5!3+O#x4Tdv&@+LSvqAyO0t$x@|Cq~d`-Z5$JA<=B-5vY)pP#>o=z!`by*BBMNpDShXVQC<4h_mRgePRv zpao`CJ{y!}>b=R1&iDndjihjEZQperTMFN+tF?Sr3_LDJfn(5CI=nlgk=Ewt+!pdXdWITDPs<=vgq`8Jf)Rf)Xvy|H$%PjhREpZT+#A%6duLEn zR}@otedpWp*EtLnExJ6E)`YcayS@h@YpgQfU$P*|Nxu~Y912RTa+=Bj{sEgah_Mtx zdeSmG-9t`Azp=Z4BUJ}0RYMNAZjcQXZI@ZII#Lt!%u-FpxxC-U)iMR(nATH^;3~~= z4!m684E+ln4UWj+0RWU}x$b{P0fo2cTz?gfasObHC#`2D35z>(78}$2;#k)wT)Yy; zEIp(@8lA)0V`+{d-Ko_JWx#EDBtki!#>8SOh!%Z+*s^UW4C{&FZ8b8y=Q>QoMvKNuUX-$e%8#BL6Ux5+{ZA1jiaN z+B*M=NV-o3WoUu2cor##-@yhDla}Bqn~!V(Q4xNImf>BC@Rf*noo;B}O}eG+Dy?Z- zqIGRIB72)QbzG)9alO0n%5*P|x8QBlP8=(R59nbWKZ5rd^(T6s=y*4d8NAAs{7R(f gX{5VK&tm=_yejR-aSbPNK+mBw6Ycl~z0}dGzX!oP)Bpeg literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/Arrays.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/Arrays.class new file mode 100644 index 0000000000000000000000000000000000000000..c89a7a36f14651c934ab4f1bfdb1ffba18a916a2 GIT binary patch literal 1993 zcma)+TT|0e5XU!MT5c-d5HBEzXv?h#qS%%qNsIT z<+$1NZ>B>}J3jsX`=8xCIXP#~pTEC;6VWD}r0HXtJ{goMhV`&jGH5uH{cO-kvk|on z8qN5JahPVhZmif5vg0O>ha4|)EI3x;m~hO*vEkT>p| zv>K5tmLJqnTUK1>?<`62hHfp_)s{&?anNdg3cJ>uIt}YVbm>)t=y zuY~78SQdn7LfAHh{Tl8 zDy}P%JwADr$D=EfJ-!6W zhiFFDzn8?b65mha2NFL_;zu0M(Y*ATqsQO^xClN0m%yjsa?WHg`==dMvfv4mE literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/Collection.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/Collection.class new file mode 100644 index 0000000000000000000000000000000000000000..476562415a312ceb1c2157b095e69d6fccf4a943 GIT binary patch literal 841 zcmZ`%%TB^T6g`7Ld8nWQilE>#ttR4H2nivWkeIlDxRBLQ8YmfCEyYAX&4nM}M;UL2 zXP_?HnS18UJ@?!@Kfhn!0B&)q;7q}}f(wS=$ow=IHdL+2pqQh^%d7h#<7bA5Zd)!l ztr0_7eHik0UJ~5umma%ALwC!XM=@Q);jZm4WK?a!8M~$^HK%x)A=)zg7I()E3FUlA zm3E_CC8pxqHOJvpKw8y0>xvAj>I3^zidWx#rX}8Oo_amFU*JB8)B=4CCJI0Is zPF2Qd#%n?_WT)PxuevP+nKx}qUdj8PRj#U&j3gj)6#n5|OXr?=bRsUFgt}teukG1TvqZ{|8poEEq$s2F# z3@JJMl?E^*SKkD~?gE-=gc%qD^li}dO9biBAq3DGh9cJpqH>KPPOMF01+Ycu+ek=! z8_7AoL-;Q7XS_X%Q`7rtWajuj;Rj1`mg2*u*gMay#CaS^z2j-Vf>$TiGO4JD6B(WU E0b}XHlK=n! literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/Collections.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/Collections.class new file mode 100644 index 0000000000000000000000000000000000000000..462b3547feff2cacd867ccf50a6c8a1636a118f0 GIT binary patch literal 4895 zcmbVQYg-dX6h0%=2%;him0qovmT-$&t*wbEm|`0Np(fBmFLp^buynJV?ryB~r}aaB zKz~#p&&=#j&g=y@{h$x;IWy zTTi-a^kQ?+QkfT-&Q>hP3aSi7=8C%vMt#={F#cRDL76+3E6qpJZX3>FY3tzFYz5_N zd~BuJELX*ZV%$|GVQX%;XLv^7dSdLeVS=ZIsVu3)69<-Kcqa|h@LER z_*YhQgkE15PTTE@1zO2TMwCy8kPxH(pGJ?tbfPKsI@i~oVKT@mqaDk(vun^67&F|< znL#RvuOZ(PEw^{V;AVm~DN^i9K6q`Y46z6msU03?q-!}0=4sBFYumWtEY~R)#{OTRVk9c4M7_4M)Al&IzPGiZo|_MrhnAQz?wLK?Xql^ASq~FYlLaO%#eD|%he?bDakb&Ji2)S~Gp8>$a_qW#C~rSUtQYXvYSQ zNVDQtA?B=8_jGlH8z2@;E+Srjlp9{T46ajB{1T=CpUuzWE z6k59aDf*y*u+Lg zn}1A1lZ8xa;kXUsE#-(u3z76h1v)*czuFM`qm*&Bk{*7G_?B~Mn}LhZjp&I(-xYMG zY)jUS$}cdo=aeiMTu?b=cW#BJPgb6=Us>ZLmMKU;0G$pJJCg3he|H#sg@j;yAp+$m4j7Dv7cxVp~GEC#L z>UqXV*ykL_Ckd0JqGClv#v5+mYne|i{#`XWsKQ_7zX0IHGx#BZIB}@36G_4+z~Bu2 zq%Z=r_-_=^JBZG}S;Pf6r|=l!aX7E=1Qc=91-OW#$KVo7D$iwsrxd<|_$o{*JR|VC z3SUD!8=L=L0>7`ue}LmZgpU;d81Z#chh%;O@lCj;{I?N*3ZE%FCvZ{WdBh7b{{mJQ zb%OgBVM*a-#3lR*Ci34!d=EZX_&(wXG5iHQRQ@l~{}nt^xQw_0j}@*W{u)*kUPb%_ zY6^dYcnzK^{4L_|Nc=kDXC(eQ;*D7RO%ne(`nO{7x3&1Q@IAax`5L%dP1sR*7x549 zqr!U_Zy$bA_-Dkwz^@9wMEn~V3LhYDL0e%HaR&|+K0<84vBJM2wxO%AgMYa~v%NPr Cg?Uc^ literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/Comparator.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/Comparator.class new file mode 100644 index 0000000000000000000000000000000000000000..9f03b7b8febdc7909fb35b19f3bee4c5713a066a GIT binary patch literal 295 zcmX^0Z`VEs1_lELK6VBkb_QNX2KMCq+=9fSR7M7M4WF#UvPAuy#JqHU|D>$cK>*zcY>W(y3`{^TGcYi* eFfuSRumJh2ARYr7kk8J*0cJx)I2pLWJZ=DRm`cq6 literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/Dictionary.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/Dictionary.class new file mode 100644 index 0000000000000000000000000000000000000000..2defd43ecff7d7b5c9bb6d9bf1baf42e3d30c9d6 GIT binary patch literal 627 zcma)(%}T>S6ot<;vFVT6s?}N*#f>Bg)}`3cl@+9diIF?m73nlRMu(pI-oOai-x!!zn}A6uyvs21Pd}4C-8b@Kii8XktF_W-?Co zE1B;+o-=fG<9TW=tZpQQ+a36k$3shs!0$0sN5b(f8HEJ7*pxG`$HQKq(iQG2>@eCg!@?Px{A=g`h~RJXsyK*6D$RYLsp=#OuG3tNYA?d@Wm)M|#$QV# h{e8tD5G)f6u$m?Tnt{Rdj0P>Rz))7(&PMXIV+L;-O~ zIPd^G6yn=;nmCD(rJb2?X1o*adQQe~V7Jabj)S{Y2XN-!j^kv*&RIr=Z z6^~KgZfdb)>vO~Ye8We)HjJgJec=N~gDY*>_jx=F1)~$URX^{v91o}GH0HwHPOI*8 zyt>mciTOz0BL~z?MwX1OZU^z5vA^N$i6i@#s6K zPW9GfveV@sJFs6NXm^6|L3>J5o@cP1r}Fk;A5c>7#W?>Z iy)rz9^m@Yc2HFw5o!H0F-lhCDdQ3X4&9X~+@1)5V-rBIGIv8LD<8 zv8@;D4nytVM$34UV%jvZ#c9w; znh%FM5ZP&(3&msbLWWt_6P#iZ20rofG)2;Y;kng4o5W7)?ZipW2ayW7tNKDsGADX} zG-J`x`}n{U&SX#q&AtdF_vD*V84CSi9J=B{dX%ep$)kJnIng)8uspl4xIsssX^Ail zrI}6!46BC!4nYSu>Yo(Y149aFdNRn;-&7)=gGH6bIeO=*PN87M*MsKp|KJf+{w>v+2O5_ck5cRJJHn5w1{Gizc1g zNug;`+No(X;pqPb=ko>Yvr?dhEPY|!vJOr)MB8O5@VQ0nBY?_jy?oj%R}C=T6IZ~1 zs%DWbddHovx-|Yb)cL_Ldls!Zg+z&CH|TJmDdD-$wtd@KrHC?BAhKNY4tEuZwr&L* zJ;1g+S25uNyBw;P%x#yxo?Y;kDi@$>Hi9&n44`}_^6OmdZgXYP?zr5+6_RwQ=Rjlu z#nEJ+pR?XMD7pbC4#rU2WC;6mopeT%f-~mrczp<69m5zxQ1OG57Hx!(Xq2Xh#dube zEy;iG&g=EF%4;ZJxb0EIAgb?*xi)m8<|77E5g{C|jK=i737Lr-KBfR&eKACzKHlz!e55JLaT-+XKbFlaxNRu(et{M!EyW?wv~P%5k*cVOC{#S8$^&nkbd_$|+QFAd=`Zj{ zJn#X06yog0b)3W~Qf7AM%$c*Z<3E3Y{U)MQIDleKr9_Z>K!D7)KWxtGk>(^<+#5ZHRMcYY!2i`7C@;yz}KSO>m?!O<`KacyppqGaCfLFMp?RddL~l`@qw+ubyczre literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/Iterator.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/Iterator.class new file mode 100644 index 0000000000000000000000000000000000000000..fae0b967366a7a78bab4fe8ba9e9fc94b4b97e8a GIT binary patch literal 334 zcmZXQJ&wXK5QX0mh?oC>C^$mWY^Yg82M7s4krf4k`V@ L`$j6LW~z1t^h{CX literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/LinkedHashMap.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/LinkedHashMap.class new file mode 100644 index 0000000000000000000000000000000000000000..27d17d80c8c38c563ea7b92e9cea52d04c9f78de GIT binary patch literal 643 zcmZuvO;5r=5S`_#fTDsTs25EPDIP?wwCN2ZDaHe&2jXQd8(gf5DO(c%ng@S?Kgu|} zG*FR4cP8)k&Agf2@1M^v0Jwt-1L_8x8E{S@XLG@&Lm+GRdrgl(#_X$*Hq}`%2Q#{) ztw{2q^+4Y(1r~;UDyWP?M&QPF+nteXd3bu3v-P_@a@*F(Yg>*M=CH+BRVev$At@IN zj|LG|sm8j1ifQZddB%KcHOFXT$|QltE_UTBDIkzH(Mc11;52@~Xh@(OvbXt?b%P08 z$gYs#2Z8#Q%WIA6hL<}j90R9NL!hT8+wJ^s?(M*w#P06t;sy7&u9TpXFoEK59)&*Z z@c{Qy8F2B+Cb9TdT?K*K=0^U|IP8XrCAjJhhK=9~2&C{!<3lK5%s>`16?1Vk;+RLY ofO!gvn%~p-K9qDkfWtL^gjpGsE&~-fUgIaIT~(;UsjgJ}1&BzRzW@LL literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/LinkedHashSet.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/LinkedHashSet.class new file mode 100644 index 0000000000000000000000000000000000000000..6aaaaf1fb676be2bfb61ee3904899cc218a32f2b GIT binary patch literal 457 zcmZuu%TB{E5S(q(nidN5fe;rYZs9^WlPH&}6_qM+2;%M*tGF0j3JC{3jRPOhkE(E- zNNFo%t!H=k;aPdJ{rLrOj|+x#hCai9VaPBdv?Hly786?jY~7bt?tMGGk4jjag9yVBBx5KNjh;i1L{c^bAO860=xc1o1QKjwo! zz#nD&X71eW{y_3U2iS zql();XgYizzhtT!!t;#BB&GVEza^KLb& zs|coY9QOKxj~ya=w12qv0> zQuLJIA=-puW};TEt|j=bu!WwXZ6tLs>6LdNlWxl>Xmb~Hvy8YA$sp->#kZqRBeaE_ zWrbsHC9G*BVQCR^9bky%w0(Qo+CxEH3aAkecO}|DgH3aPJQesjI!6clVaUImKB~ug zgE{c;*|A(VhmfB%?H+F#Iqb^lN8@n!YVGFGdG4R|bjUs35nubl*ODtUQ`GGcE$g($ za$rW`CrZ>KrVMHw5u${=uwF(}ouD6jcpC~M&$gxiS#(XQZS!97#s<%J5QB^ZcYb?} zW(E{fkI|fUTy87bAk!DE6QeOI;5SZ1{KZsYm&gG!-wCXfz+*H8RHo_Fz6Latv1c>( z^^ARkZl?KjK=T=Uffnt)x9GP0R$wRlF99vb@fEt0`tJg*&}wS00jj3GU ztNyo6#|a%aq&`;}?^{h*ucka@kM<`wI;o8v7{TaV${DS5Yle*+Dkhe6}qYMs=~K4z74zvyO_TYT#EdZ>5i7)g}jo$RfTI> zzX5zNp_lyoQ@Bo>D!&Jj|A$fjkLa=X^8|KJX-i`cyhf(R+rXtM{ti7;es`m@K~2ry b1HVDfHGTp7l3r>28a*0!>J7bB9eei=;{ZqV literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/ListIterator.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/ListIterator.class new file mode 100644 index 0000000000000000000000000000000000000000..e916842c1c8adfffb04e332d433f65c429293ed1 GIT binary patch literal 506 zcmZXQ+fKqj5QhKZ&~gw31U$V!dt1=7kU7Lm7vq zAc2cL%s2o3Gdn-OU*7=wxUz9>8mDR|?}Lzg zXib7dZxq+7&l7rP2IlQFfABf%Xxi| gAE9CN$N71JrioiOV literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/Map$Entry.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/Map$Entry.class new file mode 100644 index 0000000000000000000000000000000000000000..d91b3104a06458e230274685ff946be3b6d8445f GIT binary patch literal 480 zcmZutO;5r=6r2b23qeuAkGnD3i}eh|3(s9f03ulDmZ3}r8X^;7f+c-^ Qt-}#ccoqtdje+U>0GRY`!TS!6qDi$cm z{!b-Pa@=zP+mFv~MhRK0zY44l!XS};5O)=^UFXxa9LuJb!La$|@>&g&R>oSNviee| znbuGx0;kK^MFD|Y&mRUdNhAJRbuPLs_oCmT$|$AEyCo_`5w{4@e5OUIiJTRwn{dn# z`%4sa3MYQhT3|b;q=~PapXI3K_5}_XK(9gh2KC#fT^VR4BNH6S)^~N=%Tm~Ka&Jb9 z5O21(hE>r+LH$UjriJR2jITQ3HzwwJ-S@?S`%AEPktR^@g=sWUAAOxYFynlkZ4uYTEYsAB zz~KCUz|WffcSduu*1aumPS`)XZ7OsyWy4a~&Jx-y?eko8)a_dsgqTzJI5` z%X$y{v;G0=2Y6`o9^r6?9}$0yC$st~>*G89XRM#+^G`B=DCG`b;M6#Ii3-m;6-xZd GR_z~WUEbRO literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/Set.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/Set.class new file mode 100644 index 0000000000000000000000000000000000000000..f7bbb046a204d279476a576b3760ae1d74e08570 GIT binary patch literal 829 zcmZ`%$xg#C6dbcOE&EpXeN8}6&a_lQRgsX8I23V!lW8poG6|$E5_}p5K7fxxOx#tp z91?q;=e;-M=kK4-F965bbFl4T$HA_^K-K?H0{yOcA>jDc;`57nxA;~dSq=ju{h%t4 zb}yggo6Kk#JY=r!pH$goy_n(~6-g6D0<*4H=hTd^GZ&3`Rv=aK9|CD=5gRS_B;~G) z**uw!3D2TPQb5}E?z%gY!T2fJ0>Kuw`=}3$gpbvR0Cp z%E8=FqI#`K%`qe&W%aQTR;ad+E1q=UP`*3VF_gBA=8X@P!dg^T=e}miWJ#H$c+3K$ zcG}iEg8~zOr!O$mrnKuO1O)o{_4BEX5AcCu5a61CW7i~7b{)bnStDfiVU*`%7;oVT zizi!nig=oNP5umVx>08qbFKJ1;|m>lk$9;C$LGs`@CsI~p0!53^;j=8)s<~v)1s|k D_vpE4 literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/SortedMap.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/SortedMap.class new file mode 100644 index 0000000000000000000000000000000000000000..e673c68a3b652df69c30e0a90a26a8992c5791ba GIT binary patch literal 669 zcmZ{i!A^rv5Jm6Q7Fx8m+NyQq!o-9w6xTw!F>!;&1*ZE~#7cvud3~7pYcBi%Kgu|O zQX-hZ;?A8pGsE!t_5K0i6303YbsXs!5ez?mSqUjrED0lXe7g{@!b(&aS=WVQ6FOcv zUka7TfN=6pnsff(+7nLJ*2(NntO&N5^CGdFTlcd?;48ZtDL3_Ese(r?X3Uw%Jbr3@ zC-tUTJN-EjX$fIm)33Ig>8B~Z)-0oy2%`+$ehTGUxxpJ@_`833Ekes2Gm)T2;wRB_ z+^g!k)0)_%nwCehOYi`tnG7#Zq#xXb5#OR$e6Wl3a)iO=fQ3cqXVKEUgzhGh`5J-H y;CG9E5v@sRqQy#M)qu{rjZUEr*4x-AbeDDSkKRSU@b}o?FKcGzsQTp;KGNICpFmc?wrFauwuHwYI(T-2(h4Eq~ zRGvw~=|643#ly^>aGpttjAH9d6_V?L8sB30cy0wnZl(76Cp6U$wYkdP>hQqUdNDO_UglXFJm)hKuX9tyGC z6$mB8Ni(C_)wlQc{qYIl8s{M^$C$2*X^jDrwtB5eDLMF^~E2GE*DEMC_gE3113~QX4`~y&C)O0G^mFPBR~z0{pZZjIeogx3T29ZUBJ>%7oot+S)Na=53cZ{}e4>42+#EAn z6~tHCohYW1bhkWTu&;6CZl=phh0g@e4RXUyJ`gC_o-3&122FNNU^NQo)a_M2cQ2VO zYUURLi!rK0c_?FhOb|HCLJtR%Oh90^j08;NPhj5G(;`qRo7rT$T)=L zY|f}p08h_FWc~-cZpk4o#pKm4p$QqUjoah}*3pq4$oU78lj9t(%JE#pY^8!5UhJ~e z{@~!4EBs;Y(-ahITb0Cp;7;wolUP|@1uF_c*hLS4T1Kz8PH)(pUR44IYJj*EiGq5S zbwRwm?~KarCSYdN%Z$bu?5TzOUuxWYu2TQBn&*?$I~lfmBIiXn5I(g9rqF~F?#XTv zB^q)IXqU6v(CB#87V{m-of~Dv52fXWzRlh{9Jghm?K6gTj^(R^J2QHGA_soDBU^$P zft8V6Gm5Qhr!^GRgG=BCKkh%)bsLt#6=oA0B9Z6Q!*&eH+qsci^GMOa6O_{EtxIkN6*8 x9@)nsJl6O!N+vwfdIhDY3I7r5$57S&6O>Njnbx19^dhBCMH6}nuhgVo{{wBfn}+}Z literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/TreeSet.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/TreeSet.class new file mode 100644 index 0000000000000000000000000000000000000000..f64d855bb9ec360d54317f4aa1ee160703af93cc GIT binary patch literal 1439 zcmaJ>U2oGc6un-zrYqxPtQ#9+D;r-4W6StPw5l{soiqu=Lna=0b5k=sxk;6{L+q#V zzz^U@A+DXowbFq4;Ct@zJ@@+9>F+;3e*wTDymR2C1Fsx-?Z6uc-V&&HdBkOpz`Fb4 zf?iU8BDwH`IFW4lk&ZjwX99}>KaZ%KB#eMxxvhKF?_}kIM(6&g!37Itr>CoHuF}}B z>yG2mm?l)liQdt!=DPc+nrW1(g+O^8M^)7Y*WEMK6-Nu0)WutN>+IA>spDjg8(cCy zD1kNCvm83j^Bn@4l|-gNU_Rwn=o`9lO2FZ1e>9dqH2y-M5yp|EJW2_y=9Ab4dbp)V zheNz37e`XCp0H7TiGmBEU^Kx5@<&3V)0{ODft6|Aj8kN_ z1!ffVM(-`n0y{up4r=(DhXwreX(6hEgV_e6IatJ~4o!^Jdd=jQG`?=|4UKOad<&yx zxNYzXMlD#?I%{x8uj{a(*SokD{WdYWm*=$+CpS!yz;Gb)M(mJG1}%``6z@beFLPj)bSy8I?QoAmC~k2}VE4aB+ac6FCg!8OaItA%AZIc}(=Uu%ZGkMm?0tZUoV zd|Mr-Zy1M?7arp%6*5|Kb8wp^_3pj1j5gf8+ug27GOZ#x=!PBn0^BZ&AO^{%rNPLF zg-T4N5jRGF4zh*Vgg7#84UW}wqkhV$WXlq3a@7pGRxlihh#PvE+&Q*{9`bl$ptuZ> zXVDfS+mkAea%9jKzwPXw;{l9IIgxD*e#YmqYLCLp7IOoATts`$77TraKI!|ujAGSF zhKA9?h)5Ql?snpB4oaOXD5n+lS^4nLddJ04W=v)=N8vM(37SPsM3hZ4&HMfIh}>c! zWl^Wp6LH~GMhtBtH+)1XBTU3--cX4D zxtGYka?ZV6!>!bZ1B=OV?Hs>bfSkCN)6(OKiG&_^6M1C>`^>X|{MXMh)=%;l#jiu| zqmQLS9v?QtK3Z8)VFy<|I2a$DqwKUJBltF>@g&QXu9>r6uB37$=T zm{j_zhp6kysr%89gJWN`tra;73A)*B8HmTjK~F?o-t&=SemnHIzsn=3WveWxLkU{* z8Em_FF~bO%%AMzdIuuHJ=)uEC_BD{->#e-!FB9MB#VX>S(i{^q8Dp*z9Q)y*;dvsC z*Ar)R_nZ38Xs}i(!&*lGzAs-GEu-m9IE*~8B{jjB1o<8Pxv9_|1&rp*r^hrsF=B#G zR9U2Ws!t3_(=wh}g!rTx&(jdmW1}6zsBcWR@oA%Il_u~3E#Pm8isYDmiOK|0_`Xii z3@jD8fPH~3nzaVoEX_fq*GqPtx9jCJasjy)X(^Rog8VXRzg1c`ajSI2uCLIF(Z6cf zt8~reyAIzGlGm_%o!&6|8}z2}zd<+6>RQ>ga+TK7xLe5a7Tr$eJCJK*@?Cm6wZ8-V zyB61bWBT{$gVgUs_m640$IbYx|dD@+0~xjei1r$MWpj{(Mcl zhUYi*ZR+TQtf^`U(3=;y^zWht$JA Rk!OA<>=5=zK%Sue{{WZBR>J@Q literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/WeakHashMap.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/WeakHashMap.class new file mode 100644 index 0000000000000000000000000000000000000000..85846f8f9397c3dadc866042db0a2ca31653379b GIT binary patch literal 989 zcmZ`&T~E|N6ukqxEwCbA@}Yu=B6Quv)i>idn-BwWvl<_ktO-vH&14-I+D$v%1b>zyJLFMMQ7uwM&OCc`h{>Ilc^~?lP)-y_4pUQO)a_ zFzcE3s`vSlPk1}kQnkPEamRr3133!0PGiAn`wqcxo%TDe(_yD;skKD@01IM0My^bb zugChvexKnz5}MILuAq20YJa`B6oKwEGuI--XwHLl6Vi+tK@@5(!=x{uwqB)R^v5am z-&bVs%U3!!j3W#)QwMTKN?~NNxQ-^+)@Frt#;pfR@R-r!zea~#rKoVO#Ld9$dd15f z?PLLAR~vURANE}&oQbJU7;TjpA0wqOEg6O2?EEL?+q1y*M5yD;`(23&Z@*PO<^5yB zHSV_9v~ceCKir?%umbBAw2m$k9rHlr=1kQJ=_1T%VGyNpAWo#hpq9T0e)Wkb-@$of zt{{&2_9hmRCA{E=+28UZLVLt$2G1;hfn~%R)v+?s$)lUcIiT}c&(H!^4SHblMS5uC zlC942E6A_Xn#CW{`m}BXt4%8FY!&JrBmaalzo&WqHtkI7pJBC2&!^v}_ZNlyOZ1j? LuurdSrw4xl1l{OR literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/java/util/jar/JarFile.class b/java/java-tests/testData/psi/repositoryUse/cls/java/util/jar/JarFile.class new file mode 100644 index 0000000000000000000000000000000000000000..0309fce1946bce9ee7d690849d266fa2b5c186a5 GIT binary patch literal 785 zcma)4%T5A85Ujz+BKYK`_>4D5)bWlnA!bQ1E*>x*yqJj@$&hu}EVD-aG!K4&A7$)W z79tA=FWa-#Royk+^ZoPr1>hV<4)z@EGpu>dPP^rH?;bl%&t)jw^u?>-zR*41HKEeI z29d4?dT4|;_ri~476%N=7fLI0$xyD%D(d$PIrr^J21b$6!68Fs4)4Jdw~~Y!@Rssr z!(xRL788qUux+XNo;04&>RApA!)~oUvJ)BQ^S%iAI7ip8)N2vC+Jx^6Cvyy?#bY*! zvn2kf@bG?e8JfBjFAO~K7vE&6Wa5$r z_D4V^a@|1`K1n-8hE?)zPiJ5E!jguLPz-vW+M_lUjyk1a>Ob#=U%$ zeqvSIZ%1LMbm(V@y1=SzwJuH6C1anD?xYT>p<+uqrSDdH>>H9g_J^bDsczx;DWI-Z zk&ZoV3TznaM2|F_A&_THHsLI8_BDPwG~BKLVz7f$0JH zTy`ktwBH`&SSKAaGWE^ik|EhTiuA1tlU~uomcY27n5@7`UtC50sqQA0^+|SI{36SI zX3bu0h|8}ffnsn+!NXw?P|Vf}%_uPeov1bm%w#jFr32(A{cnx}v##y#zqq-lfDNx_ zr6vW5QTBN-CV_d^O~YIaswhKXg#R#L5@Q(U1>`Y~9Pa`iCit7@^BC_1Ud11kGV`Xm uU&b_M+&+tvtjzq^aN_Hft<-;C`~_T+eDlGg}}k%)L1=I zO*7LI-5siHV`3|ft`9(Nw2&zNB(6McbM z!06`kCvOn1X?ug-4Fg3k=hFd{P-X^HP$j(spVKn5f51`-tk0W2Kz;>kBwJOpMY!)I M%%yFoj616%--hI40RR91 literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/pack/Annotation.class b/java/java-tests/testData/psi/repositoryUse/cls/pack/Annotation.class new file mode 100644 index 0000000000000000000000000000000000000000..5acbd9af77035b33420e0635c3bddeb101e52151 GIT binary patch literal 232 zcmX^0Z`VEs1_nb0K6VCfb_O1H23|%6*0RK$(o{wUehp2Zg2d!(ecwvgywY52Mg~F0 zyuAF9#FEVXJeSn8#L}D+Mh0FqHOxV-E{qIZ!TF^{$*FFcIUs`&+Vrv#%MyViU~>_| zj0^%G3H_YJymWp4q^#6rpvm$Gp+va7`Up*Gj0}tnOhC*G^a3LbBLfQqE0D(qzkl{$0Io2K(7{oNUWfr9m}#S%8$##od`0l)U7DawFem z3=e*YA-DZc5`5Qz8K6V`|cfn)U1{RQXLLH+;$ literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/pack/MyClass.class b/java/java-tests/testData/psi/repositoryUse/cls/pack/MyClass.class new file mode 100644 index 0000000000000000000000000000000000000000..c94f833e5db5b494183d5bed48c17f48683a3d17 GIT binary patch literal 955 zcmZWnO>fgc5Pj<=aT?N=evtA}poIcSDRs*Yfj|&Iij>krP%b%boh9Ak*p{5usgXeGlU70hL_o9zR+>>bGBPw>8I08u0lx`U-l{lJzBH;oOMfb`*=t|QFVYKS zIPlKSFO_ee3%EmNE+PxJUGKFPGa6liLNn?sfwi^{)rax$TqPgndBBs6cI3;TD-&)1 zv%`Y9(4@KAj-~(EJDsG&*~y97#OaZ=6O+!yVlOg(_tjUi(G=z4$b~m2$ckFMk(ba4 zjT)$g$fXxL)aIqYQr*%mYoiirB93mS-pIA-=wTeFRu*O9a%U2n3uUxVkT;3$4=AeA ziN=Yq-fOF{n(;rfqpM;UdsW=SF#~yZ9Bw+=vC)C|I!WZDtw&~dnhv}fM4`&2mM`7U zE_n)&rp{+D1JIGzI?J7M5K~oYzqualVTrGZ4+jpeV;L3tD|`|Ts#u}7-zwH<3tU&R z&d3ILuej{f5kF`gY|@qpW0SXNcc(#ILydn-!#3eu^CHfuQ=I##eGGc)b z>201PzFV6^UQdy$)94(T7&o2A)EM+$$oQdEt+YUw<>1tF@IHBJQ@nn{9X z7#uns9J`YY{_~g&u7qyt)g(jUf|Qv^p0KKKb!x*q3evqF~M^~;O*3q3SIP2)i a9f0v(n*7UlT7{bS(y3X09Ft^sVCo+kkn(E) literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/pack/Parametrized.class b/java/java-tests/testData/psi/repositoryUse/cls/pack/Parametrized.class new file mode 100644 index 0000000000000000000000000000000000000000..4dfded0f991cf47f977bd663e006f56ee4afbcb0 GIT binary patch literal 344 zcmZXPPfx-?5XIk=(n>}7W8&Q#dazyqjluPj;7`hxB6Jd6sHbY1Dzo4; z7t&A4jPoTM?ff6~?X!L(TqLiYy~Hy%yj9ld549Q+T64WF*j7f;gVEw4+3-8ZIT!1A znr>8PhvQ>Jh~{NwGWDq4)ZSswTi2isA5HlvWAAl=(va35JSAwE}xck}z&6`iq iPJo9{G!X3cMD$V^B+^1uSJ|h2c{mmCp^dY;p8o>;?@Dt3 literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/pack/Variance.class b/java/java-tests/testData/psi/repositoryUse/cls/pack/Variance.class new file mode 100644 index 0000000000000000000000000000000000000000..5d3693594f6cb93608814a212b6b02f92cabd401 GIT binary patch literal 753 zcma)(%}&BV5XWar0b4;3MO04S0FCIui>*zJi6^2aH1)ic4J?+Htc66MN>3&pd;lNH zIJ>P0A|&=OJ0Ji4c4qeT>-_@&PM~f=26pqXmxp}&K(a|7}*2EKF4TbAy0d`cZ zgMpO { +} diff --git a/java/java-tests/testData/psi/repositoryUse/cls/src/pack/Variance.java b/java/java-tests/testData/psi/repositoryUse/cls/src/pack/Variance.java new file mode 100644 index 000000000000..76eaae73273e --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/cls/src/pack/Variance.java @@ -0,0 +1,12 @@ +package pack; + +import java.util.List; + +/** + * @author dsl + */ +public class Variance { + public Parametrized method() { return null; } + public ParametrizedmethodWithTypeParameter() { return null; }; + public void removeAll(Variance parameter) {} ; +} diff --git a/java/java-tests/testData/psi/repositoryUse/cls/sun/reflect/LangReflectAccess.class b/java/java-tests/testData/psi/repositoryUse/cls/sun/reflect/LangReflectAccess.class new file mode 100644 index 0000000000000000000000000000000000000000..f72ea5c4b06b2e8bdee21dd6611e3a15635f4243 GIT binary patch literal 1429 zcma)+&raJw5XQd=kU)U^p(T`-(25heU=FBiYlNVYkRqi*G*MNFOI@>sM3#+ghqkZQ zLm!|Ig&6N*SZl4A(^xaJzxif&#{cjB{sXX&cNJ_`@RqRXi(jW>;aw8Wcl#6P*0DUt zA6Z?`i6UEb4B~L?k93bp>Ge8VRw%AK;l`Fk+Jq&>e-ZI@!2H|i@Gmr&p+Py!lza`U zE{mwKh;HCVaX5A3AS8S@m6%Y|lV3(7Ck+qABj1Uqp&uv3KY^axcqxcQT= z!~47wkI(V6iP=XP99R$qpKT{@Rkn_B}8` B$ld?| literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/cls/sun/security/util/SecurityConstants.class b/java/java-tests/testData/psi/repositoryUse/cls/sun/security/util/SecurityConstants.class new file mode 100644 index 0000000000000000000000000000000000000000..3ded87f8db75bf10d40be78a4daa20d246d8fd41 GIT binary patch literal 1757 zcmZ`(*>ck`6umCch61Gpy3<10mx9^%&5_mCgJK!WP3V)y1P>UD!z2#NukpYK@KFrc zike6TUUG8o)w!#zU%!9+1b`c`IRTF+;E4stHatdSmoggB*ddX}eKfKU$(O{=lj5B% z%5GM?du+iG(kXgnQk2ak@253*YQb?Srmrd49;$2b%z|m@2&v<$m^FBA!Hl%FLQgyV z!h%`B$x9l=Ar+i8cdMv@Gjb8``;8TWME#+Mj64n@G#F`I3r;G{D4cPE zV&_4~0~$sZ+9e0mZjZt3AuwRtfr_|7|4jOLIMje%EHu@eG8r-ew zine6qx@*O7ZH9b1Fv_0U#5)?81750Z|0{M*;8OpUX;yWK^%)t??71XD-4>(8d6|+o z>Yl%6IJ2@q&OCyf)b8Fq)p4Gqo-86Y?!GW*%DOQed+Uw+B zs(*_Xcn literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/innerClassesScanner/ClassWithGenericParameters.java b/java/java-tests/testData/psi/repositoryUse/innerClassesScanner/ClassWithGenericParameters.java new file mode 100644 index 000000000000..07a3da1828cd --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/innerClassesScanner/ClassWithGenericParameters.java @@ -0,0 +1,6 @@ +class X { + public void method() { + Object o = new Computable() { + } + } +} diff --git a/java/java-tests/testData/psi/repositoryUse/innerClassesScanner/NewInsideNew.java b/java/java-tests/testData/psi/repositoryUse/innerClassesScanner/NewInsideNew.java new file mode 100644 index 000000000000..726b233686d9 --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/innerClassesScanner/NewInsideNew.java @@ -0,0 +1,6 @@ +class X { + public void method() { + Object o = new Computable(new List()) { + } + } +} diff --git a/java/java-tests/testData/psi/repositoryUse/scr17094/classes/a/a/a/a/e/f/i.class b/java/java-tests/testData/psi/repositoryUse/scr17094/classes/a/a/a/a/e/f/i.class new file mode 100644 index 0000000000000000000000000000000000000000..3b64eb80cda2584d7790e365244a0f08c1ce983a GIT binary patch literal 761 zcmZ8f-%ry}6#i~kR<;&4CJ0l3p%~f@c7^anjfpYwMbw8GP4;%%)#c8*B}>QuMFN5G z;2+>0Wjv>2>mW_fIrlr?{mzfvzyI$30C`-2BK& z-gg1>!>}8(h91OU#=paO^i72cA*HtN4OBWFQCx7Dx|54VG79EWO8yEuOsFmr!c4y0 z9*##*{86)HQMdZ)LOEDP#eogSK@}SoJVtyAO$HAw9I#D35M?Yxom zr%S)TF-~LOH|#iz=k`OUT8h=I%v>)DA8PH7^v}T=&jUvPvi^qSFx65 zfCKW3RQ%>OgnxJq!@oh{k|2R6WQ*iEUMFi{iy|9O$=2xno{%N-d;S%S2~2_J1WN|a sOajC$igj}W%fOFZZZ)fBQ2hdRX=ZYp_j2{D1QpBa)9PG*D@)e@1JE~z+W-In literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/scr17094/classes1/com/intellij/util/d/bw.class b/java/java-tests/testData/psi/repositoryUse/scr17094/classes1/com/intellij/util/d/bw.class new file mode 100644 index 0000000000000000000000000000000000000000..46b8238fc620d6c0b8e487ac2fd0d27c07805437 GIT binary patch literal 7667 zcmb_g3s_uNo&TN8ow+b`lMs@DOkfCkmdp@nXiHllv?&dSCJ&&mKw~tGkBx49?7Cg+`&n1leZSmYT@`=-doRpoxYSQS zKR(Vq=br!jedqb#eBvU2E7h7}G~mOsJSEFVWcg^2%g2J)fwOXaT9#*I`M50SbWG@& z48p+KB23BiSy|4@@`)fqxDdoA@u?zQlsC@_&Lth6mgi@*8*T)I{AWYxz~_SaOI()Y z=ZjH}F9h*dcwTm24B<=ovhSYh>1jEBMV7w~;cxJ~0Dm>ejBlDN$1RDI*}c% z-##*Crjog1Eqiu0w-QzLEkt;Px4(nf4s-NiTV^0JORQgE)2@yuiu`|Wi18w^iW4j%R>rf zE~vIlDwXKZB{OL4j`5 zY)VEG*`%53p%=*a_Kus0aEsrsf9unqE!+Q9g+NO(oy@f=Tvg*~!Nbj-uSc3Y+Bfwm zXyOR5BmLYpHq@8M?lJpPd{cDL@sh%;y(ljj93JdkuycKH%h2FOUqaM_)IdEY7s2oJ zLUJ*h8?hdgT(AW~3HdEv_Mze2G3&gKDdKP+wNgYOTw_y8nd!m$-F=6cZOxkq z=Uv34I+V^wPzcSC-I)+pgNdBNMlaG{$VD|2e-q`mgro+(;W6T0=Yc;Tebf9`6h|nM zpiMN8O$=r3qDjg}@svI%p@vPE$F(f-7+)bCLp z|DzD(&A<$LRUvvu+KsK_f30|6^Qrerqk;OqBdkm=ZCrv@EQldVu|WMJy-f>u#RUqK zAbAu!DVwb6E&VB{TRhmZvuS>)_ISK&b*Z$iZ#0)R`*V!M*&KIW&wp*@aa)R!Ctao4 zhNXkLt)`Z|+j>h!bZ5r0{fYLZbRNC$NS$! zgDsU!x4O+7Hv2jDG*uh;Km0i0ZW2#teLaaS< z9TdfBj1d(wR23f8m0_sGYKg9v8ma^*3{{Os6qe`5Bs$4XGD9uHBZeyFg16v71Md*X zGA}{jzHawik<`M%gaIyiG?(`IUWHk+Y!Jt_BdLgk=7qLwcJ z(8tp2jY*#$25Y3JX@`a83SET_RYv=$a<$UH<0_)7RfejNH@sc=If5#E~{1Nt=5(@M@MPg_RLt?ZP9 z)wD~`uHa)~v6ke~JIx$NdEbzElr(BOI;1A9n-hi^YHkiE?K!_KGc;^U+7db;-z5rH zxMg(41{Z7BAmQojkpeAe;3qx(L1sA&`9mEc2 z^*g4)oZjhbFQt|(=X6JwQ4a83iK8SD;QV6^LPgv-gVxJ*BnnaKt)123c)iNv=hvNjbBCyH;dxuv1SoOSIh*Gu5~9cepM_*`G1p?`CqZqF5&xMRu}0a47mXfLR<6vy_SE!qi+HcHWkDB3cLmZfNE)}J%X^gnfi;S`1A zIOn+Qd5Ty}DtC*B7h5brEBptw{jHK`OIe1tNjVsEY)e^hiL23`BI=n6{4&Hx@W}BXf6;X1<%2`T9j&H`L<;zkeOL1JrfcV*67jO+5edBXv3Hc(W@$KSN$Cw4dYjjLFxqdcK#AyOvIg5@QR$$N!waTu1S!{%jGDn1oD$Vv8Y(0Act-Y~| zDcn#Y!Qzz45hI*Q^Yp@-@G+eX-A!sLmgq%09{~_vqBl`0ivh+n`lsCEg5(`}}$L*<)75f_~&{zzgKpM6%pFO=gXF<#}3 zq3zS8d>3N8kr=(R81AuC6@vN+IzC$%*IAb1ynF%etSGPeIJV|}ZW}O65W9-Mh!4`t Ii}0b}0vV7bA^-pY literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/scr17094/classes2/com/intellij/internal/a/b/a/i.class b/java/java-tests/testData/psi/repositoryUse/scr17094/classes2/com/intellij/internal/a/b/a/i.class new file mode 100644 index 0000000000000000000000000000000000000000..26bf433c204a553ece16737160d7a11bdbce53bf GIT binary patch literal 1675 zcmb_dZBNr+6g>}vJ*5=E3CKhx8WTs<6$pyBiQ!#jfHFYK)a2PHqqFN~*J0wH@VA(L zSYi`@fIrH3+nUK2X%qdh?m0K-+=7y;%0~ z3dgF1H5pQf*Eu#MJeQ$_c$4FWge@7vAue!iOW2Vy65?Hsmomn~rLfx=M^K_L?tvgHpUp|h0w_MXJP9V)K zQUk0U-DuP2RT$Rd6u79tQfV`&c})4}hW|spwC#$%ZulT+Wc|Dh zlNWp8lY+OHS8x}ZNbW}lvi(4~$)fRDZ~5YP3hv>4q_|Bjhsr(uM7MRzA@ze8Rc(gB zP`F}>R?9D{#;DhzfdqmbQTH{|F-n;XN+a-TI9LUws1rKA;42I!9jtFl& za=0HN8CE2t8OdlxGU}0x8d)>{+s~t!bKWmHwqaFsQ-?`LuhB_*(@IGDwj|3<5$d50 zrhTW;Iqe=oUgjtJtkSA9<8##yRX~QGTQ{*va`+@{rfszNN zbvVR!97S?s=ou-#efGzOAU5#$;FU|VJ&sJgOrOa9!9j(Xa{31u6h`! yENK_lJWSB(x{DiMDLumiU2juq&__f@AI6X*%#fwX6KY}|^iiMzFhc$ya=!qVrneOU literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/psi/repositoryUse/src/MyClass1.java b/java/java-tests/testData/psi/repositoryUse/src/MyClass1.java new file mode 100644 index 000000000000..9d96a45d6f50 --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src/MyClass1.java @@ -0,0 +1,21 @@ +import a . b; +import c.*; +import + +class MyClass1{ + { + class Local{ + public void foo(){ + new Runnable(runLogName, goldenRunLogName, this){ + public void run(){ + new Throwable(){ + }; + }.run(); + } + } + }; + } +} + +class Class2{ +} diff --git a/java/java-tests/testData/psi/repositoryUse/src/StressClass.java b/java/java-tests/testData/psi/repositoryUse/src/StressClass.java new file mode 100644 index 000000000000..8c1130fd9f1b --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src/StressClass.java @@ -0,0 +1,2789 @@ +/* + * @(#)String.java 1.189 05/10/21 + * + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +import java.io.ObjectStreamClass; +import java.io.ObjectStreamField; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Formatter; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + + +/** + * The String class represents character strings. All + * string literals in Java programs, such as "abc", are + * implemented as instances of this class. + *

+ * Strings are constant; their values cannot be changed after they + * are created. String buffers support mutable strings. + * Because String objects are immutable they can be shared. For example: + *

+ *     String str = "abc";
+ * 

+ * is equivalent to: + *

+ *     char data[] = {'a', 'b', 'c'};
+ *     String str = new String(data);
+ * 

+ * Here are some more examples of how strings can be used: + *

+ *     System.out.println("abc");
+ *     String cde = "cde";
+ *     System.out.println("abc" + cde);
+ *     String c = "abc".substring(2,3);
+ *     String d = cde.substring(1, 2);
+ * 
+ *

+ * The class String includes methods for examining + * individual characters of the sequence, for comparing strings, for + * searching strings, for extracting substrings, and for creating a + * copy of a string with all characters translated to uppercase or to + * lowercase. Case mapping is based on the Unicode Standard version + * specified by the {@link java.lang.Character Character} class. + *

+ * The Java language provides special support for the string + * concatenation operator ( + ), and for conversion of + * other objects to strings. String concatenation is implemented + * through the StringBuilder(or StringBuffer) + * class and its append method. + * String conversions are implemented through the method + * toString, defined by Object and + * inherited by all classes in Java. For additional information on + * string concatenation and conversion, see Gosling, Joy, and Steele, + * The Java Language Specification. + * + *

Unless otherwise noted, passing a null argument to a constructor + * or method in this class will cause a {@link NullPointerException} to be + * thrown. + * + *

A String represents a string in the UTF-16 format + * in which supplementary characters are represented by surrogate + * pairs (see the section Unicode + * Character Representations in the Character class for + * more information). + * Index values refer to char code units, so a supplementary + * character uses two positions in a String. + *

The String class provides methods for dealing with + * Unicode code points (i.e., characters), in addition to those for + * dealing with Unicode code units (i.e., char values). + * + * @author Lee Boynton + * @author Arthur van Hoff + * @version 1.189, 10/21/05 + * @see java.lang.Object#toString() + * @see java.lang.StringBuffer + * @see java.lang.StringBuilder + * @see java.nio.charset.Charset + * @since JDK1.0 + */ + +public final class StressClass + implements java.io.Serializable, Comparable, CharSequence +{ + /** The value is used for character storage. */ + private final char value[]; + + /** The offset is the first index of the storage that is used. */ + private final int offset; + + /** The count is the number of characters in the String. */ + private final int count; + + /** Cache the hash code for the string */ + private int hash; // Default to 0 + + /** use serialVersionUID from JDK 1.0.2 for interoperability */ + private static final long serialVersionUID = -6849794470754667710L; + + /** + * Class String is special cased within the Serialization Stream Protocol. + * + * A String instance is written initially into an ObjectOutputStream in the + * following format: + *

+     *      TC_STRING (utf String)
+     * 
+ * The String is written by method DataOutput.writeUTF. + * A new handle is generated to refer to all future references to the + * string instance within the stream. + */ + private static final ObjectStreamField[] serialPersistentFields = + new ObjectStreamField[0]; + + /** + * Initializes a newly created String object so that it + * represents an empty character sequence. Note that use of this + * constructor is unnecessary since Strings are immutable. + */ + public String() { + this.offset = 0; + this.count = 0; + this.value = new char[0]; + } + + /** + * Initializes a newly created String object so that it + * represents the same sequence of characters as the argument; in other + * words, the newly created string is a copy of the argument string. Unless + * an explicit copy of original is needed, use of this + * constructor is unnecessary since Strings are immutable. + * + * @param original a String. + */ + public String(String original) { + int size = original.count; + char[] originalValue = original.value; + char[] v; + if (originalValue.length > size) { + // The array representing the String is bigger than the new + // String itself. Perhaps this constructor is being called + // in order to trim the baggage, so make a copy of the array. + v = new char[size]; + System.arraycopy(originalValue, original.offset, v, 0, size); + } else { + // The array representing the String is the same + // size as the String, so no point in making a copy. + v = originalValue; + } + this.offset = 0; + this.count = size; + this.value = v; + } + + /** + * Allocates a new String so that it represents the + * sequence of characters currently contained in the character array + * argument. The contents of the character array are copied; subsequent + * modification of the character array does not affect the newly created + * string. + * + * @param value the initial value of the string. + */ + public String(char value[]) { + int size = value.length; + char[] v = new char[size]; + System.arraycopy(value, 0, v, 0, size); + this.offset = 0; + this.count = size; + this.value = v; + } + + /** + * Allocates a new String that contains characters from + * a subarray of the character array argument. The offset + * argument is the index of the first character of the subarray and + * the count argument specifies the length of the + * subarray. The contents of the subarray are copied; subsequent + * modification of the character array does not affect the newly + * created string. + * + * @param value array that is the source of characters. + * @param offset the initial offset. + * @param count the length. + * @exception IndexOutOfBoundsException if the offset + * and count arguments index characters outside + * the bounds of the value array. + */ + public String(char value[], int offset, int count) { + if (offset < 0) { + throw new StringIndexOutOfBoundsException(offset); + } + if (count < 0) { + throw new StringIndexOutOfBoundsException(count); + } + // Note: offset or count might be near -1>>>1. + if (offset > value.length - count) { + throw new StringIndexOutOfBoundsException(offset + count); + } + char[] v = new char[count]; + System.arraycopy(value, offset, v, 0, count); + this.offset = 0; + this.count = count; + this.value = v; + } + + /** + * Allocates a new String that contains characters + * from a subarray of the Unicode code point array argument. The + * offset argument is the index of the first code + * point of the subarray and the count argument + * specifies the length of the subarray. The contents of the + * subarray are converted to chars; subsequent + * modification of the int array does not affect the + * newly created string. + * + * @param codePoints array that is the source of Unicode code points. + * @param offset the initial offset. + * @param count the length. + * @exception IllegalArgumentException if any invalid Unicode code point + * is found in codePoints + * @exception IndexOutOfBoundsException if the offset + * and count arguments index characters outside + * the bounds of the codePoints array. + * @since 1.5 + */ + public String(int[] codePoints, int offset, int count) { + if (offset < 0) { + throw new StringIndexOutOfBoundsException(offset); + } + if (count < 0) { + throw new StringIndexOutOfBoundsException(count); + } + // Note: offset or count might be near -1>>>1. + if (offset > codePoints.length - count) { + throw new StringIndexOutOfBoundsException(offset + count); + } + + int expansion = 0; + int margin = 1; + char[] v = new char[count + margin]; + int x = offset; + int j = 0; + for (int i = 0; i < count; i++) { + int c = codePoints[x++]; + if (c < 0) { + throw new IllegalArgumentException(); + } + if (margin <= 0 && (j+1) >= v.length) { + if (expansion == 0) { + expansion = (((-margin + 1) * count) << 10) / i; + expansion >>= 10; + if (expansion <= 0) { + expansion = 1; + } + } else { + expansion *= 2; + } + char[] tmp = new char[Math.min(v.length+expansion, count*2)]; + margin = (tmp.length - v.length) - (count - i); + System.arraycopy(v, 0, tmp, 0, j); + v = tmp; + } + if (c < Character.MIN_SUPPLEMENTARY_CODE_POINT) { + v[j++] = (char) c; + } else if (c <= Character.MAX_CODE_POINT) { + Character.toSurrogates(c, v, j); + j += 2; + margin--; + } else { + throw new IllegalArgumentException(); + } + } + this.offset = 0; + this.value = v; + this.count = j; + } + + /** + * Allocates a new String constructed from a subarray + * of an array of 8-bit integer values. + *

+ * The offset argument is the index of the first byte + * of the subarray, and the count argument specifies the + * length of the subarray. + *

+ * Each byte in the subarray is converted to a + * char as specified in the method above. + * + * @deprecated This method does not properly convert bytes into characters. + * As of JDK 1.1, the preferred way to do this is via the + * String constructors that take a charset name or that use + * the platform's default charset. + * + * @param ascii the bytes to be converted to characters. + * @param hibyte the top 8 bits of each 16-bit Unicode character. + * @param offset the initial offset. + * @param count the length. + * @exception IndexOutOfBoundsException if the offset + * or count argument is invalid. + * @see java.lang.String#String(byte[], int) + * @see java.lang.String#String(byte[], int, int, java.lang.String) + * @see java.lang.String#String(byte[], int, int) + * @see java.lang.String#String(byte[], java.lang.String) + * @see java.lang.String#String(byte[]) + */ + @Deprecated + public String(byte ascii[], int hibyte, int offset, int count) { + checkBounds(ascii, offset, count); + char value[] = new char[count]; + + if (hibyte == 0) { + for (int i = count ; i-- > 0 ;) { + value[i] = (char) (ascii[i + offset] & 0xff); + } + } else { + hibyte <<= 8; + for (int i = count ; i-- > 0 ;) { + value[i] = (char) (hibyte | (ascii[i + offset] & 0xff)); + } + } + this.offset = 0; + this.count = count; + this.value = value; + } + + /** + * Allocates a new String containing characters + * constructed from an array of 8-bit integer values. Each character + * cin the resulting string is constructed from the + * corresponding component b in the byte array such that: + *

+     *     c == (char)(((hibyte & 0xff) << 8)
+     *                         | (b & 0xff))
+     * 
+ * + * @deprecated This method does not properly convert bytes into characters. + * As of JDK 1.1, the preferred way to do this is via the + * String constructors that take a charset name or + * that use the platform's default charset. + * + * @param ascii the bytes to be converted to characters. + * @param hibyte the top 8 bits of each 16-bit Unicode character. + * @see java.lang.String#String(byte[], int, int, java.lang.String) + * @see java.lang.String#String(byte[], int, int) + * @see java.lang.String#String(byte[], java.lang.String) + * @see java.lang.String#String(byte[]) + */ + @Deprecated + public String(byte ascii[], int hibyte) { + this(ascii, hibyte, 0, ascii.length); + } + + /* Common private utility method used to bounds check the byte array + * and requested offset & length values used by the String(byte[],..) + * constructors. + */ + private static void checkBounds(byte[] bytes, int offset, int length) { + if (length < 0) + throw new StringIndexOutOfBoundsException(length); + if (offset < 0) + throw new StringIndexOutOfBoundsException(offset); + if (offset > bytes.length - length) + throw new StringIndexOutOfBoundsException(offset + length); + } + + /** + * Constructs a new String by decoding the specified subarray of + * bytes using the specified charset. The length of the new + * String is a function of the charset, and hence may not be equal + * to the length of the subarray. + * + *

The behavior of this constructor when the given bytes are not valid + * in the given charset is unspecified. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + * + * @param bytes the bytes to be decoded into characters + * @param offset the index of the first byte to decode + * @param length the number of bytes to decode + * @param charsetName the name of a supported + * {@link java.nio.charset.Charset charset} + * @throws UnsupportedEncodingException + * if the named charset is not supported + * @throws IndexOutOfBoundsException + * if the offset and length arguments + * index characters outside the bounds of the bytes + * array + * @since JDK1.1 + */ + public String(byte bytes[], int offset, int length, String charsetName) + throws UnsupportedEncodingException + { + if (charsetName == null) + throw new NullPointerException("charsetName"); + checkBounds(bytes, offset, length); + char[] v = StringCoding.decode(charsetName, bytes, offset, length); + this.offset = 0; + this.count = v.length; + this.value = v; + } + + /** + * Constructs a new String by decoding the specified array of + * bytes using the specified charset. The length of the new + * String is a function of the charset, and hence may not be equal + * to the length of the byte array. + * + *

The behavior of this constructor when the given bytes are not valid + * in the given charset is unspecified. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + * + * @param bytes the bytes to be decoded into characters + * @param charsetName the name of a supported + * {@link java.nio.charset.Charset charset} + * + * @exception UnsupportedEncodingException + * If the named charset is not supported + * @since JDK1.1 + */ + public String(byte bytes[], String charsetName) + throws UnsupportedEncodingException + { + this(bytes, 0, bytes.length, charsetName); + } + + /** + * Constructs a new String by decoding the specified subarray of + * bytes using the platform's default charset. The length of the new + * String is a function of the charset, and hence may not be equal + * to the length of the subarray. + * + *

The behavior of this constructor when the given bytes are not valid + * in the default charset is unspecified. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + * + * @param bytes the bytes to be decoded into characters + * @param offset the index of the first byte to decode + * @param length the number of bytes to decode + * @throws IndexOutOfBoundsException + * if the offset and the length + * arguments index characters outside the bounds of the + * bytes array + * @since JDK1.1 + */ + public String(byte bytes[], int offset, int length) { + checkBounds(bytes, offset, length); + char[] v = StringCoding.decode(bytes, offset, length); + this.offset = 0; + this.count = v.length; + this.value = v; + } + + /** + * Constructs a new String by decoding the specified array of + * bytes using the platform's default charset. The length of the new + * String is a function of the charset, and hence may not be equal + * to the length of the byte array. + * + *

The behavior of this constructor when the given bytes are not valid + * in the default charset is unspecified. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + * + * @param bytes the bytes to be decoded into characters + * @since JDK1.1 + */ + public String(byte bytes[]) { + this(bytes, 0, bytes.length); + } + + /** + * Allocates a new string that contains the sequence of characters + * currently contained in the string buffer argument. The contents of + * the string buffer are copied; subsequent modification of the string + * buffer does not affect the newly created string. + * + * @param buffer a StringBuffer. + */ + public String(StringBuffer buffer) { + String result = buffer.toString(); + this.value = result.value; + this.count = result.count; + this.offset = result.offset; + } + + /** + * Allocates a new string that contains the sequence of characters + * currently contained in the string builder argument. The contents of + * the string builder are copied; subsequent modification of the string + * builder does not affect the newly created string. + * + *

This constructor is provided to ease migration to + * StringBuilder. Obtaining a string from a string builder + * via the toString method is likely to run faster and is + * generally preferred. + * + * @param builder a StringBuilder + * @since 1.5 + */ + public String(StringBuilder builder) { + String result = builder.toString(); + this.value = result.value; + this.count = result.count; + this.offset = result.offset; + } + + + // Package private constructor which shares value array for speed. + String(int offset, int count, char value[]) { + this.value = value; + this.offset = offset; + this.count = count; + } + + /** + * Returns the length of this string. + * The length is equal to the number of 16-bit + * Unicode characters in the string. + * + * @return the length of the sequence of characters represented by this + * object. + */ + public int length() { + return count; + } + + /** + * Returns the char value at the + * specified index. An index ranges from 0 to + * length() - 1. The first char value of the sequence + * is at index 0, the next at index 1, + * and so on, as for array indexing. + * + *

If the char value specified by the index is a + * surrogate, the surrogate + * value is returned. + * + * @param index the index of the char value. + * @return the char value at the specified index of this string. + * The first char value is at index 0. + * @exception IndexOutOfBoundsException if the index + * argument is negative or not less than the length of this + * string. + */ + public char charAt(int index) { + if ((index < 0) || (index >= count)) { + throw new StringIndexOutOfBoundsException(index); + } + return value[index + offset]; + } + + /** + * Returns the character (Unicode code point) at the specified + * index. The index refers to char values + * (Unicode code units) and ranges from 0 to + * {@link #length()} - 1. + * + *

If the char value specified at the given index + * is in the high-surrogate range, the following index is less + * than the length of this String, and the + * char value at the following index is in the + * low-surrogate range, then the supplementary code point + * corresponding to this surrogate pair is returned. Otherwise, + * the char value at the given index is returned. + * + * @param index the index to the char values + * @return the code point value of the character at the + * index + * @exception IndexOutOfBoundsException if the index + * argument is negative or not less than the length of this + * string. + * @since 1.5 + */ + public int codePointAt(int index) { + if ((index < 0) || (index >= count)) { + throw new StringIndexOutOfBoundsException(index); + } + return Character.codePointAtImpl(value, offset + index, offset + count); + } + + /** + * Returns the character (Unicode code point) before the specified + * index. The index refers to char values + * (Unicode code units) and ranges from 1 to {@link + * CharSequence#length() length}. + * + *

If the char value at (index - 1) + * is in the low-surrogate range, (index - 2) is not + * negative, and the char value at (index - + * 2) is in the high-surrogate range, then the + * supplementary code point value of the surrogate pair is + * returned. If the char value at index - + * 1 is an unpaired low-surrogate or a high-surrogate, the + * surrogate value is returned. + * + * @param index the index following the code point that should be returned + * @return the Unicode code point value before the given index. + * @exception IndexOutOfBoundsException if the index + * argument is less than 1 or greater than the length + * of this string. + * @since 1.5 + */ + public int codePointBefore(int index) { + int i = index - 1; + if ((i < 0) || (i >= count)) { + throw new StringIndexOutOfBoundsException(index); + } + return Character.codePointBeforeImpl(value, offset + index, offset); + } + + /** + * Returns the number of Unicode code points in the specified text + * range of this String. The text range begins at the + * specified beginIndex and extends to the + * char at index endIndex - 1. Thus the + * length (in chars) of the text range is + * endIndex-beginIndex. Unpaired surrogates within + * the text range count as one code point each. + * + * @param beginIndex the index to the first char of + * the text range. + * @param endIndex the index after the last char of + * the text range. + * @return the number of Unicode code points in the specified text + * range + * @exception IndexOutOfBoundsException if the + * beginIndex is negative, or endIndex + * is larger than the length of this String, or + * beginIndex is larger than endIndex. + * @since 1.5 + */ + public int codePointCount(int beginIndex, int endIndex) { + if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) { + throw new IndexOutOfBoundsException(); + } + return Character.codePointCountImpl(value, offset+beginIndex, endIndex-beginIndex); + } + + /** + * Returns the index within this String that is + * offset from the given index by + * codePointOffset code points. Unpaired surrogates + * within the text range given by index and + * codePointOffset count as one code point each. + * + * @param index the index to be offset + * @param codePointOffset the offset in code points + * @return the index within this String + * @exception IndexOutOfBoundsException if index + * is negative or larger then the length of this + * String, or if codePointOffset is positive + * and the substring starting with index has fewer + * than codePointOffset code points, + * or if codePointOffset is negative and the substring + * before index has fewer than the absolute value + * of codePointOffset code points. + * @since 1.5 + */ + public int offsetByCodePoints(int index, int codePointOffset) { + if (index < 0 || index > count) { + throw new IndexOutOfBoundsException(); + } + return Character.offsetByCodePointsImpl(value, offset, count, + offset+index, codePointOffset); + } + + /** + * Copy characters from this string into dst starting at dstBegin. + * This method doesn't perform any range checking. + */ + void getChars(char dst[], int dstBegin) { + System.arraycopy(value, offset, dst, dstBegin, count); + } + + /** + * Copies characters from this string into the destination character + * array. + *

+ * The first character to be copied is at index srcBegin; + * the last character to be copied is at index srcEnd-1 + * (thus the total number of characters to be copied is + * srcEnd-srcBegin). The characters are copied into the + * subarray of dst starting at index dstBegin + * and ending at index: + *

+     *     dstbegin + (srcEnd-srcBegin) - 1
+     * 
+ * + * @param srcBegin index of the first character in the string + * to copy. + * @param srcEnd index after the last character in the string + * to copy. + * @param dst the destination array. + * @param dstBegin the start offset in the destination array. + * @exception IndexOutOfBoundsException If any of the following + * is true: + *
  • srcBegin is negative. + *
  • srcBegin is greater than srcEnd + *
  • srcEnd is greater than the length of this + * string + *
  • dstBegin is negative + *
  • dstBegin+(srcEnd-srcBegin) is larger than + * dst.length
+ */ + public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { + if (srcBegin < 0) { + throw new StringIndexOutOfBoundsException(srcBegin); + } + if (srcEnd > count) { + throw new StringIndexOutOfBoundsException(srcEnd); + } + if (srcBegin > srcEnd) { + throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); + } + System.arraycopy(value, offset + srcBegin, dst, dstBegin, + srcEnd - srcBegin); + } + + /** + * Copies characters from this string into the destination byte + * array. Each byte receives the 8 low-order bits of the + * corresponding character. The eight high-order bits of each character + * are not copied and do not participate in the transfer in any way. + *

+ * The first character to be copied is at index srcBegin; + * the last character to be copied is at index srcEnd-1. + * The total number of characters to be copied is + * srcEnd-srcBegin. The characters, converted to bytes, + * are copied into the subarray of dst starting at index + * dstBegin and ending at index: + *

+     *     dstbegin + (srcEnd-srcBegin) - 1
+     * 
+ * + * @deprecated This method does not properly convert characters into bytes. + * As of JDK 1.1, the preferred way to do this is via the + * getBytes() method, which uses the platform's default + * charset. + * + * @param srcBegin index of the first character in the string + * to copy. + * @param srcEnd index after the last character in the string + * to copy. + * @param dst the destination array. + * @param dstBegin the start offset in the destination array. + * @exception IndexOutOfBoundsException if any of the following + * is true: + *
  • srcBegin is negative + *
  • srcBegin is greater than srcEnd + *
  • srcEnd is greater than the length of this + * String + *
  • dstBegin is negative + *
  • dstBegin+(srcEnd-srcBegin) is larger than + * dst.length
+ */ + @Deprecated + public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) { + if (srcBegin < 0) { + throw new StringIndexOutOfBoundsException(srcBegin); + } + if (srcEnd > count) { + throw new StringIndexOutOfBoundsException(srcEnd); + } + if (srcBegin > srcEnd) { + throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); + } + int j = dstBegin; + int n = offset + srcEnd; + int i = offset + srcBegin; + char[] val = value; /* avoid getfield opcode */ + + while (i < n) { + dst[j++] = (byte)val[i++]; + } + } + + /** + * Encodes this String into a sequence of bytes using the + * named charset, storing the result into a new byte array. + * + *

The behavior of this method when this string cannot be encoded in + * the given charset is unspecified. The {@link + * java.nio.charset.CharsetEncoder} class should be used when more control + * over the encoding process is required. + * + * @param charsetName + * the name of a supported + * {@link java.nio.charset.Charset charset} + * + * @return The resultant byte array + * + * @exception UnsupportedEncodingException + * If the named charset is not supported + * + * @since JDK1.1 + */ + public byte[] getBytes(String charsetName) + throws UnsupportedEncodingException + { + if (charsetName == null) throw new NullPointerException(); + return StringCoding.encode(charsetName, value, offset, count); + } + + /** + * Encodes this String into a sequence of bytes using the + * platform's default charset, storing the result into a new byte array. + * + *

The behavior of this method when this string cannot be encoded in + * the default charset is unspecified. The {@link + * java.nio.charset.CharsetEncoder} class should be used when more control + * over the encoding process is required. + * + * @return The resultant byte array + * + * @since JDK1.1 + */ + public byte[] getBytes() { + return StringCoding.encode(value, offset, count); + } + + /** + * Compares this string to the specified object. + * The result is true if and only if the argument is not + * null and is a String object that represents + * the same sequence of characters as this object. + * + * @param anObject the object to compare this String + * against. + * @return true if the String are equal; + * false otherwise. + * @see java.lang.String#compareTo(java.lang.String) + * @see java.lang.String#equalsIgnoreCase(java.lang.String) + */ + public boolean equals(Object anObject) { + if (this == anObject) { + return true; + } + if (anObject instanceof String) { + String anotherString = (String)anObject; + int n = count; + if (n == anotherString.count) { + char v1[] = value; + char v2[] = anotherString.value; + int i = offset; + int j = anotherString.offset; + while (n-- != 0) { + if (v1[i++] != v2[j++]) + return false; + } + return true; + } + } + return false; + } + + /** + * Returns true if and only if this String represents + * the same sequence of characters as the specified StringBuffer. + * + * @param sb the StringBuffer to compare to. + * @return true if and only if this String represents + * the same sequence of characters as the specified + * StringBuffer, otherwise false. + * @throws NullPointerException if sb is null + * @since 1.4 + */ + public boolean contentEquals(StringBuffer sb) { + synchronized(sb) { + return contentEquals((CharSequence)sb); + } + } + + /** + * Returns true if and only if this String represents + * the same sequence of char values as the specified sequence. + * + * @param cs the sequence to compare to. + * @return true if and only if this String represents + * the same sequence of char values as the specified + * sequence, otherwise false. + * @throws NullPointerException if cs is null + * @since 1.5 + */ + public boolean contentEquals(CharSequence cs) { + if (count != cs.length()) + return false; + // Argument is a StringBuffer, StringBuilder + if (cs instanceof AbstractStringBuilder) { + char v1[] = value; + char v2[] = ((AbstractStringBuilder)cs).getValue(); + int i = offset; + int j = 0; + int n = count; + while (n-- != 0) { + if (v1[i++] != v2[j++]) + return false; + } + } + // Argument is a String + if (cs.equals(this)) + return true; + // Argument is a generic CharSequence + char v1[] = value; + int i = offset; + int j = 0; + int n = count; + while (n-- != 0) { + if (v1[i++] != cs.charAt(j++)) + return false; + } + return true; + } + + /** + * Compares this String to another String, + * ignoring case considerations. Two strings are considered equal + * ignoring case if they are of the same length, and corresponding + * characters in the two strings are equal ignoring case. + *

+ * Two characters c1 and c2 are considered + * the same, ignoring case if at least one of the following is true: + *

  • The two characters are the same (as compared by the + * == operator). + *
  • Applying the method {@link java.lang.Character#toUpperCase(char)} + * to each character produces the same result. + *
  • Applying the method {@link java.lang.Character#toLowerCase(char)} + * to each character produces the same result.
+ * + * @param anotherString the String to compare this + * String against. + * @return true if the argument is not null + * and the Strings are equal, + * ignoring case; false otherwise. + * @see #equals(Object) + * @see java.lang.Character#toLowerCase(char) + * @see java.lang.Character#toUpperCase(char) + */ + public boolean equalsIgnoreCase(String anotherString) { + return (this == anotherString) ? true : + (anotherString != null) && (anotherString.count == count) && + regionMatches(true, 0, anotherString, 0, count); + } + + /** + * Compares two strings lexicographically. + * The comparison is based on the Unicode value of each character in + * the strings. The character sequence represented by this + * String object is compared lexicographically to the + * character sequence represented by the argument string. The result is + * a negative integer if this String object + * lexicographically precedes the argument string. The result is a + * positive integer if this String object lexicographically + * follows the argument string. The result is zero if the strings + * are equal; compareTo returns 0 exactly when + * the {@link #equals(Object)} method would return true. + *

+ * This is the definition of lexicographic ordering. If two strings are + * different, then either they have different characters at some index + * that is a valid index for both strings, or their lengths are different, + * or both. If they have different characters at one or more index + * positions, let k be the smallest such index; then the string + * whose character at position k has the smaller value, as + * determined by using the < operator, lexicographically precedes the + * other string. In this case, compareTo returns the + * difference of the two character values at position k in + * the two string -- that is, the value: + *

+     * this.charAt(k)-anotherString.charAt(k)
+     * 
+ * If there is no index position at which they differ, then the shorter + * string lexicographically precedes the longer string. In this case, + * compareTo returns the difference of the lengths of the + * strings -- that is, the value: + *
+     * this.length()-anotherString.length()
+     * 
+ * + * @param anotherString the String to be compared. + * @return the value 0 if the argument string is equal to + * this string; a value less than 0 if this string + * is lexicographically less than the string argument; and a + * value greater than 0 if this string is + * lexicographically greater than the string argument. + */ + public int compareTo(String anotherString) { + int len1 = count; + int len2 = anotherString.count; + int n = Math.min(len1, len2); + char v1[] = value; + char v2[] = anotherString.value; + int i = offset; + int j = anotherString.offset; + + if (i == j) { + int k = i; + int lim = n + i; + while (k < lim) { + char c1 = v1[k]; + char c2 = v2[k]; + if (c1 != c2) { + return c1 - c2; + } + k++; + } + } else { + while (n-- != 0) { + char c1 = v1[i++]; + char c2 = v2[j++]; + if (c1 != c2) { + return c1 - c2; + } + } + } + return len1 - len2; + } + + /** + * A Comparator that orders String objects as by + * compareToIgnoreCase. This comparator is serializable. + *

+ * Note that this Comparator does not take locale into account, + * and will result in an unsatisfactory ordering for certain locales. + * The java.text package provides Collators to allow + * locale-sensitive ordering. + * + * @see java.text.Collator#compare(String, String) + * @since 1.2 + */ + public static final Comparator CASE_INSENSITIVE_ORDER + = new CaseInsensitiveComparator(); + private static class CaseInsensitiveComparator + implements Comparator, java.io.Serializable { + // use serialVersionUID from JDK 1.2.2 for interoperability + private static final long serialVersionUID = 8575799808933029326L; + + public int compare(String s1, String s2) { + int n1=s1.length(), n2=s2.length(); + for (int i1=0, i2=0; i1compareTo with normalized versions of the strings + * where case differences have been eliminated by calling + * Character.toLowerCase(Character.toUpperCase(character)) on + * each character. + *

+ * Note that this method does not take locale into account, + * and will result in an unsatisfactory ordering for certain locales. + * The java.text package provides collators to allow + * locale-sensitive ordering. + * + * @param str the String to be compared. + * @return a negative integer, zero, or a positive integer as the + * specified String is greater than, equal to, or less + * than this String, ignoring case considerations. + * @see java.text.Collator#compare(String, String) + * @since 1.2 + */ + public int compareToIgnoreCase(String str) { + return CASE_INSENSITIVE_ORDER.compare(this, str); + } + + /** + * Tests if two string regions are equal. + *

+ * A substring of this String object is compared to a substring + * of the argument other. The result is true if these substrings + * represent identical character sequences. The substring of this + * String object to be compared begins at index toffset + * and has length len. The substring of other to be compared + * begins at index ooffset and has length len. The + * result is false if and only if at least one of the following + * is true: + *

  • toffset is negative. + *
  • ooffset is negative. + *
  • toffset+len is greater than the length of this + * String object. + *
  • ooffset+len is greater than the length of the other + * argument. + *
  • There is some nonnegative integer k less than len + * such that: + * this.charAt(toffset+k) != other.charAt(ooffset+k) + *
+ * + * @param toffset the starting offset of the subregion in this string. + * @param other the string argument. + * @param ooffset the starting offset of the subregion in the string + * argument. + * @param len the number of characters to compare. + * @return true if the specified subregion of this string + * exactly matches the specified subregion of the string argument; + * false otherwise. + */ + public boolean regionMatches(int toffset, String other, int ooffset, + int len) { + char ta[] = value; + int to = offset + toffset; + char pa[] = other.value; + int po = other.offset + ooffset; + // Note: toffset, ooffset, or len might be near -1>>>1. + if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len) + || (ooffset > (long)other.count - len)) { + return false; + } + while (len-- > 0) { + if (ta[to++] != pa[po++]) { + return false; + } + } + return true; + } + + /** + * Tests if two string regions are equal. + *

+ * A substring of this String object is compared to a substring + * of the argument other. The result is true if these + * substrings represent character sequences that are the same, ignoring + * case if and only if ignoreCase is true. The substring of + * this String object to be compared begins at index + * toffset and has length len. The substring of + * other to be compared begins at index ooffset and + * has length len. The result is false if and only if + * at least one of the following is true: + *

  • toffset is negative. + *
  • ooffset is negative. + *
  • toffset+len is greater than the length of this + * String object. + *
  • ooffset+len is greater than the length of the other + * argument. + *
  • ignoreCase is false and there is some nonnegative + * integer k less than len such that: + *
    +     * this.charAt(toffset+k) != other.charAt(ooffset+k)
    +     * 
    + *
  • ignoreCase is true and there is some nonnegative + * integer k less than len such that: + *
    +     * Character.toLowerCase(this.charAt(toffset+k)) !=
    +               Character.toLowerCase(other.charAt(ooffset+k))
    +     * 
    + * and: + *
    +     * Character.toUpperCase(this.charAt(toffset+k)) !=
    +     *         Character.toUpperCase(other.charAt(ooffset+k))
    +     * 
    + *
+ * + * @param ignoreCase if true, ignore case when comparing + * characters. + * @param toffset the starting offset of the subregion in this + * string. + * @param other the string argument. + * @param ooffset the starting offset of the subregion in the string + * argument. + * @param len the number of characters to compare. + * @return true if the specified subregion of this string + * matches the specified subregion of the string argument; + * false otherwise. Whether the matching is exact + * or case insensitive depends on the ignoreCase + * argument. + */ + public boolean regionMatches(boolean ignoreCase, int toffset, + String other, int ooffset, int len) { + char ta[] = value; + int to = offset + toffset; + char pa[] = other.value; + int po = other.offset + ooffset; + // Note: toffset, ooffset, or len might be near -1>>>1. + if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len) || + (ooffset > (long)other.count - len)) { + return false; + } + while (len-- > 0) { + char c1 = ta[to++]; + char c2 = pa[po++]; + if (c1 == c2) { + continue; + } + if (ignoreCase) { + // If characters don't match but case may be ignored, + // try converting both characters to uppercase. + // If the results match, then the comparison scan should + // continue. + char u1 = Character.toUpperCase(c1); + char u2 = Character.toUpperCase(c2); + if (u1 == u2) { + continue; + } + // Unfortunately, conversion to uppercase does not work properly + // for the Georgian alphabet, which has strange rules about case + // conversion. So we need to make one last check before + // exiting. + if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { + continue; + } + } + return false; + } + return true; + } + + /** + * Tests if this string starts with the specified prefix beginning + * a specified index. + * + * @param prefix the prefix. + * @param toffset where to begin looking in the string. + * @return true if the character sequence represented by the + * argument is a prefix of the substring of this object starting + * at index toffset; false otherwise. + * The result is false if toffset is + * negative or greater than the length of this + * String object; otherwise the result is the same + * as the result of the expression + *
+     *          this.substring(toffset).startsWith(prefix)
+     *          
+ */ + public boolean startsWith(String prefix, int toffset) { + char ta[] = value; + int to = offset + toffset; + char pa[] = prefix.value; + int po = prefix.offset; + int pc = prefix.count; + // Note: toffset might be near -1>>>1. + if ((toffset < 0) || (toffset > count - pc)) { + return false; + } + while (--pc >= 0) { + if (ta[to++] != pa[po++]) { + return false; + } + } + return true; + } + + /** + * Tests if this string starts with the specified prefix. + * + * @param prefix the prefix. + * @return true if the character sequence represented by the + * argument is a prefix of the character sequence represented by + * this string; false otherwise. + * Note also that true will be returned if the + * argument is an empty string or is equal to this + * String object as determined by the + * {@link #equals(Object)} method. + * @since 1. 0 + */ + public boolean startsWith(String prefix) { + return startsWith(prefix, 0); + } + + /** + * Tests if this string ends with the specified suffix. + * + * @param suffix the suffix. + * @return true if the character sequence represented by the + * argument is a suffix of the character sequence represented by + * this object; false otherwise. Note that the + * result will be true if the argument is the + * empty string or is equal to this String object + * as determined by the {@link #equals(Object)} method. + */ + public boolean endsWith(String suffix) { + return startsWith(suffix, count - suffix.count); + } + + /** + * Returns a hash code for this string. The hash code for a + * String object is computed as + *
+     * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
+     * 
+ * using int arithmetic, where s[i] is the + * ith character of the string, n is the length of + * the string, and ^ indicates exponentiation. + * (The hash value of the empty string is zero.) + * + * @return a hash code value for this object. + */ + public int hashCode() { + int h = hash; + if (h == 0) { + int off = offset; + char val[] = value; + int len = count; + + for (int i = 0; i < len; i++) { + h = 31*h + val[off++]; + } + hash = h; + } + return h; + } + + /** + * Returns the index within this string of the first occurrence of + * the specified character. If a character with value + * ch occurs in the character sequence represented by + * this String object, then the index (in Unicode + * code units) of the first such occurrence is returned. For + * values of ch in the range from 0 to 0xFFFF + * (inclusive), this is the smallest value k such that: + *
+     * this.charAt(k) == ch
+     * 
+ * is true. For other values of ch, it is the + * smallest value k such that: + *
+     * this.codePointAt(k) == ch
+     * 
+ * is true. In either case, if no such character occurs in this + * string, then -1 is returned. + * + * @param ch a character (Unicode code point). + * @return the index of the first occurrence of the character in the + * character sequence represented by this object, or + * -1 if the character does not occur. + */ + public int indexOf(int ch) { + return indexOf(ch, 0); + } + + /** + * Returns the index within this string of the first occurrence of the + * specified character, starting the search at the specified index. + *

+ * If a character with value ch occurs in the + * character sequence represented by this String + * object at an index no smaller than fromIndex, then + * the index of the first such occurrence is returned. For values + * of ch in the range from 0 to 0xFFFF (inclusive), + * this is the smallest value k such that: + *

+     * (this.charAt(k) == ch) && (k >= fromIndex)
+     * 
+ * is true. For other values of ch, it is the + * smallest value k such that: + *
+     * (this.codePointAt(k) == ch) && (k >= fromIndex)
+     * 
+ * is true. In either case, if no such character occurs in this + * string at or after position fromIndex, then + * -1 is returned. + * + *

+ * There is no restriction on the value of fromIndex. If it + * is negative, it has the same effect as if it were zero: this entire + * string may be searched. If it is greater than the length of this + * string, it has the same effect as if it were equal to the length of + * this string: -1 is returned. + * + *

All indices are specified in char values + * (Unicode code units). + * + * @param ch a character (Unicode code point). + * @param fromIndex the index to start the search from. + * @return the index of the first occurrence of the character in the + * character sequence represented by this object that is greater + * than or equal to fromIndex, or -1 + * if the character does not occur. + */ + public int indexOf(int ch, int fromIndex) { + int max = offset + count; + char v[] = value; + + if (fromIndex < 0) { + fromIndex = 0; + } else if (fromIndex >= count) { + // Note: fromIndex might be near -1>>>1. + return -1; + } + + int i = offset + fromIndex; + if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { + // handle most cases here (ch is a BMP code point or a + // negative value (invalid code point)) + for (; i < max ; i++) { + if (v[i] == ch) { + return i - offset; + } + } + return -1; + } + + if (ch <= Character.MAX_CODE_POINT) { + // handle supplementary characters here + char[] surrogates = Character.toChars(ch); + for (; i < max; i++) { + if (v[i] == surrogates[0]) { + if (i + 1 == max) { + break; + } + if (v[i+1] == surrogates[1]) { + return i - offset; + } + } + } + } + return -1; + } + + /** + * Returns the index within this string of the last occurrence of + * the specified character. For values of ch in the + * range from 0 to 0xFFFF (inclusive), the index (in Unicode code + * units) returned is the largest value k such that: + *

+     * this.charAt(k) == ch
+     * 
+ * is true. For other values of ch, it is the + * largest value k such that: + *
+     * this.codePointAt(k) == ch
+     * 
+ * is true. In either case, if no such character occurs in this + * string, then -1 is returned. The + * String is searched backwards starting at the last + * character. + * + * @param ch a character (Unicode code point). + * @return the index of the last occurrence of the character in the + * character sequence represented by this object, or + * -1 if the character does not occur. + */ + public int lastIndexOf(int ch) { + return lastIndexOf(ch, count - 1); + } + + /** + * Returns the index within this string of the last occurrence of + * the specified character, searching backward starting at the + * specified index. For values of ch in the range + * from 0 to 0xFFFF (inclusive), the index returned is the largest + * value k such that: + *
+     * (this.charAt(k) == ch) && (k <= fromIndex)
+     * 
+ * is true. For other values of ch, it is the + * largest value k such that: + *
+     * (this.codePointAt(k) == ch) && (k <= fromIndex)
+     * 
+ * is true. In either case, if no such character occurs in this + * string at or before position fromIndex, then + * -1 is returned. + * + *

All indices are specified in char values + * (Unicode code units). + * + * @param ch a character (Unicode code point). + * @param fromIndex the index to start the search from. There is no + * restriction on the value of fromIndex. If it is + * greater than or equal to the length of this string, it has + * the same effect as if it were equal to one less than the + * length of this string: this entire string may be searched. + * If it is negative, it has the same effect as if it were -1: + * -1 is returned. + * @return the index of the last occurrence of the character in the + * character sequence represented by this object that is less + * than or equal to fromIndex, or -1 + * if the character does not occur before that point. + */ + public int lastIndexOf(int ch, int fromIndex) { + int min = offset; + char v[] = value; + + int i = offset + ((fromIndex >= count) ? count - 1 : fromIndex); + + if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { + // handle most cases here (ch is a BMP code point or a + // negative value (invalid code point)) + for (; i >= min ; i--) { + if (v[i] == ch) { + return i - offset; + } + } + return -1; + } + + int max = offset + count; + if (ch <= Character.MAX_CODE_POINT) { + // handle supplementary characters here + char[] surrogates = Character.toChars(ch); + for (; i >= min; i--) { + if (v[i] == surrogates[0]) { + if (i + 1 == max) { + break; + } + if (v[i+1] == surrogates[1]) { + return i - offset; + } + } + } + } + return -1; + } + + /** + * Returns the index within this string of the first occurrence of the + * specified substring. The integer returned is the smallest value + * k such that: + *

+     * this.startsWith(str, k)
+     * 
+ * is true. + * + * @param str any string. + * @return if the string argument occurs as a substring within this + * object, then the index of the first character of the first + * such substring is returned; if it does not occur as a + * substring, -1 is returned. + */ + public int indexOf(String str) { + return indexOf(str, 0); + } + + /** + * Returns the index within this string of the first occurrence of the + * specified substring, starting at the specified index. The integer + * returned is the smallest value k for which: + *
+     *     k >= Math.min(fromIndex, str.length()) && this.startsWith(str, k)
+     * 
+ * If no such value of k exists, then -1 is returned. + * + * @param str the substring for which to search. + * @param fromIndex the index from which to start the search. + * @return the index within this string of the first occurrence of the + * specified substring, starting at the specified index. + */ + public int indexOf(String str, int fromIndex) { + return indexOf(value, offset, count, + str.value, str.offset, str.count, fromIndex); + } + + /** + * Code shared by String and StringBuffer to do searches. The + * source is the character array being searched, and the target + * is the string being searched for. + * + * @param source the characters being searched. + * @param sourceOffset offset of the source string. + * @param sourceCount count of the source string. + * @param target the characters being searched for. + * @param targetOffset offset of the target string. + * @param targetCount count of the target string. + * @param fromIndex the index to begin searching from. + */ + static int indexOf(char[] source, int sourceOffset, int sourceCount, + char[] target, int targetOffset, int targetCount, + int fromIndex) { + if (fromIndex >= sourceCount) { + return (targetCount == 0 ? sourceCount : -1); + } + if (fromIndex < 0) { + fromIndex = 0; + } + if (targetCount == 0) { + return fromIndex; + } + + char first = target[targetOffset]; + int max = sourceOffset + (sourceCount - targetCount); + + for (int i = sourceOffset + fromIndex; i <= max; i++) { + /* Look for first character. */ + if (source[i] != first) { + while (++i <= max && source[i] != first); + } + + /* Found first character, now look at the rest of v2 */ + if (i <= max) { + int j = i + 1; + int end = j + targetCount - 1; + for (int k = targetOffset + 1; j < end && source[j] == + target[k]; j++, k++); + + if (j == end) { + /* Found whole string. */ + return i - sourceOffset; + } + } + } + return -1; + } + + /** + * Returns the index within this string of the rightmost occurrence + * of the specified substring. The rightmost empty string "" is + * considered to occur at the index value this.length(). + * The returned index is the largest value k such that + *
+     * this.startsWith(str, k)
+     * 
+ * is true. + * + * @param str the substring to search for. + * @return if the string argument occurs one or more times as a substring + * within this object, then the index of the first character of + * the last such substring is returned. If it does not occur as + * a substring, -1 is returned. + */ + public int lastIndexOf(String str) { + return lastIndexOf(str, count); + } + + /** + * Returns the index within this string of the last occurrence of the + * specified substring, searching backward starting at the specified index. + * The integer returned is the largest value k such that: + *
+     *     k <= Math.min(fromIndex, str.length()) && this.startsWith(str, k)
+     * 
+ * If no such value of k exists, then -1 is returned. + * + * @param str the substring to search for. + * @param fromIndex the index to start the search from. + * @return the index within this string of the last occurrence of the + * specified substring. + */ + public int lastIndexOf(String str, int fromIndex) { + return lastIndexOf(value, offset, count, + str.value, str.offset, str.count, fromIndex); + } + + /** + * Code shared by String and StringBuffer to do searches. The + * source is the character array being searched, and the target + * is the string being searched for. + * + * @param source the characters being searched. + * @param sourceOffset offset of the source string. + * @param sourceCount count of the source string. + * @param target the characters being searched for. + * @param targetOffset offset of the target string. + * @param targetCount count of the target string. + * @param fromIndex the index to begin searching from. + */ + static int lastIndexOf(char[] source, int sourceOffset, int sourceCount, + char[] target, int targetOffset, int targetCount, + int fromIndex) { + /* + * Check arguments; return immediately where possible. For + * consistency, don't check for null str. + */ + int rightIndex = sourceCount - targetCount; + if (fromIndex < 0) { + return -1; + } + if (fromIndex > rightIndex) { + fromIndex = rightIndex; + } + /* Empty string always matches. */ + if (targetCount == 0) { + return fromIndex; + } + + int strLastIndex = targetOffset + targetCount - 1; + char strLastChar = target[strLastIndex]; + int min = sourceOffset + targetCount - 1; + int i = min + fromIndex; + + startSearchForLastChar: + while (true) { + while (i >= min && source[i] != strLastChar) { + i--; + } + if (i < min) { + return -1; + } + int j = i - 1; + int start = j - (targetCount - 1); + int k = strLastIndex - 1; + + while (j > start) { + if (source[j--] != target[k--]) { + i--; + continue startSearchForLastChar; + } + } + return start - sourceOffset + 1; + } + } + + /** + * Returns a new string that is a substring of this string. The + * substring begins with the character at the specified index and + * extends to the end of this string.

+ * Examples: + *

+     * "unhappy".substring(2) returns "happy"
+     * "Harbison".substring(3) returns "bison"
+     * "emptiness".substring(9) returns "" (an empty string)
+     * 
+ * + * @param beginIndex the beginning index, inclusive. + * @return the specified substring. + * @exception IndexOutOfBoundsException if + * beginIndex is negative or larger than the + * length of this String object. + */ + public String substring(int beginIndex) { + return substring(beginIndex, count); + } + + /** + * Returns a new string that is a substring of this string. The + * substring begins at the specified beginIndex and + * extends to the character at index endIndex - 1. + * Thus the length of the substring is endIndex-beginIndex. + *

+ * Examples: + *

+     * "hamburger".substring(4, 8) returns "urge"
+     * "smiles".substring(1, 5) returns "mile"
+     * 
+ * + * @param beginIndex the beginning index, inclusive. + * @param endIndex the ending index, exclusive. + * @return the specified substring. + * @exception IndexOutOfBoundsException if the + * beginIndex is negative, or + * endIndex is larger than the length of + * this String object, or + * beginIndex is larger than + * endIndex. + */ + public String substring(int beginIndex, int endIndex) { + if (beginIndex < 0) { + throw new StringIndexOutOfBoundsException(beginIndex); + } + if (endIndex > count) { + throw new StringIndexOutOfBoundsException(endIndex); + } + if (beginIndex > endIndex) { + throw new StringIndexOutOfBoundsException(endIndex - beginIndex); + } + return ((beginIndex == 0) && (endIndex == count)) ? this : + new String(offset + beginIndex, endIndex - beginIndex, value); + } + + /** + * Returns a new character sequence that is a subsequence of this sequence. + * + *

An invocation of this method of the form + * + *

+     * str.subSequence(begin, end)
+ * + * behaves in exactly the same way as the invocation + * + *
+     * str.substring(begin, end)
+ * + * This method is defined so that the String class can implement + * the {@link CharSequence} interface.

+ * + * @param beginIndex the begin index, inclusive. + * @param endIndex the end index, exclusive. + * @return the specified subsequence. + * + * @throws IndexOutOfBoundsException + * if beginIndex or endIndex are negative, + * if endIndex is greater than length(), + * or if beginIndex is greater than startIndex + * + * @since 1.4 + * @spec JSR-51 + */ + public CharSequence subSequence(int beginIndex, int endIndex) { + return this.substring(beginIndex, endIndex); + } + + /** + * Concatenates the specified string to the end of this string. + *

+ * If the length of the argument string is 0, then this + * String object is returned. Otherwise, a new + * String object is created, representing a character + * sequence that is the concatenation of the character sequence + * represented by this String object and the character + * sequence represented by the argument string.

+ * Examples: + *

+     * "cares".concat("s") returns "caress"
+     * "to".concat("get").concat("her") returns "together"
+     * 
+ * + * @param str the String that is concatenated to the end + * of this String. + * @return a string that represents the concatenation of this object's + * characters followed by the string argument's characters. + */ + public String concat(String str) { + int otherLen = str.length(); + if (otherLen == 0) { + return this; + } + char buf[] = new char[count + otherLen]; + getChars(0, count, buf, 0); + str.getChars(0, otherLen, buf, count); + return new String(0, count + otherLen, buf); + } + + /** + * Returns a new string resulting from replacing all occurrences of + * oldChar in this string with newChar. + *

+ * If the character oldChar does not occur in the + * character sequence represented by this String object, + * then a reference to this String object is returned. + * Otherwise, a new String object is created that + * represents a character sequence identical to the character sequence + * represented by this String object, except that every + * occurrence of oldChar is replaced by an occurrence + * of newChar. + *

+ * Examples: + *

+     * "mesquite in your cellar".replace('e', 'o')
+     *         returns "mosquito in your collar"
+     * "the war of baronets".replace('r', 'y')
+     *         returns "the way of bayonets"
+     * "sparring with a purple porpoise".replace('p', 't')
+     *         returns "starring with a turtle tortoise"
+     * "JonL".replace('q', 'x') returns "JonL" (no change)
+     * 
+ * + * @param oldChar the old character. + * @param newChar the new character. + * @return a string derived from this string by replacing every + * occurrence of oldChar with newChar. + */ + public String replace(char oldChar, char newChar) { + if (oldChar != newChar) { + int len = count; + int i = -1; + char[] val = value; /* avoid getfield opcode */ + int off = offset; /* avoid getfield opcode */ + + while (++i < len) { + if (val[off + i] == oldChar) { + break; + } + } + if (i < len) { + char buf[] = new char[len]; + for (int j = 0 ; j < i ; j++) { + buf[j] = val[off+j]; + } + while (i < len) { + char c = val[off + i]; + buf[i] = (c == oldChar) ? newChar : c; + i++; + } + return new String(0, len, buf); + } + } + return this; + } + + /** + * Tells whether or not this string matches the given regular expression. + * + *

An invocation of this method of the form + * str.matches(regex) yields exactly the + * same result as the expression + * + *

{@link java.util.regex.Pattern}.{@link + * java.util.regex.Pattern#matches(String,CharSequence) + * matches}(regex, str)
+ * + * @param regex + * the regular expression to which this string is to be matched + * + * @return true if, and only if, this string matches the + * given regular expression + * + * @throws PatternSyntaxException + * if the regular expression's syntax is invalid + * + * @see java.util.regex.Pattern + * + * @since 1.4 + * @spec JSR-51 + */ + public boolean matches(String regex) { + return Pattern.matches(regex, this); + } + + /** + * Returns true if and only if this string contains the specified + * sequence of char values. + * + * @param s the sequence to search for + * @return true if this string contains s, false otherwise + * @throws NullPointerException if s is null + * @since 1.5 + */ + public boolean contains(CharSequence s) { + return indexOf(s.toString()) > -1; + } + + /** + * Replaces the first substring of this string that matches the given regular expression with the + * given replacement. + * + *

An invocation of this method of the form + * str.replaceFirst(regex, repl) + * yields exactly the same result as the expression + * + *

+ * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile + * compile}(regex).{@link + * java.util.regex.Pattern#matcher(java.lang.CharSequence) + * matcher}(str).{@link java.util.regex.Matcher#replaceFirst + * replaceFirst}(repl)
+ * + * @param regex + * the regular expression to which this string is to be matched + * + * @return The resulting String + * + * @throws PatternSyntaxException + * if the regular expression's syntax is invalid + * + * @see java.util.regex.Pattern + * + * @since 1.4 + * @spec JSR-51 + */ + public String replaceFirst(String regex, String replacement) { + return Pattern.compile(regex).matcher(this).replaceFirst(replacement); + } + + /** + * Replaces each substring of this string that matches the given regular expression with the + * given replacement. + * + *

An invocation of this method of the form + * str.replaceAll(regex, repl) + * yields exactly the same result as the expression + * + *

+ * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile + * compile}(regex).{@link + * java.util.regex.Pattern#matcher(java.lang.CharSequence) + * matcher}(str).{@link java.util.regex.Matcher#replaceAll + * replaceAll}(repl)
+ * + * @param regex + * the regular expression to which this string is to be matched + * + * @return The resulting String + * + * @throws PatternSyntaxException + * if the regular expression's syntax is invalid + * + * @see java.util.regex.Pattern + * + * @since 1.4 + * @spec JSR-51 + */ + public String replaceAll(String regex, String replacement) { + return Pattern.compile(regex).matcher(this).replaceAll(replacement); + } + + /** + * Replaces each substring of this string that matches the literal target + * sequence with the specified literal replacement sequence. The + * replacement proceeds from the beginning of the string to the end, for + * example, replacing "aa" with "b" in the string "aaa" will result in + * "ba" rather than "ab". + * + * @param target The sequence of char values to be replaced + * @param replacement The replacement sequence of char values + * @return The resulting string + * @throws NullPointerException if target or + * replacement is null. + * @since 1.5 + */ + public String replace(CharSequence target, CharSequence replacement) { + return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( + this).replaceAll(Matcher.quoteReplacement(replacement.toString())); + } + + /** + * Splits this string around matches of the given + * regular expression. + * + *

The array returned by this method contains each substring of this + * string that is terminated by another substring that matches the given + * expression or is terminated by the end of the string. The substrings in + * the array are in the order in which they occur in this string. If the + * expression does not match any part of the input then the resulting array + * has just one element, namely this string. + * + *

The limit parameter controls the number of times the + * pattern is applied and therefore affects the length of the resulting + * array. If the limit n is greater than zero then the pattern + * will be applied at most n - 1 times, the array's + * length will be no greater than n, and the array's last entry + * will contain all input beyond the last matched delimiter. If n + * is non-positive then the pattern will be applied as many times as + * possible and the array can have any length. If n is zero then + * the pattern will be applied as many times as possible, the array can + * have any length, and trailing empty strings will be discarded. + * + *

The string "boo:and:foo", for example, yields the + * following results with these parameters: + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
RegexLimitResult
:2{ "boo", "and:foo" }
:5{ "boo", "and", "foo" }
:-2{ "boo", "and", "foo" }
o5{ "b", "", ":and:f", "", "" }
o-2{ "b", "", ":and:f", "", "" }
o0{ "b", "", ":and:f" }
+ * + *

An invocation of this method of the form + * str.split(regex, n) + * yields the same result as the expression + * + *

+ * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile + * compile}(regex).{@link + * java.util.regex.Pattern#split(java.lang.CharSequence,int) + * split}(str, n) + *
+ * + * + * @param regex + * the delimiting regular expression + * + * @param limit + * the result threshold, as described above + * + * @return the array of strings computed by splitting this string + * around matches of the given regular expression + * + * @throws PatternSyntaxException + * if the regular expression's syntax is invalid + * + * @see java.util.regex.Pattern + * + * @since 1.4 + * @spec JSR-51 + */ + public String[] split(String regex, int limit) { + return Pattern.compile(regex).split(this, limit); + } + + /** + * Splits this string around matches of the given + * {@linkplain java.util.regex.Pattern#sum regular expression}. + * + *

This method works as if by invoking the two-argument {@link + * #split(String, int) split} method with the given expression and a limit + * argument of zero. Trailing empty strings are therefore not included in + * the resulting array. + * + *

The string "boo:and:foo", for example, yields the following + * results with these expressions: + * + *

+ * + * + * + * + * + * + * + * + *
RegexResult
:{ "boo", "and", "foo" }
o{ "b", "", ":and:f" }
+ * + * + * @param regex + * the delimiting regular expression + * + * @return the array of strings computed by splitting this string + * around matches of the given regular expression + * + * @throws PatternSyntaxException + * if the regular expression's syntax is invalid + * + * @see java.util.regex.Pattern + * + * @since 1.4 + * @spec JSR-51 + */ + public String[] split(String regex) { + return split(regex, 0); + } + + /** + * Converts all of the characters in this String to lower + * case using the rules of the given Locale. Case mapping is based + * on the Unicode Standard version specified by the {@link java.lang.Character Character} + * class. Since case mappings are not always 1:1 char mappings, the resulting + * String may be a different length than the original String. + *

+ * Examples of lowercase mappings are in the following table: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Language Code of LocaleUpper CaseLower CaseDescription
tr (Turkish)\u0130\u0069capital letter I with dot above -> small letter i
tr (Turkish)\u0049\u0131capital letter I -> small letter dotless i
(all)French Friesfrench frieslowercased all chars in String
(all)capiotacapchi + * capthetacapupsil + * capsigmaiotachi + * thetaupsilon + * sigmalowercased all chars in String
+ * + * @param locale use the case transformation rules for this locale + * @return the String, converted to lowercase. + * @see java.lang.String#toLowerCase() + * @see java.lang.String#toUpperCase() + * @see java.lang.String#toUpperCase(Locale) + * @since 1.1 + */ + public String toLowerCase(Locale locale) { + if (locale == null) { + throw new NullPointerException(); + } + + int firstUpper; + + /* Now check if there are any characters that need to be changed. */ + scan: { + for (firstUpper = 0 ; firstUpper < count; ) { + char c = value[offset+firstUpper]; + if ((c >= Character.MIN_HIGH_SURROGATE) && + (c <= Character.MAX_HIGH_SURROGATE)) { + int supplChar = codePointAt(firstUpper); + if (supplChar != Character.toLowerCase(supplChar)) { + break scan; + } + firstUpper += Character.charCount(supplChar); + } else { + if (c != Character.toLowerCase(c)) { + break scan; + } + firstUpper++; + } + } + return this; + } + + char[] result = new char[count]; + int resultOffset = 0; /* result may grow, so i+resultOffset + * is the write location in result */ + + /* Just copy the first few lowerCase characters. */ + System.arraycopy(value, offset, result, 0, firstUpper); + + String lang = locale.getLanguage(); + boolean localeDependent = + (lang == "tr" || lang == "az" || lang == "lt"); + char[] lowerCharArray; + int lowerChar; + int srcChar; + int srcCount; + for (int i = firstUpper; i < count; i += srcCount) { + srcChar = (int)value[offset+i]; + if ((char)srcChar >= Character.MIN_HIGH_SURROGATE && + (char)srcChar <= Character.MAX_HIGH_SURROGATE) { + srcChar = codePointAt(i); + srcCount = Character.charCount(srcChar); + } else { + srcCount = 1; + } + if (localeDependent || srcChar == '\u03A3') { // GREEK CAPITAL LETTER SIGMA + lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale); + } else { + lowerChar = Character.toLowerCase(srcChar); + } + if ((lowerChar == Character.ERROR) || + (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) { + if (lowerChar == Character.ERROR) { + lowerCharArray = + ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale); + } else if (srcCount == 2) { + resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount; + continue; + } else { + lowerCharArray = Character.toChars(lowerChar); + } + + /* Grow result if needed */ + int mapLen = lowerCharArray.length; + if (mapLen > srcCount) { + char[] result2 = new char[result.length + mapLen - srcCount]; + System.arraycopy(result, 0, result2, 0, + i + resultOffset); + result = result2; + } + for (int x=0; xString to lower + * case using the rules of the default locale. This is equivalent to calling + * toLowerCase(Locale.getDefault()). + *

+ * @return the String, converted to lowercase. + * @see java.lang.String#toLowerCase(Locale) + */ + public String toLowerCase() { + return toLowerCase(Locale.getDefault()); + } + + /** + * Converts all of the characters in this String to upper + * case using the rules of the given Locale. Case mapping is based + * on the Unicode Standard version specified by the {@link java.lang.Character Character} + * class. Since case mappings are not always 1:1 char mappings, the resulting + * String may be a different length than the original String. + *

+ * Examples of locale-sensitive and 1:M case mappings are in the following table. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Language Code of LocaleLower CaseUpper CaseDescription
tr (Turkish)\u0069\u0130small letter i -> capital letter I with dot above
tr (Turkish)\u0131\u0049small letter dotless i -> capital letter I
(all)\u00df\u0053 \u0053small letter sharp s -> two letters: SS
(all)FahrvergnügenFAHRVERGNÜGEN
+ * @param locale use the case transformation rules for this locale + * @return the String, converted to uppercase. + * @see java.lang.String#toUpperCase() + * @see java.lang.String#toLowerCase() + * @see java.lang.String#toLowerCase(Locale) + * @since 1.1 + */ + public String toUpperCase(Locale locale) { + if (locale == null) { + throw new NullPointerException(); + } + + int firstLower; + + /* Now check if there are any characters that need to be changed. */ + scan: { + for (firstLower = 0 ; firstLower < count; ) { + int c = (int)value[offset+firstLower]; + int srcCount; + if ((c >= Character.MIN_HIGH_SURROGATE) && + (c <= Character.MAX_HIGH_SURROGATE)) { + c = codePointAt(firstLower); + srcCount = Character.charCount(c); + } else { + srcCount = 1; + } + int upperCaseChar = Character.toUpperCaseEx(c); + if ((upperCaseChar == Character.ERROR) || + (c != upperCaseChar)) { + break scan; + } + firstLower += srcCount; + } + return this; + } + + char[] result = new char[count]; /* may grow */ + int resultOffset = 0; /* result may grow, so i+resultOffset + * is the write location in result */ + + /* Just copy the first few upperCase characters. */ + System.arraycopy(value, offset, result, 0, firstLower); + + String lang = locale.getLanguage(); + boolean localeDependent = + (lang == "tr" || lang == "az" || lang == "lt"); + char[] upperCharArray; + int upperChar; + int srcChar; + int srcCount; + for (int i = firstLower; i < count; i += srcCount) { + srcChar = (int)value[offset+i]; + if ((char)srcChar >= Character.MIN_HIGH_SURROGATE && + (char)srcChar <= Character.MAX_HIGH_SURROGATE) { + srcChar = codePointAt(i); + srcCount = Character.charCount(srcChar); + } else { + srcCount = 1; + } + if (localeDependent) { + upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale); + } else { + upperChar = Character.toUpperCaseEx(srcChar); + } + if ((upperChar == Character.ERROR) || + (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) { + if (upperChar == Character.ERROR) { + if (localeDependent) { + upperCharArray = + ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale); + } else { + upperCharArray = Character.toUpperCaseCharArray(srcChar); + } + } else if (srcCount == 2) { + resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount; + continue; + } else { + upperCharArray = Character.toChars(upperChar); + } + + /* Grow result if needed */ + int mapLen = upperCharArray.length; + if (mapLen > srcCount) { + char[] result2 = new char[result.length + mapLen - srcCount]; + System.arraycopy(result, 0, result2, 0, + i + resultOffset); + result = result2; + } + for (int x=0; xString to upper + * case using the rules of the default locale. This method is equivalent to + * toUpperCase(Locale.getDefault()). + *

+ * @return the String, converted to uppercase. + * @see java.lang.String#toUpperCase(Locale) + */ + public String toUpperCase() { + return toUpperCase(Locale.getDefault()); + } + + /** + * Returns a copy of the string, with leading and trailing whitespace + * omitted. + *

+ * If this String object represents an empty character + * sequence, or the first and last characters of character sequence + * represented by this String object both have codes + * greater than '\u0020' (the space character), then a + * reference to this String object is returned. + *

+ * Otherwise, if there is no character with a code greater than + * '\u0020' in the string, then a new + * String object representing an empty string is created + * and returned. + *

+ * Otherwise, let k be the index of the first character in the + * string whose code is greater than '\u0020', and let + * m be the index of the last character in the string whose code + * is greater than '\u0020'. A new String + * object is created, representing the substring of this string that + * begins with the character at index k and ends with the + * character at index m-that is, the result of + * this.substring(k, m+1). + *

+ * This method may be used to trim whitespace (as defined above) from + * the beginning and end of a string. + * + * @return A copy of this string with leading and trailing white + * space removed, or this string if it has no leading or + * trailing white space. + */ + public String trim() { + int len = count; + int st = 0; + int off = offset; /* avoid getfield opcode */ + char[] val = value; /* avoid getfield opcode */ + + while ((st < len) && (val[off + st] <= ' ')) { + st++; + } + while ((st < len) && (val[off + len - 1] <= ' ')) { + len--; + } + return ((st > 0) || (len < count)) ? substring(st, len) : this; + } + + /** + * This object (which is already a string!) is itself returned. + * + * @return the string itself. + */ + public String toString() { + return this; + } + + /** + * Converts this string to a new character array. + * + * @return a newly allocated character array whose length is the length + * of this string and whose contents are initialized to contain + * the character sequence represented by this string. + */ + public char[] toCharArray() { + char result[] = new char[count]; + getChars(0, count, result, 0); + return result; + } + + /** + * Returns a formatted string using the specified format string and + * arguments. + * + *

The locale always used is the one returned by {@link + * java.util.Locale#getDefault() Locale.getDefault()}. + * + * @param format + * A format string + * + * @param args + * Arguments referenced by the format specifiers in the format + * string. If there are more arguments than format specifiers, the + * extra arguments are ignored. The number of arguments is + * variable and may be zero. The maximum number of arguments is + * limited by the maximum dimension of a Java array as defined by + * the Java + * Virtual Machine Specification. The behaviour on a + * null argument depends on the conversion. + * + * @throws IllegalFormatException + * If a format string contains an illegal syntax, a format + * specifier that is incompatible with the given arguments, + * insufficient arguments given the format string, or other + * illegal conditions. For specification of all possible + * formatting errors, see the Details section of the + * formatter class specification. + * + * @throws NullPointerException + * If the format is null + * + * @return A formatted string + * + * @see java.util.Formatter + * @since 1.5 + */ + public static String format(String format, Object ... args) { + return new Formatter().format(format, args).toString(); + } + + /** + * Returns a formatted string using the specified locale, format string, + * and arguments. + * + * @param l + * The {@linkplain java.util.Locale locale} to apply during + * formatting. If l is null then no localization + * is applied. + * + * @param format + * A format string + * + * @param args + * Arguments referenced by the format specifiers in the format + * string. If there are more arguments than format specifiers, the + * extra arguments are ignored. The number of arguments is + * variable and may be zero. The maximum number of arguments is + * limited by the maximum dimension of a Java array as defined by + * the Java + * Virtual Machine Specification. The behaviour on a + * null argument depends on the conversion. + * + * @throws IllegalFormatException + * If a format string contains an illegal syntax, a format + * specifier that is incompatible with the given arguments, + * insufficient arguments given the format string, or other + * illegal conditions. For specification of all possible + * formatting errors, see the Details section of the + * formatter class specification + * + * @throws NullPointerException + * If the format is null + * + * @return A formatted string + * + * @see java.util.Formatter + * @since 1.5 + */ + public static String format(Locale l, String format, Object ... args) { + return new Formatter(l).format(format, args).toString(); + } + + /** + * Returns the string representation of the Object argument. + * + * @param obj an Object. + * @return if the argument is null, then a string equal to + * "null"; otherwise, the value of + * obj.toString() is returned. + * @see java.lang.Object#toString() + */ + public static String valueOf(Object obj) { + return (obj == null) ? "null" : obj.toString(); + } + + /** + * Returns the string representation of the char array + * argument. The contents of the character array are copied; subsequent + * modification of the character array does not affect the newly + * created string. + * + * @param data a char array. + * @return a newly allocated string representing the same sequence of + * characters contained in the character array argument. + */ + public static String valueOf(char data[]) { + return new String(data); + } + + /** + * Returns the string representation of a specific subarray of the + * char array argument. + *

+ * The offset argument is the index of the first + * character of the subarray. The count argument + * specifies the length of the subarray. The contents of the subarray + * are copied; subsequent modification of the character array does not + * affect the newly created string. + * + * @param data the character array. + * @param offset the initial offset into the value of the + * String. + * @param count the length of the value of the String. + * @return a string representing the sequence of characters contained + * in the subarray of the character array argument. + * @exception IndexOutOfBoundsException if offset is + * negative, or count is negative, or + * offset+count is larger than + * data.length. + */ + public static String valueOf(char data[], int offset, int count) { + return new String(data, offset, count); + } + + /** + * Returns a String that represents the character sequence in the + * array specified. + * + * @param data the character array. + * @param offset initial offset of the subarray. + * @param count length of the subarray. + * @return a String that contains the characters of the + * specified subarray of the character array. + */ + public static String copyValueOf(char data[], int offset, int count) { + // All public String constructors now copy the data. + return new String(data, offset, count); + } + + /** + * Returns a String that represents the character sequence in the + * array specified. + * + * @param data the character array. + * @return a String that contains the characters of the + * character array. + */ + public static String copyValueOf(char data[]) { + return copyValueOf(data, 0, data.length); + } + + /** + * Returns the string representation of the boolean argument. + * + * @param b a boolean. + * @return if the argument is true, a string equal to + * "true" is returned; otherwise, a string equal to + * "false" is returned. + */ + public static String valueOf(boolean b) { + return b ? "true" : "false"; + } + + /** + * Returns the string representation of the char + * argument. + * + * @param c a char. + * @return a string of length 1 containing + * as its single character the argument c. + */ + public static String valueOf(char c) { + char data[] = {c}; + return new String(0, 1, data); + } + + /** + * Returns the string representation of the int argument. + *

+ * The representation is exactly the one returned by the + * Integer.toString method of one argument. + * + * @param i an int. + * @return a string representation of the int argument. + * @see java.lang.Integer#toString(int, int) + */ + public static String valueOf(int i) { + return Integer.toString(i, 10); + } + + /** + * Returns the string representation of the long argument. + *

+ * The representation is exactly the one returned by the + * Long.toString method of one argument. + * + * @param l a long. + * @return a string representation of the long argument. + * @see java.lang.Long#toString(long) + */ + public static String valueOf(long l) { + return Long.toString(l, 10); + } + + /** + * Returns the string representation of the float argument. + *

+ * The representation is exactly the one returned by the + * Float.toString method of one argument. + * + * @param f a float. + * @return a string representation of the float argument. + * @see java.lang.Float#toString(float) + */ + public static String valueOf(float f) { + return Float.toString(f); + } + + /** + * Returns the string representation of the double argument. + *

+ * The representation is exactly the one returned by the + * Double.toString method of one argument. + * + * @param d a double. + * @return a string representation of the double argument. + * @see java.lang.Double#toString(double) + */ + public static String valueOf(double d) { + return Double.toString(d); + } + + /** + * Returns a canonical representation for the string object. + *

+ * A pool of strings, initially empty, is maintained privately by the + * class String. + *

+ * When the intern method is invoked, if the pool already contains a + * string equal to this String object as determined by + * the {@link #equals(Object)} method, then the string from the pool is + * returned. Otherwise, this String object is added to the + * pool and a reference to this String object is returned. + *

+ * It follows that for any two strings s and t, + * s.intern() == t.intern() is true + * if and only if s.equals(t) is true. + *

+ * All literal strings and string-valued constant expressions are + * interned. String literals are defined in §3.10.5 of the + * Java Language + * Specification + * + * @return a string that has the same contents as this string, but is + * guaranteed to be from a pool of unique strings. + */ + public native String intern(); + +} diff --git a/java/java-tests/testData/psi/repositoryUse/src/pack/AssertParentId.java b/java/java-tests/testData/psi/repositoryUse/src/pack/AssertParentId.java new file mode 100644 index 000000000000..ede95fad2857 --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src/pack/AssertParentId.java @@ -0,0 +1,10 @@ +package pack; + +import javax.swing.*; + +public class AssertParentId extends JPanel{ + int foo(){} + + Object TEST = new JPanel(){ }; +} + diff --git a/java/java-tests/testData/psi/repositoryUse/src/pack/MyClass2.java b/java/java-tests/testData/psi/repositoryUse/src/pack/MyClass2.java new file mode 100644 index 000000000000..2eb4bcbf7cab --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src/pack/MyClass2.java @@ -0,0 +1,29 @@ +package pack; + +public class MyClass2 extends String implements Runnable{ + /** + * @deprecated + */ + int field1 = 0; + + Object field2[]; + + java.lang.Object[] field3; + + void method1(int[] p1, Object p2, pack . AAA p3, + pack . /* comment */ AAA p4, + pack . // comment + AAA p5 + ) throws Exception, java.io. IOException{ + } + + Integer method2()[]{ + new Cloneable(){ + }; + class Local implements Cloneable{} + } + + MyClass2(){} + + static class Inner{} +} diff --git a/java/java-tests/testData/psi/repositoryUse/src/pack/MyInterface1.java b/java/java-tests/testData/psi/repositoryUse/src/pack/MyInterface1.java new file mode 100644 index 000000000000..d65d560a9e95 --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src/pack/MyInterface1.java @@ -0,0 +1,6 @@ +package pack; + +import javax.swing.*; + +public interface MyInterface1{ +} diff --git a/java/java-tests/testData/psi/repositoryUse/src15/annotated/AnnotatedClass.java b/java/java-tests/testData/psi/repositoryUse/src15/annotated/AnnotatedClass.java new file mode 100644 index 000000000000..b7c852420b4e --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src15/annotated/AnnotatedClass.java @@ -0,0 +1,9 @@ +package annotated; + +import annotations.*; + +@annotations.AnnotationType +public class AnnotatedClass { + @AnnotationType("<") public void correctMethod() {} + @wrongpkg.AnnotationType public void wrongMethod() {} +} diff --git a/java/java-tests/testData/psi/repositoryUse/src15/annotated/package-info.java b/java/java-tests/testData/psi/repositoryUse/src15/annotated/package-info.java new file mode 100644 index 000000000000..d1bb0673dcbf --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src15/annotated/package-info.java @@ -0,0 +1,4 @@ +@AnnotationType +package annotated; + +import annotations.*; diff --git a/java/java-tests/testData/psi/repositoryUse/src15/annotations/AnnotationType.java b/java/java-tests/testData/psi/repositoryUse/src15/annotations/AnnotationType.java new file mode 100644 index 000000000000..34bff9a64ae3 --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src15/annotations/AnnotationType.java @@ -0,0 +1,3 @@ +package annotations; +public @interface AnnotationType { +} diff --git a/java/java-tests/testData/psi/repositoryUse/src15/annotations/DeprecatedAnnotation.java b/java/java-tests/testData/psi/repositoryUse/src15/annotations/DeprecatedAnnotation.java new file mode 100644 index 000000000000..0fa37dcbfb3b --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src15/annotations/DeprecatedAnnotation.java @@ -0,0 +1,5 @@ +package annotations; +@Deprecated class DeprecatedAnnotation { + @Deprecated void foo() {} + @Deprecated int i; +} diff --git a/java/java-tests/testData/psi/repositoryUse/src15/enumImplements/MyEnum.java b/java/java-tests/testData/psi/repositoryUse/src15/enumImplements/MyEnum.java new file mode 100644 index 000000000000..165834e29f52 --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src15/enumImplements/MyEnum.java @@ -0,0 +1,5 @@ +package enumImplements; + +interface I {} + +enum MyEnum implements I {} diff --git a/java/java-tests/testData/psi/repositoryUse/src15/enums/OurBaseInterface.java b/java/java-tests/testData/psi/repositoryUse/src15/enums/OurBaseInterface.java new file mode 100644 index 000000000000..5cdd2ff70b42 --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src15/enums/OurBaseInterface.java @@ -0,0 +1,4 @@ +package enums; + +interface OurBaseInterface { +} diff --git a/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnum.java b/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnum.java new file mode 100644 index 000000000000..da45bcd6612d --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnum.java @@ -0,0 +1,4 @@ +package enums; + +enum OurEnum { +} diff --git a/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithConstants.java b/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithConstants.java new file mode 100644 index 000000000000..ae54e1da1aaa --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithConstants.java @@ -0,0 +1,5 @@ +package enums; + +public enum OurEnumWithConstants { + A, B, C; +} diff --git a/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithConstantsAndStaticFields.java b/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithConstantsAndStaticFields.java new file mode 100644 index 000000000000..2b3de3d4a09e --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithConstantsAndStaticFields.java @@ -0,0 +1,7 @@ +package enums; + +enum OurEnumWithConstantsAndStaticFields { + A, B, C; + + public static final int A1 = 1; +} diff --git a/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithConstantsAndStaticFields2.java b/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithConstantsAndStaticFields2.java new file mode 100644 index 000000000000..f411f7ff9b8c --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithConstantsAndStaticFields2.java @@ -0,0 +1,39 @@ +package enums; + +public abstract enum OurEnumWithConstantsAndStaticFields2 { + A { + void foo() { + //To change body of implemented methods use File | Settings | File Templates. + } + }, + B { + void foo() { + //To change body of implemented methods use File | Settings | File Templates. + } + + }, + C(10) + ; + + public static final int A1 = 10; + void foo() {} + + public OurEnum() { + + } + { + Enum a = A; + OurEnum value = A; + switch(value) { + case A: + break; + case + } + + int i = 10; + switch(i) { + case A1 + } + } +} +} diff --git a/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithInitializedConstants.java b/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithInitializedConstants.java new file mode 100644 index 000000000000..2fe43ab75867 --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src15/enums/OurEnumWithInitializedConstants.java @@ -0,0 +1,12 @@ +package enums; + +public enum OurEnumWithInitializedConstants { + A(0) { + }, + B(1) { + void foo (){} + }, + C(new OurBaseInterface() {}) { + void foo () {} + } +} diff --git a/java/java-tests/testData/psi/repositoryUse/src15/staticImports/StaticImports.java b/java/java-tests/testData/psi/repositoryUse/src15/staticImports/StaticImports.java new file mode 100644 index 000000000000..7077269eef27 --- /dev/null +++ b/java/java-tests/testData/psi/repositoryUse/src15/staticImports/StaticImports.java @@ -0,0 +1,20 @@ +package staticImports; + +import java.util.Arrays; +import static java.util.Collections.*; +import java.util.Collections; +import static java.util.Arrays.*; +import static java.util.Collections.sort; +import static java.util.Arrays.sort; + +public class StaticImports { + { + sort(new List()); + sort(new List()); + sort(new int[256]); + Integer[] v = new Integer[256]; + sort(v) + sort(asList(v)); + } +} + diff --git a/java/java-tests/testData/psi/shortenClassRefs/SCR22368.java b/java/java-tests/testData/psi/shortenClassRefs/SCR22368.java new file mode 100644 index 000000000000..e25a3d75355c --- /dev/null +++ b/java/java-tests/testData/psi/shortenClassRefs/SCR22368.java @@ -0,0 +1,5 @@ +class X { + void method() { + java.util.List< + } +} diff --git a/java/java-tests/testData/psi/shortenClassRefs/SCR22368_after.java b/java/java-tests/testData/psi/shortenClassRefs/SCR22368_after.java new file mode 100644 index 000000000000..f3e6338fa916 --- /dev/null +++ b/java/java-tests/testData/psi/shortenClassRefs/SCR22368_after.java @@ -0,0 +1,7 @@ +import java.util.List; + +class X { + void method() { + List< + } +} diff --git a/java/java-tests/testData/psi/shortenClassRefs/SCR37254.java b/java/java-tests/testData/psi/shortenClassRefs/SCR37254.java new file mode 100644 index 000000000000..4a49297120d1 --- /dev/null +++ b/java/java-tests/testData/psi/shortenClassRefs/SCR37254.java @@ -0,0 +1,18 @@ +class Parent{ + + protected Child createChild() { + return null; + } + + static class Child { + } +} + +class SubClass extends Parent { + //Do not shorten Parent.Child to Child + protected Parent.Child createChild() { + return null; + } + + class Child extends Parent.Child {} +} diff --git a/java/java-tests/testData/psi/shortenClassRefs/SCR37254_after.java b/java/java-tests/testData/psi/shortenClassRefs/SCR37254_after.java new file mode 100644 index 000000000000..4a49297120d1 --- /dev/null +++ b/java/java-tests/testData/psi/shortenClassRefs/SCR37254_after.java @@ -0,0 +1,18 @@ +class Parent{ + + protected Child createChild() { + return null; + } + + static class Child { + } +} + +class SubClass extends Parent { + //Do not shorten Parent.Child to Child + protected Parent.Child createChild() { + return null; + } + + class Child extends Parent.Child {} +} diff --git a/java/java-tests/testData/psi/types/assignableSubinheritor/empty.txt b/java/java-tests/testData/psi/types/assignableSubinheritor/empty.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/java/java-tests/testData/psi/types/boundedParams/A.java b/java/java-tests/testData/psi/types/boundedParams/A.java new file mode 100644 index 000000000000..4e9dc5e4906b --- /dev/null +++ b/java/java-tests/testData/psi/types/boundedParams/A.java @@ -0,0 +1,7 @@ +import test.*; + +class A { + void method(T param) { + Iterator it = param.iterator(); + } +} diff --git a/java/java-tests/testData/psi/types/complexInheritance/A.java b/java/java-tests/testData/psi/types/complexInheritance/A.java new file mode 100644 index 000000000000..e1cc4aa7becf --- /dev/null +++ b/java/java-tests/testData/psi/types/complexInheritance/A.java @@ -0,0 +1,9 @@ +import test.*; + +public class A { + void method() { + IntListList l = new IntListList(); + l.get(0); + } +} + diff --git a/java/java-tests/testData/psi/types/listListInheritance/A.java b/java/java-tests/testData/psi/types/listListInheritance/A.java new file mode 100644 index 000000000000..2eff7e20b759 --- /dev/null +++ b/java/java-tests/testData/psi/types/listListInheritance/A.java @@ -0,0 +1,15 @@ +import test.*; + +public class A { + public static class B extends ListList { + } + + public void method() { + ListList l = new ListList(); + l.get(0); + B b = new B(); + b.get(0); + l.add(b.get(0)); + b.add(l.get(0)) + } +} diff --git a/java/java-tests/testData/psi/types/methodTypeParameter/A.java b/java/java-tests/testData/psi/types/methodTypeParameter/A.java new file mode 100644 index 000000000000..5a33e57a3379 --- /dev/null +++ b/java/java-tests/testData/psi/types/methodTypeParameter/A.java @@ -0,0 +1,10 @@ +import test.*; + +public class A { + public void method() { + List l = new List(); + CollectionUtil.sort(l); + List l1 = new List(); + CollectionUtil.sort(l1) + } +} diff --git a/java/java-tests/testData/psi/types/rawArrayTypes/A.java b/java/java-tests/testData/psi/types/rawArrayTypes/A.java new file mode 100644 index 000000000000..552a0ba41630 --- /dev/null +++ b/java/java-tests/testData/psi/types/rawArrayTypes/A.java @@ -0,0 +1,9 @@ +import test.*; + +class A { + void method() { + List l; + l.getArray(); + l.getListOfArrays(); + } +} diff --git a/java/java-tests/testData/psi/types/rawTypeExtension/A.java b/java/java-tests/testData/psi/types/rawTypeExtension/A.java new file mode 100644 index 000000000000..bb09f352edbe --- /dev/null +++ b/java/java-tests/testData/psi/types/rawTypeExtension/A.java @@ -0,0 +1,7 @@ +import test.*; + +class A extends List { + void method() { + Iterator it = iterator(); + } +} diff --git a/java/java-tests/testData/psi/types/rawTypeInMethodArg/A.java b/java/java-tests/testData/psi/types/rawTypeInMethodArg/A.java new file mode 100644 index 000000000000..d279a2a909d3 --- /dev/null +++ b/java/java-tests/testData/psi/types/rawTypeInMethodArg/A.java @@ -0,0 +1,9 @@ +import test.*; + +class A { + public void method() { + List l = new List(); + List l1 = new List(); + l1.putAll(l); + } +} diff --git a/java/java-tests/testData/psi/types/rawTypes/A.java b/java/java-tests/testData/psi/types/rawTypes/A.java new file mode 100644 index 000000000000..81bb47f266e0 --- /dev/null +++ b/java/java-tests/testData/psi/types/rawTypes/A.java @@ -0,0 +1,9 @@ +import test.*; + +class A { + public void method() { + List list = new List(); + list.add(new A()); + list.iterator(); + } +} diff --git a/java/java-tests/testData/psi/types/simpleRawTypeInMethodArg/A.java b/java/java-tests/testData/psi/types/simpleRawTypeInMethodArg/A.java new file mode 100644 index 000000000000..e4415f27f603 --- /dev/null +++ b/java/java-tests/testData/psi/types/simpleRawTypeInMethodArg/A.java @@ -0,0 +1,9 @@ +import test.*; + +public class A { + void method() { + Object o = null; + List l = new List(); + l.add(o); + } +} diff --git a/java/java-tests/testData/psi/types/simpleStuff/A.java b/java/java-tests/testData/psi/types/simpleStuff/A.java new file mode 100644 index 000000000000..b4039ac92699 --- /dev/null +++ b/java/java-tests/testData/psi/types/simpleStuff/A.java @@ -0,0 +1,9 @@ +import test.*; + +class A { + public void method() { + List list = new List(); + list.add("abcd"); + list.iterator(); + } +} diff --git a/java/java-tests/testData/psi/types/spaceInTypeParameterList/A.java b/java/java-tests/testData/psi/types/spaceInTypeParameterList/A.java new file mode 100644 index 000000000000..659652ddac15 --- /dev/null +++ b/java/java-tests/testData/psi/types/spaceInTypeParameterList/A.java @@ -0,0 +1,7 @@ +import test.*; + +public class A { + public void method() { + List> l = null; + } +} diff --git a/java/java-tests/testData/psi/types/src/test/AbstractCollection.java b/java/java-tests/testData/psi/types/src/test/AbstractCollection.java new file mode 100644 index 000000000000..5c2b4cd47a67 --- /dev/null +++ b/java/java-tests/testData/psi/types/src/test/AbstractCollection.java @@ -0,0 +1,2 @@ +public class SubList extends List { +} diff --git a/java/java-tests/testData/psi/types/src/test/Collection.java b/java/java-tests/testData/psi/types/src/test/Collection.java new file mode 100644 index 000000000000..f7c133b14d71 --- /dev/null +++ b/java/java-tests/testData/psi/types/src/test/Collection.java @@ -0,0 +1,9 @@ +package test; + +public interface Collection { + void add(E e); + void remove(E e); + boolean contains(E e); + Iterator iterator(); + void putAll(Collection l); +} diff --git a/java/java-tests/testData/psi/types/src/test/CollectionUtil.java b/java/java-tests/testData/psi/types/src/test/CollectionUtil.java new file mode 100644 index 000000000000..8ba67910fce5 --- /dev/null +++ b/java/java-tests/testData/psi/types/src/test/CollectionUtil.java @@ -0,0 +1,6 @@ +package test; + +public abstract class CollectionUtil { + public static void sort(Collection collection) { + } +} diff --git a/java/java-tests/testData/psi/types/src/test/IntList.java b/java/java-tests/testData/psi/types/src/test/IntList.java new file mode 100644 index 000000000000..2371b5b35d43 --- /dev/null +++ b/java/java-tests/testData/psi/types/src/test/IntList.java @@ -0,0 +1,5 @@ +package test; + +public class IntList extends List { + +} diff --git a/java/java-tests/testData/psi/types/src/test/IntListList.java b/java/java-tests/testData/psi/types/src/test/IntListList.java new file mode 100644 index 000000000000..5d2c22b2f24a --- /dev/null +++ b/java/java-tests/testData/psi/types/src/test/IntListList.java @@ -0,0 +1,4 @@ +package test; + +public class IntListList extends List> { +} diff --git a/java/java-tests/testData/psi/types/src/test/Iterator.java b/java/java-tests/testData/psi/types/src/test/Iterator.java new file mode 100644 index 000000000000..26ba19b7cbba --- /dev/null +++ b/java/java-tests/testData/psi/types/src/test/Iterator.java @@ -0,0 +1,5 @@ +package test; +public interface Iterator { + E next(); + boolean hasNext(); +} diff --git a/java/java-tests/testData/psi/types/src/test/List.java b/java/java-tests/testData/psi/types/src/test/List.java new file mode 100644 index 000000000000..0a9b7a6564af --- /dev/null +++ b/java/java-tests/testData/psi/types/src/test/List.java @@ -0,0 +1,23 @@ +package test; + +public class List implements Collection { + public void add(T e) { + } + public void remove(T e) { + } + public Iterator iterator() { + return null; + } + public boolean contains(T e) { + return false; + } + public T get(int i) { + return null; + } + public void putAll(Collection e) { + } + public T[] getArray() { + } + public List getListOfArrays() { + } +} diff --git a/java/java-tests/testData/psi/types/src/test/ListList.java b/java/java-tests/testData/psi/types/src/test/ListList.java new file mode 100644 index 000000000000..bfcf77cc7932 --- /dev/null +++ b/java/java-tests/testData/psi/types/src/test/ListList.java @@ -0,0 +1,4 @@ +package test; + +public class ListList extends List> { +} diff --git a/java/java-tests/testData/psi/types/src/test/SubList.java b/java/java-tests/testData/psi/types/src/test/SubList.java new file mode 100644 index 000000000000..8a0cbeee5eeb --- /dev/null +++ b/java/java-tests/testData/psi/types/src/test/SubList.java @@ -0,0 +1,4 @@ +package test; + +public class SubList extends List { +} diff --git a/java/java-tests/testData/psi/types/substWithInheritor/A.java b/java/java-tests/testData/psi/types/substWithInheritor/A.java new file mode 100644 index 000000000000..fddba5a72444 --- /dev/null +++ b/java/java-tests/testData/psi/types/substWithInheritor/A.java @@ -0,0 +1,9 @@ +import test.*; + +class A { + public void method() { + IntList list = new IntList(); + list.add(new Integer(1)); + list.iterator(); + } +} diff --git a/java/java-tests/testData/psi/types/typesInGenericClass/A.java b/java/java-tests/testData/psi/types/typesInGenericClass/A.java new file mode 100644 index 000000000000..0f02adc1af6f --- /dev/null +++ b/java/java-tests/testData/psi/types/typesInGenericClass/A.java @@ -0,0 +1,9 @@ +public class A { + T get() { + return null; + } + + void method() { + get(); + } +} diff --git a/java/java-tests/testData/psi/types/wildcardTypesAssignable/usages/Base.java b/java/java-tests/testData/psi/types/wildcardTypesAssignable/usages/Base.java new file mode 100644 index 000000000000..e5c359d6eb87 --- /dev/null +++ b/java/java-tests/testData/psi/types/wildcardTypesAssignable/usages/Base.java @@ -0,0 +1,4 @@ +package usages; + +public class Base { +} diff --git a/java/java-tests/testData/psi/types/wildcardTypesAssignable/usages/Intermediate.java b/java/java-tests/testData/psi/types/wildcardTypesAssignable/usages/Intermediate.java new file mode 100644 index 000000000000..d939aacd2769 --- /dev/null +++ b/java/java-tests/testData/psi/types/wildcardTypesAssignable/usages/Intermediate.java @@ -0,0 +1,4 @@ +package usages; + +public class Intermediate extends Base, Runnable { +} diff --git a/java/java-tests/testData/psi/types/wildcardTypesAssignable/usages/Leaf.java b/java/java-tests/testData/psi/types/wildcardTypesAssignable/usages/Leaf.java new file mode 100644 index 000000000000..bf93b6571eef --- /dev/null +++ b/java/java-tests/testData/psi/types/wildcardTypesAssignable/usages/Leaf.java @@ -0,0 +1,4 @@ +package usages; + +public class Leaf extends Intermediate { +} diff --git a/java/java-tests/testSrc/com/intellij/openapi/roots/impl/ProjectLibrariesTest.java b/java/java-tests/testSrc/com/intellij/openapi/roots/impl/ProjectLibrariesTest.java new file mode 100644 index 000000000000..60a94e6f9ae0 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/openapi/roots/impl/ProjectLibrariesTest.java @@ -0,0 +1,104 @@ +package com.intellij.openapi.roots.impl; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.roots.libraries.LibraryTable; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiClass; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.testFramework.IdeaTestCase; + +import java.io.File; +import java.util.Arrays; + +/** + * @author dsl + */ +public class ProjectLibrariesTest extends IdeaTestCase { + public void test() { + final LibraryTable libraryTable = ProjectLibraryTable.getInstance(myProject); + Library lib = ApplicationManager.getApplication().runWriteAction(new Computable() { + public Library compute() { + return libraryTable.createLibrary("LIB"); + } + }); + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + rootModel.addLibraryEntry(lib); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + rootModel.commit(); + } + }); + final JavaPsiFacade manager = getJavaFacade(); + assertNull(manager.findClass("pack.MyClass", GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(myModule))); + final File file = new File(PathManagerEx.getTestDataPath() + "/psi/repositoryUse/cls"); + final VirtualFile root = ApplicationManager.getApplication().runWriteAction(new Computable() { + public VirtualFile compute() { + return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file); + } + }); + assertNotNull(root); + final Library.ModifiableModel modifyableModel = lib.getModifiableModel(); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + modifyableModel.addRoot(root, OrderRootType.CLASSES); + modifyableModel.commit(); + } + }); + final PsiClass aClass = manager.findClass("pack.MyClass", GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(myModule)); + assertNotNull(aClass); + } + + public void test1() { + final LibraryTable libraryTable = ProjectLibraryTable.getInstance(myProject); + Library lib = ApplicationManager.getApplication().runWriteAction(new Computable() { + public Library compute() { + return libraryTable.createLibrary("LIB"); + } + }); + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + rootModel.addLibraryEntry(lib); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + rootModel.commit(); + } + }); + final JavaPsiFacade manager = getJavaFacade(); + assertNull(manager.findClass("pack.MyClass", GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(myModule))); + + final ModifiableRootModel rootModel2 = ModuleRootManager.getInstance(myModule).getModifiableModel(); + assertNotNull(rootModel2.findLibraryOrderEntry(lib)); + final File file = new File(PathManagerEx.getTestDataPath() + "/psi/repositoryUse/cls"); + final VirtualFile root = ApplicationManager.getApplication().runWriteAction(new Computable() { + public VirtualFile compute() { + return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file); + } + }); + assertNotNull(root); + final Library.ModifiableModel modifyableModel = lib.getModifiableModel(); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + modifyableModel.addRoot(root, OrderRootType.CLASSES); + modifyableModel.commit(); + } + }); + final PsiClass aClass = manager.findClass("pack.MyClass", GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(myModule)); + assertNotNull(aClass); + assertTrue(Arrays.asList(rootModel2.orderEntries().librariesOnly().classes().getRoots()).contains(root)); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + rootModel2.commit(); + } + }); + final PsiClass aClass1 = manager.findClass("pack.MyClass", GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(myModule)); + assertNotNull(aClass1); + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/ClsRepositoryUseTest.java b/java/java-tests/testSrc/com/intellij/psi/ClsRepositoryUseTest.java new file mode 100644 index 000000000000..118f43b85c5c --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/ClsRepositoryUseTest.java @@ -0,0 +1,666 @@ +package com.intellij.psi; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileFilter; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiUtil; +import com.intellij.testFramework.PsiTestCase; +import com.intellij.testFramework.PsiTestUtil; + +import java.io.File; + +public class ClsRepositoryUseTest extends PsiTestCase{ + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.ClsRepositoryUseTest"); + private static final String TEST_ROOT = PathManagerEx.getTestDataPath() + "/psi/repositoryUse/cls"; + private GlobalSearchScope RESOLVE_SCOPE; + + public ClsRepositoryUseTest() { + myRunCommandForTest = true; + } + + protected void setUp() throws Exception { + super.setUp(); + + RESOLVE_SCOPE = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(myModule); + + ApplicationManager.getApplication().runWriteAction( + new Runnable() { + public void run() { + try{ + VirtualFile vDir = getRootFile(); + PsiTestUtil.removeAllRoots(myModule, JavaSdkImpl.getMockJdk17()); + addLibraryToRoots(vDir, OrderRootType.CLASSES); +// PsiTestUtil.addSourceContentToRoots(myProject, vDir); + } + catch(Exception e){ + LOG.error(e); + } + } + } + ); + } + + protected void tearDown() throws Exception { + RESOLVE_SCOPE = null; + super.tearDown(); + } + + public void testClassFileUpdate() throws Exception { + final File classes = createTempDir("classes"); + + final File com = new File(classes, "com"); + com.mkdir(); + + File dataPath = new File(PathManagerEx.getTestDataPath() + "/psi/cls"); + + + final File target = new File(com, "TestClass.class"); + FileUtil.copy(new File(dataPath, "1/TestClass.class"), target); + target.setLastModified(System.currentTimeMillis()); + + ApplicationManager.getApplication().runWriteAction( + new Runnable() { + public void run() { + try{ + VirtualFile vDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(classes); + assertNotNull(vDir); + addLibraryToRoots(vDir, OrderRootType.CLASSES); + } + catch(Exception e){ + LOG.error(e); + } + } + } + ); + + PsiClass psiClass = myJavaFacade.findClass("com.TestClass", GlobalSearchScope.allScope(myProject)); + PsiJavaFile psiFile = (PsiJavaFile)psiClass.getContainingFile(); + final VirtualFile vFile = psiFile.getVirtualFile(); + + assertNotNull(psiClass); + assertTrue(psiClass.isValid()); + assertTrue(psiFile.isValid()); + + assertEquals(1, psiFile.getClasses().length); + assertSame(psiClass, psiFile.getClasses()[0]); + + assertEquals(2, psiClass.getFields().length); + assertEquals("field11", psiClass.getFields()[0].getName()); + assertEquals("field12", psiClass.getFields()[1].getName()); + + assertEquals(2, psiClass.getMethods().length); + assertEquals("TestClass", psiClass.getMethods()[0].getName()); + assertEquals("method1", psiClass.getMethods()[1].getName()); + + FileUtil.copy(new File(dataPath, "2/TestClass.class"), target); + target.setLastModified(System.currentTimeMillis() + 5000); + + ApplicationManager.getApplication().runWriteAction( + new Runnable() { + public void run() { + try{ + vFile.refresh(false, false); + } + catch(Exception e){ + LOG.error(e); + } + } + } + ); + + assertTrue(psiFile.isValid()); + PsiClass oldClass = psiClass; + psiClass = myJavaFacade.findClass("com.TestClass", GlobalSearchScope.allScope(myProject)); + assertNotSame(oldClass, psiClass); + assertFalse(oldClass.isValid()); + + assertNotNull(psiClass); + assertEquals(1, psiFile.getClasses().length); + assertSame(psiClass, psiFile.getClasses()[0]); + + assertTrue(psiClass.isValid()); + assertEquals(1, psiClass.getFields().length); + assertEquals("field2", psiClass.getFields()[0].getName()); + + assertEquals(2, psiClass.getMethods().length); + assertEquals("TestClass", psiClass.getMethods()[0].getName()); + assertEquals("method2", psiClass.getMethods()[1].getName()); + } + + + private static VirtualFile getRootFile() { + VirtualFile vDir = LocalFileSystem.getInstance().findFileByPath(TEST_ROOT.replace(File.separatorChar, '/')); + return vDir; + } + + public void testGetClasses(){ + final VirtualFile rootFile = getRootFile(); + VirtualFile child = rootFile.findChild("pack").findChild("MyClass.class"); + assertNotNull(child); + PsiJavaFile file = (PsiJavaFile)myPsiManager.findFile(child); + checkValid(file); + PsiClass[] classes = file.getClasses(); + assertTrue(classes.length == 1); + PsiClass aClass = classes[0]; + checkValid(aClass); + assertEquals(file, aClass.getParent()); + } + + public void testGetClassName(){ + final VirtualFile rootFile = getRootFile(); + VirtualFile child = rootFile.findChild("pack").findChild("MyClass.class"); + assertNotNull(child); + PsiJavaFile file = (PsiJavaFile)myPsiManager.findFile(child); + PsiClass[] classes = file.getClasses(); + assertTrue(classes.length == 1); + + PsiClass aClass = classes[0]; + checkValid(aClass); + assertEquals("MyClass", aClass.getName()); + } + + public void testGetClassQName(){ + final VirtualFile rootFile = getRootFile(); + VirtualFile child = rootFile.findChild("pack").findChild("MyClass.class"); + assertNotNull(child); + PsiJavaFile file = (PsiJavaFile)myPsiManager.findFile(child); + PsiClass[] classes = file.getClasses(); + assertTrue(classes.length == 1); + + PsiClass aClass = classes[0]; + checkValid(aClass); + assertEquals("pack.MyClass", aClass.getQualifiedName()); + } + + public void testGetContainingFile(){ + final VirtualFile rootFile = getRootFile(); + VirtualFile child = rootFile.findChild("pack").findChild("MyClass.class"); + assertNotNull(child); + PsiJavaFile file = (PsiJavaFile)myPsiManager.findFile(child); + PsiClass[] classes = file.getClasses(); + assertTrue(classes.length == 1); + + PsiClass aClass = classes[0]; + checkValid(aClass); + assertEquals(file, aClass.getContainingFile()); + } + + public void testFindClass(){ + getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.ALL); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + assertNotNull(aClass); + checkValid(aClass); + + getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE); + } + + public void testIsInterface(){ + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + assertTrue(!aClass.isInterface()); + } + + private static void checkValid(final PsiElement elt) { + assertTrue(elt.isValid()); + } + + public void testPackageName(){ + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + String packageName = ((PsiJavaFile)aClass.getContainingFile()).getPackageName(); + assertEquals("pack", packageName); + } + + public void testGetFields(){ + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + PsiField[] fields = aClass.getFields(); + assertEquals(2, fields.length); + assertEquals(aClass, fields[0].getParent()); + } + + public void testGetMethods(){ + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + PsiMethod[] methods = aClass.getMethods(); + assertEquals(3, methods.length); + assertEquals(aClass, methods[0].getParent()); + } + + public void testGetInnerClasses(){ + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + PsiClass[] inners = aClass.getInnerClasses(); + assertEquals(1, inners.length); + assertEquals(aClass, inners[0].getParent()); + } + + public void testModifierList() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + PsiModifierList modifierList = aClass.getModifierList(); + assertTrue(modifierList.hasModifierProperty(PsiModifier.PUBLIC)); + assertTrue(modifierList.hasModifierProperty(PsiModifier.STATIC)); + assertEquals(modifierList.getParent(), aClass); + + PsiField field = aClass.getFields()[0]; + modifierList = field.getModifierList(); + assertTrue(modifierList.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)); + assertEquals(modifierList.getParent(), field); + + PsiMethod method = aClass.getMethods()[0]; + modifierList = method.getModifierList(); + assertTrue(modifierList.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)); + assertEquals(modifierList.getParent(), method); + } + + public void testGetFieldName(){ + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + assertEquals("field1", aClass.getFields()[0].getName()); + } + + public void testGetMethodName(){ + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + assertEquals("method1", aClass.getMethods()[0].getName()); + } + + public void testFindFieldByName(){ + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + PsiField field = aClass.findFieldByName("field1", false); + assertNotNull(field); + } + + public void testIsDeprecated(){ + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + assertTrue(!aClass.isDeprecated()); + + PsiField field = aClass.findFieldByName("field1", false); + assertTrue(field.isDeprecated()); + } + + public void testFieldType() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + + PsiField field1 = aClass.getFields()[0]; + PsiType type1 = field1.getType(); + + PsiField field2 = aClass.getFields()[1]; + PsiType type2 = field2.getType(); + + assertEquals(PsiType.INT, type1); + assertTrue(type2.equalsToText("java.lang.Object[]")); + + assertEquals("int", type1.getPresentableText()); + assertEquals("Object[]", type2.getPresentableText()); + + assertTrue(type1 instanceof PsiPrimitiveType); + assertTrue(!(type1 instanceof PsiArrayType)); + assertTrue(!(type2 instanceof PsiPrimitiveType)); + assertTrue(type2 instanceof PsiArrayType); + } + + public void testMethodType() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + + PsiMethod method1 = aClass.getMethods()[0]; + PsiTypeElement type1 = method1.getReturnTypeElement(); + assertEquals(method1, type1.getParent()); + + assertEquals("void", type1.getText()); + assertTrue(type1.getType() instanceof PsiPrimitiveType); + assertTrue(!(type1.getType() instanceof PsiArrayType)); + + PsiMethod method3 = aClass.getMethods()[2]; + assertNull(method3.getReturnType()); + } + + public void testIsConstructor() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + + PsiMethod method1 = aClass.getMethods()[0]; + assertFalse(method1.isConstructor()); + + PsiMethod method3 = aClass.getMethods()[2]; + assertTrue(method3.isConstructor()); + } + + public void testComponentType() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + + PsiField field = aClass.getFields()[1]; + PsiType type = field.getType(); + LOG.assertTrue(type instanceof PsiArrayType); + PsiType componentType = ((PsiArrayType) type).getComponentType(); + + assertTrue(componentType.equalsToText("java.lang.Object")); + assertEquals("Object", componentType.getPresentableText()); + assertFalse(componentType instanceof PsiPrimitiveType); + assertFalse(componentType instanceof PsiArrayType); + } + + public void testTypeReference() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + + PsiField field1 = aClass.getFields()[0]; + PsiType type1 = field1.getType(); + assertNull(PsiUtil.resolveClassInType(type1)); + + PsiField field2 = aClass.getFields()[1]; + PsiType type2 = ((PsiArrayType) field2.getType()).getComponentType(); + assertTrue(type2 instanceof PsiClassType); + + assertTrue(type2.equalsToText("java.lang.Object")); + assertEquals("Object", type2.getPresentableText()); + } + + public void testResolveTypeReference() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + + PsiType type1 = aClass.getFields()[1].getType(); + PsiElement target1 = PsiUtil.resolveClassInType(type1); + assertNotNull(target1); + PsiClass objectClass = myJavaFacade.findClass("java.lang.Object", RESOLVE_SCOPE); + assertEquals(objectClass, target1); + } + + public void testInitializer() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + + PsiField field1 = aClass.getFields()[0]; + assertTrue(field1.hasInitializer()); + PsiLiteralExpression initializer = (PsiLiteralExpression)field1.getInitializer(); + assertEquals("123", initializer.getText()); + assertEquals(new Integer(123), initializer.getValue()); + assertEquals(PsiType.INT, initializer.getType()); + + PsiField field2 = aClass.getFields()[1]; + assertFalse(field2.hasInitializer()); + assertNull(field2.getInitializer()); + } + + public void testExtendsList() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + + PsiReferenceList list = aClass.getExtendsList(); + + PsiClassType[] refs = list.getReferencedTypes(); + assertEquals(1, refs.length); + assertEquals("ArrayList", refs[0].getPresentableText()); + assertEquals("java.util.ArrayList", refs[0].getCanonicalText()); + } + + public void testImplementsList() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + + PsiReferenceList list = aClass.getImplementsList(); + + PsiClassType[] refs = list.getReferencedTypes(); + assertEquals(1, refs.length); + assertEquals("Cloneable", refs[0].getPresentableText()); + assertEquals("java.lang.Cloneable", refs[0].getCanonicalText()); + } + + public void testThrowsList() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + + PsiReferenceList list = aClass.getMethods()[0].getThrowsList(); + + PsiClassType[] refs = list.getReferencedTypes(); + assertEquals(2, refs.length); + assertEquals("Exception", refs[0].getPresentableText()); + assertEquals("IOException", refs[1].getPresentableText()); + assertEquals("java.lang.Exception", refs[0].getCanonicalText()); + assertEquals("java.io.IOException", refs[1].getCanonicalText()); + } + + + public void testParameters() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + + PsiParameterList list = aClass.getMethods()[0].getParameterList(); + + PsiParameter[] parms = list.getParameters(); + assertEquals(2, parms.length); + + PsiType type1 = parms[0].getType(); + assertEquals("int[]", type1.getPresentableText()); + assertTrue(type1.equalsToText("int[]")); + assertTrue(type1 instanceof PsiArrayType); + assertFalse(type1 instanceof PsiPrimitiveType); + assertNull(PsiUtil.resolveClassInType(type1)); + + PsiType type2 = parms[1].getType(); + assertEquals("Object", type2.getPresentableText()); + assertTrue(type2.equalsToText("java.lang.Object")); + assertFalse(type2 instanceof PsiArrayType); + assertFalse(type2 instanceof PsiPrimitiveType); + PsiClass target2 = PsiUtil.resolveClassInType(type2); + assertNotNull(target2); + PsiClass objectClass = myJavaFacade.findClass("java.lang.Object", RESOLVE_SCOPE); + assertEquals(objectClass, target2); + + parms[0].getModifierList(); + } + + public void testGenericClass() throws Exception { + disableJdk(); + + PsiClass map = myJavaFacade.findClass("java.util.HashMap", RESOLVE_SCOPE); + PsiMethod entrySet = map.findMethodsByName("entrySet", false)[0]; + PsiClassType ret = (PsiClassType) entrySet.getReturnType(); + final PsiClassType.ClassResolveResult setResolveResult = ret.resolveGenerics(); + assertEquals("java.util.Set", setResolveResult.getElement().getQualifiedName()); + final PsiTypeParameter typeParameter = setResolveResult.getElement().getTypeParameters()[0]; + + final PsiType substResult = setResolveResult.getSubstitutor().substitute(typeParameter); + assertTrue(substResult instanceof PsiWildcardType); + assertTrue(((PsiWildcardType)substResult).isExtends()); + PsiClassType setType = (PsiClassType)((PsiWildcardType)substResult).getBound(); + final PsiClassType.ClassResolveResult setTypeResolveResult = setType.resolveGenerics(); + assertEquals("java.util.Map.Entry", setTypeResolveResult.getElement().getQualifiedName()); + final PsiTypeParameter[] typeParameters = setTypeResolveResult.getElement().getTypeParameters(); + assertEquals(2, typeParameters.length); + PsiType[] mapParams = new PsiType[]{ + setTypeResolveResult.getSubstitutor().substitute(typeParameters[0]), + setTypeResolveResult.getSubstitutor().substitute(typeParameters[1]) + }; + assertEquals(2, mapParams.length); + assertEquals("K", mapParams[0].getCanonicalText()); + assertTrue(((PsiClassType) mapParams[0]).resolve() instanceof PsiTypeParameter); + assertEquals("V", mapParams[1].getCanonicalText()); + assertTrue(((PsiClassType) mapParams[1]).resolve() instanceof PsiTypeParameter); + } + + private void disableJdk() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + rootModel.setSdk(null); + rootModel.commit(); + } + } + ); + } + + + public void testGenericReturnType() throws Exception { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + rootModel.setSdk(null); + rootModel.commit(); + } + } + ); + + final PsiClass map = myJavaFacade.findClass("java.util.Map", RESOLVE_SCOPE); + final PsiElementFactory factory = myJavaFacade.getElementFactory(); + final PsiClassType typeMapStringToInteger = + (PsiClassType) factory.createTypeFromText("java.util.Map ", null); + final PsiClassType.ClassResolveResult mapResolveResult = typeMapStringToInteger.resolveGenerics(); + assertTrue(mapResolveResult.getElement().equals(map)); + + final PsiMethod entrySetMethod = map.findMethodsByName("entrySet", false)[0]; + final PsiType entrySetReturnType = entrySetMethod.getReturnType(); + assertEquals("java.util.Set>", entrySetReturnType.getCanonicalText()); + final PsiSubstitutor substitutor = ((PsiClassType)entrySetReturnType).resolveGenerics().getSubstitutor(); + assertEquals("E of java.util.Set -> ? extends java.util.Map.Entry\n", substitutor.toString()); + final PsiType typeSetOfEntriesOfStringAndInteger = factory.createTypeFromText("java.util.Set>", null); + final PsiType substitutedEntrySetReturnType = mapResolveResult.getSubstitutor().substitute(entrySetReturnType); + assertTrue(typeSetOfEntriesOfStringAndInteger.equals(substitutedEntrySetReturnType)); + assertTrue(typeSetOfEntriesOfStringAndInteger.isAssignableFrom(substitutedEntrySetReturnType)); + } + + public void testGenericInheritance() throws Exception { + PsiJavaFile file = (PsiJavaFile)PsiFileFactory.getInstance(getProject()).createFileFromText("Dummy.java", "import java.util.*;\n" + + "class Dummy {\n" + + "{ Map list = new HashMap();}\n" + + "}"); + + PsiDeclarationStatement decl = (PsiDeclarationStatement) file.getClasses()[0].getInitializers()[0].getBody().getStatements()[0]; + PsiVariable list = (PsiVariable) decl.getDeclaredElements()[0]; + + assertTrue(list.getType().isAssignableFrom(list.getInitializer().getType())); + } + + public void testSimplerGenericInheritance() throws Exception { + PsiElementFactory factory = myJavaFacade.getElementFactory(); + PsiClass map = myJavaFacade.findClass("java.util.Map", RESOLVE_SCOPE); + PsiClass hashMap = myJavaFacade.findClass("java.util.HashMap", RESOLVE_SCOPE); + + assertTrue(factory.createType(map).isAssignableFrom(factory.createType(hashMap))); + } + + public void testAnnotations () throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.Annotated", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + + PsiAnnotation[] annotations = aClass.getModifierList().getAnnotations(); + assertTrue(annotations.length == 1); + assertTrue(annotations[0].getText().equals("@pack.Annotation")); + + PsiMethod[] methods = aClass.findMethodsByName("foo", false); + assertTrue(methods.length == 1); + annotations = methods[0].getModifierList().getAnnotations(); + assertTrue(annotations.length == 1); + assertTrue(annotations[0].getText().equals("@pack.Annotation")); + + PsiParameter[] params = methods[0].getParameterList().getParameters(); + assertTrue(params.length == 1); + annotations = params[0].getModifierList().getAnnotations(); + assertTrue(annotations.length == 1); + assertTrue(annotations[0].getText().equals("@pack.Annotation")); + + PsiField[] fields = aClass.getFields(); + assertTrue(fields.length == 1); + annotations = fields[0].getModifierList().getAnnotations(); + assertTrue(annotations.length == 1); + assertTrue(annotations[0].getText().equals("@pack.Annotation")); + } + + public void testAnnotationMethodDefault () throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.Annotation", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + + PsiMethod[] methods = aClass.findMethodsByName("value", false); + assertTrue(methods.length == 1 && methods[0] instanceof PsiAnnotationMethod); + PsiAnnotationMemberValue defaultValue = ((PsiAnnotationMethod)methods[0]).getDefaultValue(); + assertTrue(defaultValue != null); + } + + public void testEnum() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyEnum", GlobalSearchScope.allScope(myProject)); + checkValid(aClass); + + assertTrue(aClass.isEnum()); + PsiField[] fields = aClass.getFields(); + PsiClassType type = myJavaFacade.getElementFactory().createType(aClass); + checkEnumConstant("RED", fields[0], type); + checkEnumConstant("GREEN", fields[1], type); + checkEnumConstant("BLUE", fields[2], type); + } + + public void testVariance() throws Exception { + final PsiClass aClass = myJavaFacade.findClass("pack.Variance", RESOLVE_SCOPE); + checkValid(aClass); + final PsiMethod[] methodsByName = aClass.findMethodsByName("method", false); + assertEquals(1, methodsByName.length); + final PsiMethod methodsWithReturnType = methodsByName[0]; + final PsiType returnType = methodsWithReturnType.getReturnType(); + assertEquals("pack.Parametrized", returnType.getCanonicalText()); + + //TODO[ven, max]: After fix for loading decompiled stuff the result had been change. Need to discuss whether this is important + //enough to try to conform old output. + //assertEquals("public Parametrized method() { /* compiled code */ }", methodsWithReturnType.getText()); + assertEquals("public pack.Parametrized method() { /* compiled code */ }", methodsWithReturnType.getText()); + } + + private void checkEnumConstant(String name, PsiField field, PsiClassType type) { + assertEquals(name, field.getName()); + assertTrue(field instanceof PsiEnumConstant); + assertEquals(type, field.getType()); + } + + public void testInvariantParsing() throws Exception { + final PsiClass collection = myJavaFacade.findClass("pack.Variance", RESOLVE_SCOPE); + assertNotNull(collection); + final PsiMethod[] methods = collection.findMethodsByName("removeAll", false); + assertEquals(1, methods.length); + final PsiParameter[] parameters = methods[0].getParameterList().getParameters(); + assertEquals(1, parameters.length); + final PsiType parameterType = parameters[0].getType(); + assertTrue(parameterType instanceof PsiClassType); + final PsiClassType psiClassType = ((PsiClassType)parameterType); + final PsiClassType.ClassResolveResult resolveResult = psiClassType.resolveGenerics(); + final PsiTypeParameter[] typeParameters = resolveResult.getElement().getTypeParameters(); + assertEquals(1, typeParameters.length); + final PsiType substitution = resolveResult.getSubstitutor().substitute(typeParameters[0]); + assertTrue(substitution instanceof PsiWildcardType); + assertEquals(PsiWildcardType.createUnbounded(myPsiManager), substitution); + } + + public void testInvariantParsing2() throws Exception { + disableJdk(); + final PsiClass collection = myJavaFacade.findClass("java.util.Collection", RESOLVE_SCOPE); + assertNotNull(collection); + final PsiMethod[] methods = collection.findMethodsByName("removeAll", false); + assertEquals(1, methods.length); + final PsiParameter[] parameters = methods[0].getParameterList().getParameters(); + assertEquals(1, parameters.length); + final PsiType parameterType = parameters[0].getType(); + assertTrue(parameterType instanceof PsiClassType); + final PsiClassType psiClassType = ((PsiClassType)parameterType); + final PsiClassType.ClassResolveResult resolveResult = psiClassType.resolveGenerics(); + final PsiTypeParameter[] typeParameters = resolveResult.getElement().getTypeParameters(); + assertEquals(1, typeParameters.length); + final PsiType substitution = resolveResult.getSubstitutor().substitute(typeParameters[0]); + assertTrue(substitution instanceof PsiWildcardType); + assertEquals(PsiWildcardType.createUnbounded(myPsiManager), substitution); + } + +} diff --git a/java/java-tests/testSrc/com/intellij/psi/GenericsTestCase.java b/java/java-tests/testSrc/com/intellij/psi/GenericsTestCase.java new file mode 100644 index 000000000000..c30dbc3c3896 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/GenericsTestCase.java @@ -0,0 +1,39 @@ +package com.intellij.psi; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.LanguageLevelProjectExtension; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.testFramework.PsiTestCase; + +import java.io.File; + +/** + * @author dsl + */ +public abstract class GenericsTestCase extends PsiTestCase { + protected void setUp() throws Exception { + super.setUp(); + LanguageLevelProjectExtension.getInstance(myJavaFacade.getProject()).setLanguageLevel(LanguageLevel.JDK_1_5); + } + + protected ModifiableRootModel setupGenericSampleClasses() { + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + final String commonPath = PathManagerEx.getTestDataPath().replace(File.separatorChar, '/') + "/psi/types/src"; + final VirtualFile[] commonRoot = new VirtualFile[] { null }; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + commonRoot[0] = LocalFileSystem.getInstance().refreshAndFindFileByPath(commonPath); + } + }); + + final ContentEntry commonContentEntry = rootModel.addContentEntry(commonRoot[0]); + commonContentEntry.addSourceFolder(commonRoot[0], false); + return rootModel; + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java b/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java new file mode 100644 index 000000000000..7bfc6c089d44 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java @@ -0,0 +1,75 @@ +package com.intellij.psi; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.impl.source.PostprocessReformattingAspect; +import com.intellij.testFramework.PsiTestCase; + +import java.io.File; + +public class OptimizeImportsTest extends PsiTestCase{ + private static final String BASE_PATH = PathManagerEx.getTestDataPath() + "/psi/optimizeImports"; + + public void testSCR6138() throws Exception { doTest(); } + public void testSCR18364() throws Exception { doTest(); } + public void testEmptyImportInJsp() throws Exception { doTest(".jsp"); } + public void testStaticImports1() throws Exception { doTest(); } + public void testStaticImportsToOptimize() throws Exception { doTest(); } + public void testStaticImportsToOptimize2() throws Exception { doTest(); } + public void testEmptyImportList() throws Exception { doTest(); } + public void testIDEADEV10716() throws Exception { doTest(); } + public void testUnresolvedImports() throws Exception { doTest(); } + public void testUnresolvedImports2() throws Exception { doTest(); } + public void testNewImportListIsEmptyAndCommentPreserved() throws Exception { doTest(); } + public void testNewImportListIsEmptyAndJavaDocWithInvalidCodePreserved() throws Exception { doTest(); } + + protected Sdk getTestProjectJdk() { + return JavaSdkImpl.getMockJdk17("mock 1.5"); + } + + private void doTest() throws Exception { + final String extension = ".java"; + doTest(extension); + } + + private void doTest(final String extension) throws Exception { + CommandProcessor.getInstance().executeCommand( + getProject(), new Runnable() { + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + String fileName = getTestName(false) + extension; + try { + String text = loadFile(fileName); + PsiFile file = createFile(fileName, text); + + JavaCodeStyleManager.getInstance(myProject).optimizeImports(file); + PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting(); + PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); + String textAfter = loadFile(getTestName(false) + "_after" + extension); + String fileText = file.getText(); + assertEquals(textAfter, fileText); + } + catch (Exception e) { + LOG.error(e); + } + } + }); + } + }, "", ""); + + } + + private static String loadFile(String name) throws Exception { + String fullName = BASE_PATH + File.separatorChar + name; + String text = new String(FileUtil.loadFileText(new File(fullName))); + text = StringUtil.convertLineSeparators(text); + return text; + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java b/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java new file mode 100644 index 000000000000..2cf1b7a08558 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java @@ -0,0 +1,186 @@ +/* + * @author max + */ +package com.intellij.psi; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; +import com.intellij.openapi.roots.LanguageLevelProjectExtension; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.testFramework.PsiTestCase; +import com.intellij.testFramework.PsiTestUtil; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.indexing.StorageException; + +import java.util.Random; +import java.util.concurrent.CountDownLatch; + +public class PsiConcurrencyStressTest extends PsiTestCase { + + protected void setUp() throws Exception { + super.setUp(); + + ApplicationManager.getApplication().runWriteAction( + new Runnable() { + + public void run() { + try { + LanguageLevelProjectExtension.getInstance(myProject).setLanguageLevel(LanguageLevel.JDK_1_5); + String root = PathManagerEx.getTestDataPath() + "/psi/repositoryUse/src"; + PsiTestUtil.removeAllRoots(myModule, JavaSdkImpl.getMockJdk17()); + PsiTestUtil.createTestProjectStructure(myProject, myModule, root, myFilesToDelete); + } + catch(Exception e){ + LOG.error(e); + } + } + } + ); + } + + private PsiJavaFile myFile; + public void testStress() throws Exception { + int numOfThreads = 10; + final int readIterations = 50000; + final int writeIterations = 30; + + synchronized (this) { + PsiClass myClass = myJavaFacade.findClass("StressClass", GlobalSearchScope.allScope(myProject)); + assertNotNull(myClass); + myFile = (PsiJavaFile)myClass.getContainingFile(); + } + + final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject()); + + final CountDownLatch reads = new CountDownLatch(numOfThreads); + final Random random = new Random(); + for (int i = 0; i < numOfThreads; i++) { + new Thread(new Runnable() { + public void run() { + for (int i = 0; i < readIterations; i++) { + if (myPsiManager == null) return; + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + try { + readStep(random); + } + catch (StorageException e) { + LOG.error(e); + } + } + }); + } + + reads.countDown(); + } + }, "stress thread" + i).start(); + } + + final Document document = documentManager.getDocument(myFile); + + for (int i = 0; i < writeIterations; i++) { + Thread.sleep(100); + new WriteCommandAction(myProject, myFile) { + protected void run(final Result result) throws Throwable { + documentManager.commitAllDocuments(); + writeStep(random); + documentManager.commitAllDocuments(); + assertEquals(document.getText(), myFile.getText()); + } + }.execute(); + } + + reads.await(); + } + + private static void mark(final String s) { + //System.out.print(s); + //System.out.flush(); + } + + private synchronized PsiClass getPsiClass() { + assertTrue(myFile.isValid()); + PsiClass psiClass = myFile.getClasses()[0]; + assertTrue(psiClass.isValid()); + return psiClass; + } + + private synchronized void writeStep(final Random random) throws IncorrectOperationException { + switch (random.nextInt(2)) { + case 0 : + mark("+"); + getPsiClass().add(myJavaFacade.getElementFactory().createMethod("foo" + System.currentTimeMillis(), PsiType.FLOAT)); + break; + case 1 : + mark("-"); + final PsiMethod[] psiMethods = getPsiClass().getMethods(); + if (psiMethods.length > 0) { + psiMethods[random.nextInt(psiMethods.length)].delete(); + } + break; + } + } + + private void readStep(final Random random) throws StorageException { + PsiClass aClass = getPsiClass(); + switch (random.nextInt(5)) { + case 0 : + mark("v"); + aClass.getContainingFile().accept(new PsiRecursiveElementVisitor() {}); break; + + case 1 : + mark("m"); + aClass.getMethods(); + break; + + //case 2 : { + // mark("h"); + // psiFile.accept(new PsiRecursiveElementVisitor() { + // @Override public void visitElement(final PsiElement element) { + // super.visitElement(element); + // + // final HighlightInfoHolder infoHolder = new HighlightInfoHolder(psiFile, HighlightInfoFilter.EMPTY_ARRAY); + // infoHolder.setWritable(true); + // new HighlightVisitorImpl(getPsiManager()).visit(element, infoHolder); + // } + // }); + // break; + //} + + case 3 : + mark("u"); + //FileBasedIndex.getInstance().ensureUpToDate(StubUpdatingIndex.INDEX_ID); + break; + case 4 : + mark("\n"); + break; + + } + } + + protected void invokeTestRunnable(final Runnable runnable) throws Exception { + final Exception[] e = new Exception[1]; + Runnable runnable1 = new Runnable() { + public void run() { + runnable.run(); + } + }; + + if (myRunCommandForTest) { + CommandProcessor.getInstance().executeCommand(myProject, runnable1, "", null); + } + else { + runnable1.run(); + } + + if (e[0] != null) { + throw e[0]; + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/SCR17094Test.java b/java/java-tests/testSrc/com/intellij/psi/SCR17094Test.java new file mode 100644 index 000000000000..e0129a1a1de2 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/SCR17094Test.java @@ -0,0 +1,59 @@ +package com.intellij.psi; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.testFramework.PsiTestCase; + +import java.io.File; + +/** + * @author dsl + */ +public class SCR17094Test extends PsiTestCase { + protected void setUpClasses(final String s) throws Exception { + final String testRoot = PathManagerEx.getTestDataPath() + "/psi/repositoryUse/scr17094"; + VirtualFile classesRoot = ApplicationManager.getApplication().runWriteAction(new Computable() { + public VirtualFile compute() { + String path = testRoot + "/" + s; + path = path.replace(File.separatorChar, '/'); + return LocalFileSystem.getInstance().refreshAndFindFileByPath(path); + } + }); + assertNotNull(classesRoot); + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + final Library.ModifiableModel libraryModel = rootModel.getModuleLibraryTable().createLibrary().getModifiableModel(); + libraryModel.addRoot(classesRoot, OrderRootType.CLASSES); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + libraryModel.commit(); + rootModel.commit(); + } + }); + } + + protected void setUpJdk() { + + } + + public void testSRC() throws Exception { + setUpClasses("classes"); + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiClass classA = psiManager.findClass("a.a.a.a.e.f.i", GlobalSearchScope.moduleWithLibrariesScope(myModule)); + assertNotNull(classA); + } + + public void test3() throws Exception { + setUpClasses("classes2"); + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiClass classA = psiManager.findClass("com.intellij.internal.f.a.b.a.i", GlobalSearchScope.moduleWithLibrariesScope(myModule)); + assertNotNull(classA); + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/Src15RepositoryUseTest.java b/java/java-tests/testSrc/com/intellij/psi/Src15RepositoryUseTest.java new file mode 100644 index 000000000000..67fa0e627e82 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/Src15RepositoryUseTest.java @@ -0,0 +1,332 @@ +package com.intellij.psi; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; +import com.intellij.openapi.roots.LanguageLevelProjectExtension; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileFilter; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.searches.AnnotatedMembersSearch; +import com.intellij.psi.search.searches.AnnotatedPackagesSearch; +import com.intellij.psi.search.searches.ClassInheritorsSearch; +import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.testFramework.PsiTestCase; +import com.intellij.testFramework.PsiTestUtil; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * @author dsl + */ +public class Src15RepositoryUseTest extends PsiTestCase { + + public Src15RepositoryUseTest() { + myRunCommandForTest = true; + } + + protected void setUp() throws Exception { + super.setUp(); + + ApplicationManager.getApplication().runWriteAction( + new Runnable() { + + public void run() { + try { + LanguageLevelProjectExtension.getInstance(myProject).setLanguageLevel(LanguageLevel.JDK_1_5); + String root = PathManagerEx.getTestDataPath() + "/psi/repositoryUse/src15"; + PsiTestUtil.removeAllRoots(myModule, JavaSdkImpl.getMockJdk17("mock 1.5")); + PsiTestUtil.createTestProjectStructure(myProject, myModule, root, myFilesToDelete); + } + catch(Exception e){ + LOG.error(e); + } + } + } + ); + } + + protected Sdk getTestProjectJdk() { + return JavaSdkImpl.getMockJdk17("mock 1.5"); + } + + protected void tearDown() throws Exception { + LanguageLevelProjectExtension.getInstance(myProject).setLanguageLevel(LanguageLevel.JDK_1_5); + super.tearDown(); + } + + + public void testStaticImports() throws IOException { + setupLoadingFilter(); + + final PsiClass aClass = myJavaFacade.findClass("staticImports.StaticImports", GlobalSearchScope.moduleScope(myModule)); + assertNotNull(aClass); + final PsiJavaFile javaFile = (PsiJavaFile)aClass.getContainingFile(); + doTestStaticImports(javaFile, false); + teardownLoadingFilter(); + doTestStaticImports(javaFile, true); + } + + public void testDeprecatedAnnotation() throws IOException { + setupLoadingFilter(); + + final PsiClass aClass = myJavaFacade.findClass("annotations.DeprecatedAnnotation", GlobalSearchScope.moduleScope(myModule)); + assertNotNull(aClass); + assertTrue(aClass.isDeprecated()); + PsiMethod method = aClass.getMethods()[0]; + assertTrue(method.isDeprecated()); + PsiField field = aClass.getFields()[0]; + assertTrue(field.isDeprecated()); + teardownLoadingFilter(); + } + + public void testEnumImplements() { + setupLoadingFilter(); + + final PsiClass aClass = myJavaFacade.findClass("enumImplements.MyEnum", GlobalSearchScope.moduleScope(myModule)); + assertNotNull(aClass); + final PsiClassType[] implementsListTypes = aClass.getImplementsListTypes(); + assertEquals(1, implementsListTypes.length); + + final PsiClass baseInterface = implementsListTypes[0].resolve(); + assertNotNull(baseInterface); + assertEquals("I", baseInterface.getName()); + teardownLoadingFilter(); + } + + private void doTestStaticImports(final PsiJavaFile javaFile, boolean okToLoadTree) { + final PsiImportList importList = javaFile.getImportList(); + final PsiImportStatementBase[] allImportStatements = importList.getAllImportStatements(); + assertEquals(6, allImportStatements.length); + final PsiImportStatement[] importStatements = importList.getImportStatements(); + assertEquals(2, importStatements.length); + final PsiImportStaticStatement[] importStaticStatements = importList.getImportStaticStatements(); + assertEquals(4, importStaticStatements.length); + assertFalse(importStatements[0].isOnDemand()); + assertTrue(importStaticStatements[0].isOnDemand()); + assertFalse(importStatements[0].isOnDemand()); + assertTrue(importStaticStatements[1].isOnDemand()); + assertFalse(importStaticStatements[2].isOnDemand()); + assertFalse(importStaticStatements[3].isOnDemand()); + + assertEquals("sort", importStaticStatements[2].getReferenceName()); + assertEquals("sort", importStaticStatements[3].getReferenceName()); + + final PsiImportStaticStatement classReference1 = importStaticStatements[1]; + final PsiElement element1 = classReference1.resolveTargetClass(); + assertNotNull(element1); + assertTrue(element1 instanceof PsiClass); + assertEquals("java.util.Arrays", ((PsiClass)element1).getQualifiedName()); + + final PsiImportStaticStatement classReference3 = importStaticStatements[3]; + final PsiElement element3 = classReference3.resolveTargetClass(); + assertNotNull(element3); + assertTrue(element3 instanceof PsiClass); + assertEquals("java.util.Arrays", ((PsiClass)element3).getQualifiedName()); + + if (okToLoadTree) { + assertEquals("java.util.Collections", importStaticStatements[0].getImportReference().getText()); + assertEquals("java.util.Arrays", importStaticStatements[1].getImportReference().getText()); + assertEquals("java.util.Collections.sort", importStaticStatements[2].getImportReference().getText()); + assertEquals("java.util.Arrays.sort", importStaticStatements[3].getImportReference().getText()); + } + } + + public void testEnum() throws Exception { + setupLoadingFilter(); + final PsiClass enumClass = myJavaFacade.findClass("enums.OurEnum", GlobalSearchScope.moduleScope(myModule)); + assertNotNull(enumClass); + assertTrue(enumClass.isEnum()); + final PsiClass superClass = enumClass.getSuperClass(); + assertNotNull(superClass); + assertEquals("java.lang.Enum", superClass.getQualifiedName()); + assertTrue(enumClass.isInheritor(superClass, false)); + final PsiClassType[] superTypes = enumClass.getSuperTypes(); + assertEquals(1, superTypes.length); + assertEquals("java.lang.Enum", superTypes[0].getCanonicalText()); + final PsiClass[] supers = enumClass.getSupers(); + assertEquals(1, supers.length); + assertEquals("java.lang.Enum", supers[0].getQualifiedName()); + final PsiClassType[] extendsListTypes = enumClass.getExtendsListTypes(); + assertEquals(1, extendsListTypes.length); + assertEquals("java.lang.Enum", extendsListTypes[0].getCanonicalText()); + final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, enumClass, PsiSubstitutor.EMPTY); + assertEquals("java.lang.Enum", myJavaFacade.getElementFactory().createType(superClass, superClassSubstitutor).getCanonicalText()); + teardownLoadingFilter(); + } + + public void testEnumWithConstants() throws Exception { + setupLoadingFilter(); + PsiClass enumClass = myJavaFacade.findClass("enums.OurEnumWithConstants", GlobalSearchScope.moduleScope(myModule)); + assertNotNull(enumClass); + assertTrue(enumClass.isEnum()); + checkEnumWithConstants(enumClass, false); + teardownLoadingFilter(); + checkEnumWithConstants(enumClass, true); + } + + public void testEnumWithInitializedConstants() throws Exception { + setupLoadingFilter(); + final GlobalSearchScope moduleScope = GlobalSearchScope.moduleScope(myModule); + PsiClass enumClass = myJavaFacade.findClass("enums.OurEnumWithInitializedConstants", moduleScope); + assertNotNull(enumClass); + assertTrue(enumClass.isEnum()); + PsiField[] fields = enumClass.getFields(); + assertEquals(3, fields.length); + assertTrue(fields[0] instanceof PsiEnumConstant); + assertTrue(fields[1] instanceof PsiEnumConstant); + assertTrue(fields[2] instanceof PsiEnumConstant); + PsiAnonymousClass initializingClass0 = ((PsiEnumConstant)fields[0]).getInitializingClass(); + PsiClass baseClass0 = initializingClass0.getBaseClassType().resolve(); + assertTrue(baseClass0 == enumClass); + + PsiAnonymousClass initializingClass1 = ((PsiEnumConstant)fields[1]).getInitializingClass(); + PsiClass baseClass1 = initializingClass1.getBaseClassType().resolve(); + assertTrue(baseClass1 == enumClass); + + + PsiAnonymousClass initializingClass2 = ((PsiEnumConstant)fields[1]).getInitializingClass(); + PsiClass baseClass2 = initializingClass2.getBaseClassType().resolve(); + assertTrue(baseClass2 == enumClass); + + assertTrue(initializingClass0.isInheritor(enumClass, false)); + assertTrue(initializingClass1.isInheritor(enumClass, false)); + assertTrue(initializingClass2.isInheritor(enumClass, false)); + + final PsiClass[] enumInheritors = ClassInheritorsSearch.search(enumClass, moduleScope, false).toArray(PsiClass.EMPTY_ARRAY); + assertEquals(3, enumInheritors.length); + assertTrue(Arrays.asList(enumInheritors).contains(initializingClass0)); + assertTrue(Arrays.asList(enumInheritors).contains(initializingClass1)); + assertTrue(Arrays.asList(enumInheritors).contains(initializingClass2)); + + + PsiMethod[] methods1 = initializingClass2.getMethods(); + assertEquals(1, methods1.length); + assertEquals("foo", methods1[0].getName()); + + final PsiClass baseInterfaceClass = myJavaFacade.findClass("enums.OurBaseInterface", GlobalSearchScope.moduleWithLibrariesScope(myModule)); + assertNotNull(baseInterfaceClass); + + final PsiClass[] inheritors = ClassInheritorsSearch.search(baseInterfaceClass, moduleScope, false).toArray(PsiClass.EMPTY_ARRAY); + assertEquals(1, inheritors.length); + assertTrue(inheritors[0] instanceof PsiAnonymousClass); + + teardownLoadingFilter(); + + assertTrue(inheritors[0].getParent().getParent() instanceof PsiExpressionList); + assertTrue(inheritors[0].getParent().getParent().getParent() == fields[2]); + + final PsiExpression[] expressions2 = ((PsiEnumConstant)fields[2]).getArgumentList().getExpressions(); + assertEquals(1, expressions2.length); + assertTrue(expressions2[0] instanceof PsiNewExpression); + final PsiAnonymousClass anonymousClass2 = ((PsiNewExpression)expressions2[0]).getAnonymousClass(); + assertTrue(anonymousClass2 != null); + assertTrue(anonymousClass2.isInheritor(baseInterfaceClass, false)); + + } + + private void checkEnumWithConstants(PsiClass enumClass, boolean okToLoadTree) { + PsiField[] fields = enumClass.getFields(); + assertEquals(3, fields.length); + checkEnumConstant("A", fields[0]); + checkEnumConstant("B", fields[1]); + checkEnumConstant("C", fields[2]); + if (okToLoadTree) { + assertEquals("A", fields[0].getText()); + assertEquals("B", fields[1].getText()); + assertEquals("C", fields[2].getText()); + } + } + + private void checkEnumConstant(String expectedName, PsiField field) { + assertTrue(field instanceof PsiEnumConstant); + assertEquals(expectedName, field.getName()); + assertTrue(field.hasModifierProperty(PsiModifier.PUBLIC)); + assertTrue(field.hasModifierProperty(PsiModifier.FINAL)); + assertTrue(field.hasModifierProperty(PsiModifier.STATIC)); + } + + public void testEnumWithConstantsAndSastaticFields() throws Exception { + setupLoadingFilter(); + PsiClass enumClass = myJavaFacade.findClass("enums.OurEnumWithConstantsAndStaticFields", GlobalSearchScope.moduleScope(myModule)); + PsiField[] fields = enumClass.getFields(); + assertTrue(fields[0] instanceof PsiEnumConstant); + assertTrue(fields[1] instanceof PsiEnumConstant); + assertTrue(fields[2] instanceof PsiEnumConstant); + assertFalse(fields[3] instanceof PsiEnumConstant); + + teardownLoadingFilter(); + + assertEquals("public static final int A1 = 1;", fields[3].getText()); + } + + public void testEnumWithConstantsAndStaticFields2() throws Exception { + setupLoadingFilter(); + PsiClass enumClass = myJavaFacade.findClass("enums.OurEnumWithConstantsAndStaticFields2", GlobalSearchScope.moduleScope(myModule)); + PsiField[] fields = enumClass.getFields(); + assertTrue(fields[0] instanceof PsiEnumConstant); + assertTrue(fields[1] instanceof PsiEnumConstant); + assertTrue(fields[2] instanceof PsiEnumConstant); + assertFalse(fields[3] instanceof PsiEnumConstant); + + teardownLoadingFilter(); + + assertEquals("public static final int A1 = 10;", fields[3].getText()); + enumClass.accept(new JavaRecursiveElementWalkingVisitor(){ + @Override public void visitReferenceExpression(PsiReferenceExpression expression) { + visitExpression(expression); + } + }); + enumClass.getText(); + } + + private void teardownLoadingFilter() { + getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE); + } + + private void setupLoadingFilter() { + getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.ALL); + } + + + public void testAnnotationType() throws Exception { + setupLoadingFilter(); + final PsiClass annotationTypeClass = myJavaFacade.findClass("annotations.AnnotationType", GlobalSearchScope.moduleScope(myModule)); + assertNotNull(annotationTypeClass); + assertTrue(annotationTypeClass.isAnnotationType()); + teardownLoadingFilter(); + } + + public void testAnnotationIndex() throws Exception { + getJavaFacade().setAssertOnFileLoadingFilter(new VirtualFileFilter() { + public boolean accept(final VirtualFile file) { + return !"package-info.java".equals(file.getName()); + } + }); + + final PsiClass annotationTypeClass = myJavaFacade.findClass("annotations.AnnotationType", GlobalSearchScope.moduleScope(myModule)); + assertNotNull(annotationTypeClass); + assertTrue(annotationTypeClass.isAnnotationType()); + + final Collection all = AnnotatedMembersSearch.search(annotationTypeClass, GlobalSearchScope.moduleScope(myModule)).findAll(); + + assertEquals(2, all.size()); + Set correctNames = new HashSet(Arrays.asList("AnnotatedClass", "correctMethod")); + for (PsiMember member : all) { + assertTrue(correctNames.contains(member.getName())); + } + + final Collection packages = + AnnotatedPackagesSearch.search(annotationTypeClass, GlobalSearchScope.moduleScope(myModule)).findAll(); + assertEquals(1, packages.size()); + assertEquals("annotated", packages.iterator().next().getQualifiedName()); + + teardownLoadingFilter(); + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/SrcRepositoryUseTest.java b/java/java-tests/testSrc/com/intellij/psi/SrcRepositoryUseTest.java new file mode 100644 index 000000000000..d8628f1ce6c5 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/SrcRepositoryUseTest.java @@ -0,0 +1,829 @@ +package com.intellij.psi; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; +import com.intellij.openapi.projectRoots.impl.ProjectRootUtil; +import com.intellij.openapi.roots.*; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileFilter; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.impl.source.PsiFileImpl; +import com.intellij.psi.impl.source.tree.CompositeElement; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.searches.ClassInheritorsSearch; +import com.intellij.psi.text.BlockSupport; +import com.intellij.psi.util.PsiUtil; +import com.intellij.refactoring.rename.RenameProcessor; +import com.intellij.testFramework.PsiTestCase; +import com.intellij.testFramework.PsiTestUtil; + +import java.io.File; +import java.io.IOException; + +public class SrcRepositoryUseTest extends PsiTestCase{ + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.SrcRepositoryUseTest"); + private static final Key TEST_KEY = Key.create("TEST"); + + public SrcRepositoryUseTest() { + myRunCommandForTest = true; + } + + protected void setUp() throws Exception { + super.setUp(); + + ApplicationManager.getApplication().runWriteAction( + new Runnable() { + + public void run() { + try { + LanguageLevelProjectExtension.getInstance(myProject).setLanguageLevel(LanguageLevel.JDK_1_5); + String root = PathManagerEx.getTestDataPath() + "/psi/repositoryUse/src"; + PsiTestUtil.removeAllRoots(myModule, JavaSdkImpl.getMockJdk17()); + PsiTestUtil.createTestProjectStructure(myProject, myModule, root, myFilesToDelete); + } + catch(Exception e){ + LOG.error(e); + } + } + } + ); + } + + public void testGetClasses(){ + setupLoadingFilter(); + + PsiDirectory root = ProjectRootUtil.getAllContentRoots(myProject) [0]; + VirtualFile child = root.getVirtualFile().findChild("MyClass1.java"); + assertNotNull(child); + PsiJavaFile file = (PsiJavaFile)myPsiManager.findFile(child); + PsiClass[] classes = file.getClasses(); + assertEquals(2, classes.length); + assertEquals(file, classes[0].getParent()); + + teardownLoadingFilter(); + } + + public void testGetClassName(){ + setupLoadingFilter(); + + PsiDirectory root = ProjectRootUtil.getAllContentRoots(myProject) [0]; + VirtualFile child = root.getVirtualFile().findChild("MyClass1.java"); + assertNotNull(child); + PsiJavaFile file = (PsiJavaFile)myPsiManager.findFile(child); + PsiClass[] classes = file.getClasses(); + assertEquals(2, classes.length); + + assertEquals("MyClass1", classes[0].getName()); + assertEquals("Class2", classes[1].getName()); + + teardownLoadingFilter(); + } + + public void testClassParameter() { + setupLoadingFilter(); + PsiClass psiClass = myJavaFacade.findClass("Class2", GlobalSearchScope.allScope(myProject)); + assertNotNull(psiClass); + + PsiTypeParameterList parameterList = psiClass.getTypeParameterList(); + assertNotNull(parameterList); + PsiTypeParameter[] params = parameterList.getTypeParameters(); + assertEquals(params.length, 2); + + assertEquals(params[0].getName(), "A"); + assertEquals(params[1].getName(), "B"); + + assertEquals("java.lang.String", params[0].getSupers()[0].getQualifiedName()); + assertEquals("java.lang.Object", params[1].getSupers()[0].getQualifiedName()); + + teardownLoadingFilter(); + } + + public void testGetClassQName(){ + setupLoadingFilter(); + + PsiDirectory root = ProjectRootUtil.getAllContentRoots(myProject) [0]; + VirtualFile child = root.getVirtualFile().findChild("pack").findChild("MyClass2.java"); + assertNotNull(child); + PsiJavaFile file = (PsiJavaFile)myPsiManager.findFile(child); + PsiClass[] classes = file.getClasses(); + assertEquals(1, classes.length); + + assertEquals("pack.MyClass2", classes[0].getQualifiedName()); + + teardownLoadingFilter(); + } + + public void testGetFields(){ + setupLoadingFilter(); + + PsiDirectory root = ProjectRootUtil.getAllContentRoots(myProject) [0]; + VirtualFile child = root.getVirtualFile().findChild("pack").findChild("MyClass2.java"); + assertNotNull(child); + PsiJavaFile file = (PsiJavaFile)myPsiManager.findFile(child); + PsiClass[] classes = file.getClasses(); + assertEquals(1, classes.length); + + PsiClass aClass = classes[0]; + PsiField[] fields = aClass.getFields(); + assertEquals(3, fields.length); + assertEquals(aClass, fields[0].getParent()); + + teardownLoadingFilter(); + } + + public void testGetMethods(){ + setupLoadingFilter(); + + PsiDirectory root = ProjectRootUtil.getAllContentRoots(myProject) [0]; + VirtualFile child = root.getVirtualFile().findChild("pack").findChild("MyClass2.java"); + assertNotNull(child); + PsiJavaFile file = (PsiJavaFile)myPsiManager.findFile(child); + PsiClass[] classes = file.getClasses(); + assertEquals(1, classes.length); + + PsiClass aClass = classes[0]; + PsiMethod[] methods = aClass.getMethods(); + assertEquals(3, methods.length); + assertEquals(aClass, methods[0].getParent()); + + teardownLoadingFilter(); + } + + public void testGetInnerClasses(){ + setupLoadingFilter(); + + PsiDirectory root = ProjectRootUtil.getAllContentRoots(myProject) [0]; + VirtualFile child = root.getVirtualFile().findChild("pack").findChild("MyClass2.java"); + assertNotNull(child); + PsiJavaFile file = (PsiJavaFile)myPsiManager.findFile(child); + PsiClass[] classes = file.getClasses(); + assertEquals(1, classes.length); + + PsiClass aClass = classes[0]; + PsiClass[] inners = aClass.getInnerClasses(); + assertEquals(1, inners.length); + assertEquals(aClass, inners[0].getParent()); + + teardownLoadingFilter(); + } + public void testResolveSuperClass(){ + setupLoadingFilter(); + + PsiDirectory root = ProjectRootUtil.getAllContentRoots(myProject) [0]; + VirtualFile child = root.getVirtualFile().findChild("pack").findChild("MyClass2.java"); + assertNotNull(child); + PsiJavaFile file = (PsiJavaFile)myPsiManager.findFile(child); + PsiClass[] classes = file.getClasses(); + assertEquals(1, classes.length); + + PsiClass aClass = classes[0]; + PsiClass[] superTypes = aClass.getSupers(); + LOG.assertTrue(superTypes.length == 2); + LOG.assertTrue(superTypes[0].getQualifiedName().equals("java.lang.String")); + LOG.assertTrue(superTypes[1].getQualifiedName().equals("java.lang.Runnable")); + + teardownLoadingFilter(); + } + + public void testGetContainingFile(){ + setupLoadingFilter(); + + PsiDirectory root = ProjectRootUtil.getAllContentRoots(myProject) [0]; + VirtualFile child = root.getVirtualFile().findChild("pack").findChild("MyClass2.java"); + assertNotNull(child); + PsiJavaFile file = (PsiJavaFile)myPsiManager.findFile(child); + PsiClass[] classes = file.getClasses(); + assertEquals(1, classes.length); + + assertEquals(file, classes[0].getContainingFile()); + + teardownLoadingFilter(); + } + + public void testFindClass(){ + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + assertNotNull(aClass); + + teardownLoadingFilter(); + } + + public void testGetFieldName(){ + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + assertEquals("field1", aClass.getFields()[0].getName()); + + teardownLoadingFilter(); + } + + public void testGetMethodName(){ + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + assertEquals("method1", aClass.getMethods()[0].getName()); + + teardownLoadingFilter(); + } + + public void testModifierList() throws Exception { + setupLoadingFilter(); + + PsiModifierList modifierList; + { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + + modifierList = aClass.getModifierList(); + assertTrue(modifierList.hasModifierProperty(PsiModifier.PUBLIC)); + assertTrue(!modifierList.hasModifierProperty(PsiModifier.STATIC)); + assertEquals(modifierList.getParent(), aClass); + + PsiField field = aClass.getFields()[0]; + modifierList = field.getModifierList(); + assertTrue(modifierList.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)); + assertEquals(modifierList.getParent(), field); + + PsiMethod method = aClass.getMethods()[0]; + modifierList = method.getModifierList(); + assertTrue(modifierList.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)); + assertEquals(modifierList.getParent(), method); + + teardownLoadingFilter(); + method = null; + } + + + for (int i = 0; i < 2; i++) { + System.gc(); + Thread.sleep(200); + } + + modifierList.getChildren(); + } + + public void testIsInterface(){ + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + assertTrue(!aClass.isInterface()); + + PsiClass anInterface = myJavaFacade.findClass("pack.MyInterface1", GlobalSearchScope.allScope(myProject)); + assertTrue(anInterface.isInterface()); + + teardownLoadingFilter(); + } + + public void testFindFieldByName(){ + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + PsiField field = aClass.findFieldByName("field1", false); + assertNotNull(field); + + teardownLoadingFilter(); + } + + public void testIsDeprecated(){ + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + assertTrue(!aClass.isDeprecated()); + + PsiField field = aClass.findFieldByName("field1", false); + assertTrue(field.isDeprecated()); + + teardownLoadingFilter(); + } + + public void testPackageName(){ + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + String packageName = ((PsiJavaFile)aClass.getContainingFile()).getPackageName(); + assertEquals("pack", packageName); + + teardownLoadingFilter(); + } + + public void testFieldType() throws Exception { + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + + PsiField field1 = aClass.getFields()[0]; + PsiType type1 = field1.getType(); + + PsiField field2 = aClass.getFields()[1]; + PsiType type2 = field2.getType(); + + PsiField field3 = aClass.getFields()[2]; + PsiType type3 = field3.getType(); + + assertEquals("int", type1.getPresentableText()); + assertEquals("Object[]", type2.getPresentableText()); + assertEquals("Object[]", type3.getPresentableText()); + + assertTrue(type1.equalsToText("int")); + assertTrue(type2.equalsToText("java.lang.Object[]")); + assertTrue(type3.equalsToText("java.lang.Object[]")); + + assertTrue(!(type1 instanceof PsiArrayType)); + assertTrue(type1 instanceof PsiPrimitiveType); + assertTrue(!(type3 instanceof PsiPrimitiveType)); + assertTrue(type3 instanceof PsiArrayType); + + teardownLoadingFilter(); + } + + public void testHasInitializer() throws Exception { + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + + assertTrue(aClass.getFields()[0].hasInitializer()); + assertFalse(aClass.getFields()[1].hasInitializer()); + assertFalse(aClass.getFields()[2].hasInitializer()); + + teardownLoadingFilter(); + } + + public void testMethodType() throws Exception { + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + + PsiMethod method1 = aClass.getMethods()[0]; + PsiType type1 = method1.getReturnType(); + + assertTrue(type1.equalsToText("void")); + assertTrue(!(type1 instanceof PsiArrayType)); + assertTrue(type1 instanceof PsiPrimitiveType); + + PsiMethod method3 = aClass.getMethods()[2]; + assertNull(method3.getReturnType()); + + teardownLoadingFilter(); + } + + public void testIsConstructor() throws Exception { + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + PsiMethod method1 = aClass.getMethods()[0]; + assertFalse(method1.isConstructor()); + + teardownLoadingFilter(); + } + + public void testComponentType() throws Exception { + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + + PsiField field = aClass.getFields()[2]; + PsiType type = field.getType(); + LOG.assertTrue(type instanceof PsiArrayType); + PsiType componentType = ((PsiArrayType) type).getComponentType(); + + assertTrue(componentType.equalsToText("java.lang.Object")); + assertFalse(componentType instanceof PsiPrimitiveType); + assertFalse(componentType instanceof PsiArrayType); + + teardownLoadingFilter(); + } + + public void testTypeReference() throws Exception { + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + + PsiField field1 = aClass.getFields()[0]; + PsiType type1 = field1.getType(); + assertNull(PsiUtil.resolveClassInType(type1)); + + PsiField field2 = aClass.getFields()[1]; + PsiType type2 = ((PsiArrayType) field2.getType()).getComponentType(); + assertEquals("Object", type2.getPresentableText()); + + PsiField field3 = aClass.getFields()[2]; + PsiType type3 = ((PsiArrayType) field3.getType()).getComponentType(); + assertTrue(type3.equalsToText("java.lang.Object")); + + teardownLoadingFilter(); + } + + public void testImportList(){ + setupLoadingFilter(); + + PsiDirectory root = ProjectRootUtil.getAllContentRoots(myProject) [0]; + VirtualFile child = root.getVirtualFile().findChild("MyClass1.java"); + assertNotNull(child); + PsiJavaFile file = (PsiJavaFile)myPsiManager.findFile(child); + PsiImportList list = file.getImportList(); + assertEquals(file, list.getParent()); + + PsiImportStatement[] imports = list.getImportStatements(); + assertEquals(3, imports.length); + assertFalse(imports[0].isOnDemand()); + assertTrue(imports[1].isOnDemand()); + imports[2].isOnDemand(); + + String ref1 = imports[0].getQualifiedName(); + String ref2 = imports[1].getQualifiedName(); + String ref3 = imports[2].getQualifiedName(); + + assertEquals("a.b", ref1); + assertEquals("c", ref2); + assertNull(ref3); + + teardownLoadingFilter(); + } + + public void testResolveTypeReference() throws Exception { + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + + PsiType type1 = aClass.getFields()[1].getType(); + PsiElement target1 = PsiUtil.resolveClassInType(type1); + assertNotNull(target1); + PsiClass objectClass = myJavaFacade.findClass("java.lang.Object", GlobalSearchScope.allScope(myProject)); + assertEquals(objectClass, target1); + + PsiType type2 = aClass.getFields()[1].getType(); + PsiElement target2 = PsiUtil.resolveClassInType(type2); + assertNotNull(target2); + assertEquals(objectClass, target2); + + teardownLoadingFilter(); + } + + public void testExtendsList() throws Exception { + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + + PsiReferenceList list = aClass.getExtendsList(); + + PsiClassType[] refs = list.getReferencedTypes(); + assertEquals(1, refs.length); + assertEquals("String", refs[0].getPresentableText()); + + teardownLoadingFilter(); + } + + public void testImplementsList() throws Exception { + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + + PsiReferenceList list = aClass.getImplementsList(); + + PsiClassType[] refs = list.getReferencedTypes(); + assertEquals(1, refs.length); + assertEquals("Runnable", refs[0].getPresentableText()); + + teardownLoadingFilter(); + } + + public void testThrowsList() throws Exception { + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + + PsiReferenceList list = aClass.getMethods()[0].getThrowsList(); + + PsiClassType[] refs = list.getReferencedTypes(); + assertEquals(2, refs.length); + assertEquals("Exception", refs[0].getPresentableText()); + assertEquals("java.io.IOException", refs[1].getCanonicalText()); + + teardownLoadingFilter(); + } + + public void testParameters() throws Exception { + setupLoadingFilter(); + + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + + PsiParameterList list = aClass.getMethods()[0].getParameterList(); + + PsiParameter[] parms = list.getParameters(); + assertEquals(5, parms.length); + + assertEquals("p1", parms[0].getName()); + assertEquals("p2", parms[1].getName()); + assertEquals("p3", parms[2].getName()); + assertEquals("p4", parms[3].getName()); + assertEquals("p5", parms[4].getName()); + + PsiType type1 = parms[0].getType(); + assertEquals("int[]", type1.getPresentableText()); + assertFalse(type1 instanceof PsiPrimitiveType); + assertTrue(type1 instanceof PsiArrayType); + assertNull(PsiUtil.resolveClassInType(type1)); + + PsiType type2 = parms[1].getType(); + assertEquals("Object", type2.getPresentableText()); + assertFalse(type2 instanceof PsiArrayType); + assertFalse(type2 instanceof PsiPrimitiveType); + PsiClass target2 = PsiUtil.resolveClassInType(type2); + assertNotNull(target2); + PsiClass objectClass = myJavaFacade.findClass("java.lang.Object", GlobalSearchScope.allScope(myProject)); + assertEquals(objectClass, target2); + + checkPackAAA(parms[2].getType()); + checkPackAAA(parms[3].getType()); + checkPackAAA(parms[4].getType()); + + teardownLoadingFilter(); + + parms[0].getModifierList(); + } + + private static void checkPackAAA(PsiType type) { + assertEquals("AAA", type.getPresentableText()); + assertFalse(type instanceof PsiArrayType); + assertFalse(type instanceof PsiPrimitiveType); + PsiClass target3 = PsiUtil.resolveClassInType(type); + assertNull(target3); + assertEquals("pack.AAA", type.getCanonicalText()); + } + + public void testAnonymousClass() throws Exception { + setupLoadingFilter(); + + PsiClass cloneableClass = myJavaFacade.findClass("java.lang.Cloneable", GlobalSearchScope.allScope(myProject)); + PsiClass[] inheritors = ClassInheritorsSearch.search(cloneableClass, GlobalSearchScope.projectScope(myProject), true).toArray(PsiClass.EMPTY_ARRAY); + assertEquals(2, inheritors.length); + assertTrue(inheritors[0] instanceof PsiAnonymousClass || inheritors[1] instanceof PsiAnonymousClass); + PsiAnonymousClass anonClass = (PsiAnonymousClass)(inheritors[0] instanceof PsiAnonymousClass ? inheritors[0] : inheritors[1]); + + PsiClassType baseClassRef = anonClass.getBaseClassType(); + assertEquals("Cloneable", baseClassRef.getPresentableText()); + assertEquals(cloneableClass, baseClassRef.resolve()); + assertEquals("java.lang.Cloneable", baseClassRef.getCanonicalText()); + + teardownLoadingFilter(); + + assertTrue(anonClass.getParent() instanceof PsiNewExpression); + } + + private void teardownLoadingFilter() { + getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE); + } + + private void setupLoadingFilter() { + getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.ALL); + } + + public void testAnonymousClass2() throws Exception { + setupLoadingFilter(); + + PsiClass throwable = myJavaFacade.findClass("java.lang.Throwable", GlobalSearchScope.allScope(myProject)); + PsiClass[] inheritors = ClassInheritorsSearch.search(throwable, GlobalSearchScope.projectScope(myProject), true).toArray(PsiClass.EMPTY_ARRAY); + assertEquals(1, inheritors.length); + assertTrue(inheritors[0] instanceof PsiAnonymousClass); + PsiAnonymousClass anonClass = (PsiAnonymousClass)inheritors[0]; + + PsiClassType baseClassRef = anonClass.getBaseClassType(); + assertEquals("Throwable", baseClassRef.getPresentableText()); + assertEquals(throwable, baseClassRef.resolve()); + assertEquals("java.lang.Throwable", baseClassRef.getCanonicalText()); + + teardownLoadingFilter(); + + assertTrue(anonClass.getParent() instanceof PsiNewExpression); + } + + public void testLocalClass() throws Exception { + setupLoadingFilter(); + + PsiClass cloneableClass = myJavaFacade.findClass("java.lang.Cloneable", GlobalSearchScope.allScope(myProject)); + PsiClass[] inheritors = ClassInheritorsSearch.search(cloneableClass, GlobalSearchScope.projectScope(myProject), true).toArray(PsiClass.EMPTY_ARRAY); + assertEquals(2, inheritors.length); + assertTrue(inheritors[0] instanceof PsiAnonymousClass || inheritors[1] instanceof PsiAnonymousClass); + PsiClass localClass = inheritors[0] instanceof PsiAnonymousClass ? inheritors[1] : inheritors[0]; + + teardownLoadingFilter(); + + assertTrue(localClass.getParent() instanceof PsiDeclarationStatement); + } + + public void testClassNameModification() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + assertNotNull(aClass); + + aClass.getNameIdentifier().replace(myJavaFacade.getElementFactory().createIdentifier("NewName")); + assertEquals("pack.NewName", aClass.getQualifiedName()); + } + + public void testModification1() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + assertNotNull(aClass); + + PsiField field = aClass.getFields()[0]; + aClass.getNameIdentifier().replace(myJavaFacade.getElementFactory().createIdentifier("NewName")); + assertTrue(field.isValid()); + } + + public void testModification2() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + PsiUtil.setModifierProperty(aClass, PsiModifier.FINAL, true); + + PsiClass aClass2 = myJavaFacade.findClass("pack.MyClass2", GlobalSearchScope.allScope(myProject)); + assertEquals(aClass, aClass2); + } + + public void testModification3() throws Exception { + PsiClass aClass = myJavaFacade.findClass("pack.MyInterface1", GlobalSearchScope.allScope(myProject)); + TextRange classRange = aClass.getTextRange(); + String text = aClass.getText(); + + BlockSupport blockSupport = ServiceManager.getService(myProject, BlockSupport.class); + final PsiFile psiFile = aClass.getContainingFile(); + blockSupport.reparseRange(psiFile, classRange.getStartOffset(), classRange.getEndOffset(), ""); + LOG.assertTrue(!aClass.isValid()); + blockSupport.reparseRange(psiFile, classRange.getStartOffset(), classRange.getStartOffset(), text); + + aClass = myJavaFacade.findClass("pack.MyInterface1", GlobalSearchScope.allScope(myProject)); + PsiElement[] children = aClass.getChildren(); + for (PsiElement child : children) { + if (child instanceof PsiModifierList) { + PsiElement parent = child.getParent(); + assertEquals(aClass, parent); + PsiModifierList modifierList = aClass.getModifierList(); + assertEquals(modifierList, child); + } + } + + PsiJavaFile file = (PsiJavaFile)aClass.getContainingFile(); + PsiImportList importList = file.getImportList(); + children = importList.getChildren(); + int index = 0; + for (PsiElement child : children) { + if (child instanceof PsiImportStatement) { + PsiElement parent = child.getParent(); + assertEquals(importList, parent); + PsiImportStatement statement = importList.getImportStatements()[index++]; + assertEquals(statement, child); + } + } + } + + public void testRenamePackage() throws Exception { + renamePackage("pack", "renamedPack"); + + PsiClass psiClass = myJavaFacade.findClass("renamedPack.MyInterface1", GlobalSearchScope.allScope(myProject)); + assertNotNull(psiClass); + } + + public void testReplaceRootWithSubRoot1() throws Exception { + final PsiClass aClass = myJavaFacade.findClass("pack.MyInterface1", GlobalSearchScope.allScope(myProject)); + final PsiFile psiFile = aClass.getContainingFile(); + ((PsiJavaFile) psiFile).getClasses(); + psiFile.getText(); + assertNotNull(aClass); + + ApplicationManager.getApplication().runWriteAction( + new Runnable() { + public void run() { + VirtualFile newSourceRoot = psiFile.getVirtualFile().getParent(); + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + final ContentEntry[] content = rootModel.getContentEntries(); + boolean contentToChangeFound = false; + for (ContentEntry contentEntry : content) { + final SourceFolder[] sourceFolders = contentEntry.getSourceFolders(); + for (SourceFolder sourceFolder : sourceFolders) { + contentEntry.removeSourceFolder(sourceFolder); + } + final VirtualFile contentRoot = contentEntry.getFile(); + if (contentRoot != null && VfsUtil.isAncestor(contentRoot, newSourceRoot, false)) { + contentEntry.addSourceFolder(newSourceRoot, false); + contentToChangeFound = true; + } + } + assertTrue(contentToChangeFound); + rootModel.commit(); + } + } + ); + + assertEquals("MyInterface1", aClass.getName()); + } + + public void testReplaceRootWithSubRoot2() throws Exception { + final PsiClass aClass = myJavaFacade.findClass("pack.MyInterface1", GlobalSearchScope.allScope(myProject)); + assertNotNull(aClass); + + ApplicationManager.getApplication().runWriteAction( + new Runnable() { + public void run() { + VirtualFile newSourceRoot = aClass.getContainingFile().getVirtualFile().getParent(); + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + final ContentEntry[] content = rootModel.getContentEntries(); + boolean contentToChangeFound = false; + for (ContentEntry contentEntry : content) { + final SourceFolder[] sourceFolders = contentEntry.getSourceFolders(); + for (SourceFolder sourceFolder : sourceFolders) { + contentEntry.removeSourceFolder(sourceFolder); + } + final VirtualFile contentRoot = contentEntry.getFile(); + if (contentRoot != null && VfsUtil.isAncestor(contentRoot, newSourceRoot, false)) { + contentEntry.addSourceFolder(newSourceRoot, false); + contentToChangeFound = true; + } + } + assertTrue(contentToChangeFound); + rootModel.commit(); + } + } + ); + + assertEquals("MyInterface1", aClass.getName()); + } + + public void testParentIdAssert() throws Exception { + PsiClass jpanelClass = myJavaFacade.findClass("javax.swing.JPanel", GlobalSearchScope.allScope(myProject)); + PsiClass[] inheritors = ClassInheritorsSearch.search(jpanelClass, GlobalSearchScope.projectScope(myProject), true).toArray(PsiClass.EMPTY_ARRAY); + assertEquals(2, inheritors.length); + assertTrue(inheritors[0] instanceof PsiAnonymousClass || inheritors[1] instanceof PsiAnonymousClass); + PsiClass nonAnonClass = inheritors[0] instanceof PsiAnonymousClass ? inheritors[1] : inheritors[0]; + + PsiMethod[] methods = nonAnonClass.getMethods(); + assertEquals(1, methods.length); + PsiTypeElement newType = myJavaFacade.getElementFactory().createTypeElement(PsiType.FLOAT); + methods[0].getReturnTypeElement().replace(newType); + } + + public void testParentIdAssertOnExternalChange() throws Exception { + PsiDirectory root = ProjectRootUtil.getAllContentRoots(myProject) [0]; + VirtualFile vFile = root.getVirtualFile().findChild("MyClass1.java"); + + PsiJavaFile psiFile = (PsiJavaFile) myPsiManager.findFile(vFile); + psiFile.getClasses(); + + rewriteFileExternally(vFile, "import a . b;\n" + + "import c.*;\n" + + "import\n" + + "\n" + + "class MyClass1{\n" + + " {\n" + + " class Local{\n" + + " public void foo(){\n" + + " new Runnable(){\n" + + " public void run(){\n" + + " new Throwable(){\n" + + " };\n" + + " };\n" + + " }\n" + + " }\n" + + " };\n" + + " }\n" + + "}\n" + + "\n" + + "class Class2{\n" + + "}\n"); + + PsiClass myClass = myJavaFacade.findClass("MyClass1", GlobalSearchScope.allScope(myProject)); + myClass.getChildren(); + } + + public void testCopyableUserDataChild() throws Exception { + final PsiClass aClass = myJavaFacade.findClass("pack.MyInterface1", GlobalSearchScope.allScope(myProject)); + assertNotNull(aClass); + final PsiFile containingFile = aClass.getContainingFile(); + final CompositeElement element = ((PsiFileImpl)containingFile).calcTreeElement(); + aClass.putCopyableUserData(TEST_KEY, "TEST"); + final PsiJavaFile fileCopy = (PsiJavaFile)containingFile.copy(); + final PsiClass[] classesCopy = fileCopy.getClasses(); + assertEquals(1, classesCopy.length); + assertNotNull(element); + assertEquals("TEST", classesCopy[0].getCopyableUserData(TEST_KEY)); + } + + private static void rewriteFileExternally(VirtualFile vFile, String text) throws IOException { + FileUtil.writeToFile(new File(vFile.getPath()), text.getBytes("UTF-8")); + vFile.refresh(false, false); + } + + private void renamePackage(String packageName, String newPackageName) throws Exception { + PsiPackage aPackage = JavaPsiFacade.getInstance(myPsiManager.getProject()).findPackage(packageName); + assertNotNull("Package " + packageName + " not found", aPackage); + + PsiDirectory dir = aPackage.getDirectories()[0]; + new RenameProcessor(myProject, dir, newPackageName, true, true).run(); + FileDocumentManager.getInstance().saveAllDocuments(); + } + + +} diff --git a/java/java-tests/testSrc/com/intellij/psi/TypesTest.java b/java/java-tests/testSrc/com/intellij/psi/TypesTest.java new file mode 100644 index 000000000000..8784a45b4226 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/TypesTest.java @@ -0,0 +1,436 @@ +package com.intellij.psi; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiUtil; + +import java.io.File; + +/** + * @author dsl + */ +public class TypesTest extends GenericsTestCase { + protected void setUp() throws Exception { + super.setUp(); + final ModifiableRootModel rootModel = setupGenericSampleClasses(); + + final String testPath = PathManagerEx.getTestDataPath().replace(File.separatorChar, '/') + "/psi/types/" + getTestName(true); + final VirtualFile[] testRoot = new VirtualFile[] { null }; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + testRoot[0] = LocalFileSystem.getInstance().refreshAndFindFileByPath(testPath); + } + }); + if (testRoot[0] != null) { + final ContentEntry testContentEntry = rootModel.addContentEntry(testRoot[0]); + testContentEntry.addSourceFolder(testRoot[0], false); + } + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + rootModel.commit(); + } + }); + } + + public void testSimpleStuff() throws Exception { + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiElementFactory factory = psiManager.getElementFactory(); + final PsiClass classA = psiManager.findClass("A"); + assertTrue(classA != null); + + final PsiMethod method = classA.getMethods()[0]; + final PsiStatement[] methodStatements = method.getBody().getStatements(); + final PsiDeclarationStatement declarationStatement = ((PsiDeclarationStatement) methodStatements[0]); + final PsiVariable varList = ((PsiVariable) declarationStatement.getDeclaredElements()[0]); + final PsiType typeListOfA = factory.createTypeFromText("test.List", null); + assertTrue(varList.getType().equals(typeListOfA)); + final PsiType typeListOfObject = factory.createTypeFromText("test.List", null); + assertFalse(varList.getType().equals(typeListOfObject)); + + final PsiReferenceExpression methodExpression + = ((PsiMethodCallExpression) ((PsiExpressionStatement) methodStatements[1]).getExpression()).getMethodExpression(); + final JavaResolveResult resolveResult = methodExpression.advancedResolve(false); + assertTrue(resolveResult.getElement() instanceof PsiMethod); + final PsiMethod methodFromList = ((PsiMethod) resolveResult.getElement()); + final PsiType typeOfFirstParameterOfAdd = methodFromList.getParameterList().getParameters()[0].getType(); + final PsiType substitutedType = resolveResult.getSubstitutor().substitute(typeOfFirstParameterOfAdd); + final PsiClassType typeA = factory.createTypeByFQClassName("java.lang.String"); + assertEquals(typeA, substitutedType); + assertTrue(typeA.equalsToText("java.lang.String")); + + final PsiType aListIteratorType = ((PsiExpressionStatement) methodStatements[2]).getExpression().getType(); + final PsiType aIteratorType = factory.createTypeFromText("test.Iterator", null); + assertTrue(aIteratorType.equals(aListIteratorType)); + final PsiType objectIteratorType = factory.createTypeFromText("test.Iterator", null); + assertFalse(objectIteratorType.equals(aListIteratorType)); + } + + public void testRawTypes() throws Exception { + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiElementFactory factory = psiManager.getElementFactory(); + final PsiClass classA = psiManager.findClass("A"); + assertTrue(classA != null); + + final PsiMethod method = classA.getMethods()[0]; + final PsiStatement[] methodStatements = method.getBody().getStatements(); + final PsiDeclarationStatement declarationStatement = ((PsiDeclarationStatement) methodStatements[0]); + final PsiVariable varList = ((PsiVariable) declarationStatement.getDeclaredElements()[0]); + final PsiType typeFromText = factory.createTypeFromText("test.List", null); + assertEquals(varList.getType(), typeFromText); + + final PsiReferenceExpression methodExpression = ((PsiMethodCallExpression) ((PsiExpressionStatement) methodStatements[1]).getExpression()).getMethodExpression(); + final JavaResolveResult resolveResult = methodExpression.advancedResolve(false); + assertTrue(resolveResult.getElement() instanceof PsiMethod); + final PsiMethod methodFromList = ((PsiMethod) resolveResult.getElement()); + final PsiType typeOfFirstParameterOfAdd = methodFromList.getParameterList().getParameters()[0].getType(); + final PsiType substitutedType = resolveResult.getSubstitutor().substitute(typeOfFirstParameterOfAdd); + assertEquals(PsiType.getJavaLangObject(getPsiManager(), method.getResolveScope()), substitutedType); + + final PsiType methodCallType = ((PsiExpressionStatement) methodStatements[2]).getExpression().getType(); + final PsiType rawIteratorType = factory.createTypeFromText("test.Iterator", null); + assertTrue(rawIteratorType.equals(methodCallType)); + } + + public void testSubstWithInheritor() throws Exception { + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiElementFactory factory = psiManager.getElementFactory(); + final PsiClass classA = psiManager.findClass("A"); + assertTrue(classA != null); + + final PsiMethod method = classA.getMethods()[0]; + final PsiStatement[] methodStatements = method.getBody().getStatements(); + final PsiDeclarationStatement declarationStatement = ((PsiDeclarationStatement) methodStatements[0]); + final PsiVariable varList = ((PsiVariable) declarationStatement.getDeclaredElements()[0]); + final PsiType typeFromText = factory.createTypeFromText("test.IntList", null); + assertEquals(varList.getType(), typeFromText); + + final PsiReferenceExpression methodExpression + = ((PsiMethodCallExpression) ((PsiExpressionStatement) methodStatements[1]).getExpression()).getMethodExpression(); + final JavaResolveResult resolveResult = methodExpression.advancedResolve(false); + assertTrue(resolveResult.getElement() instanceof PsiMethod); + final PsiMethod methodFromList = ((PsiMethod) resolveResult.getElement()); + final PsiType typeOfFirstParameterOfAdd = methodFromList.getParameterList().getParameters()[0].getType(); + final PsiType substitutedType = resolveResult.getSubstitutor().substitute(typeOfFirstParameterOfAdd); + final PsiType javaLangInteger = factory.createTypeFromText("java.lang.Integer", null); + assertTrue(javaLangInteger.equals(substitutedType)); + + final PsiType intListIteratorReturnType = ((PsiExpressionStatement) methodStatements[2]).getExpression().getType(); + final PsiType integerIteratorType = factory.createTypeFromText("test.Iterator", null); + assertTrue(integerIteratorType.equals(intListIteratorReturnType)); + final PsiType objectIteratorType = factory.createTypeFromText("test.Iterator", null); + assertFalse(objectIteratorType.equals(integerIteratorType)); + } + + public void testSimpleRawTypeInMethodArg() throws Exception { + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiElementFactory factory = psiManager.getElementFactory(); + final PsiClass classA = psiManager.findClass("A"); + assertTrue(classA != null); + + final PsiMethod method = classA.getMethods()[0]; + final PsiStatement[] methodStatements = method.getBody().getStatements(); + + final PsiVariable variable = ((PsiVariable) ((PsiDeclarationStatement) methodStatements[0]).getDeclaredElements()[0]); + final PsiClassType type = (PsiClassType) variable.getType(); + final PsiClassType.ClassResolveResult resolveClassTypeResult = type.resolveGenerics(); + assertTrue(resolveClassTypeResult.getElement() != null); + + final PsiReferenceExpression methodExpression + = ((PsiMethodCallExpression) ((PsiExpressionStatement) methodStatements[2]).getExpression()).getMethodExpression(); + final PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); + final PsiClassType qualifierType = (PsiClassType) qualifierExpression.getType(); + assertFalse(qualifierType.hasParameters()); + final PsiType typeFromText = factory.createTypeFromText("test.List", null); + assertTrue(qualifierType.equals(typeFromText)); + + final PsiElement psiElement = ((PsiReferenceExpression) qualifierExpression).resolve(); + assertTrue(psiElement instanceof PsiVariable); + final JavaResolveResult resolveResult = methodExpression.advancedResolve(false); + assertTrue(resolveResult.getElement() instanceof PsiMethod); + final PsiMethod methodFromList = (PsiMethod) resolveResult.getElement(); + assertTrue("add".equals(methodFromList.getName())); + assertTrue("test.List".equals(methodFromList.getContainingClass().getQualifiedName())); + } + + + + public void testRawTypeInMethodArg() throws Exception { + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiClass classA = psiManager.findClass("A"); + assertTrue(classA != null); + + final PsiMethod method = classA.getMethods()[0]; + final PsiStatement[] methodStatements = method.getBody().getStatements(); + final PsiReferenceExpression methodExpression + = ((PsiMethodCallExpression) ((PsiExpressionStatement) methodStatements[2]).getExpression()).getMethodExpression(); + final JavaResolveResult resolveResult = methodExpression.advancedResolve(false); + assertTrue(resolveResult.getElement() instanceof PsiMethod); + final PsiMethod methodFromList = (PsiMethod) resolveResult.getElement(); + assertTrue("putAll".equals(methodFromList.getName())); + assertTrue("test.List".equals(methodFromList.getContainingClass().getQualifiedName())); + } + + public void testBoundedParams() throws Exception { + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiElementFactory factory = psiManager.getElementFactory(); + final PsiClass classA = psiManager.findClass("A"); + assertTrue(classA != null); + + final PsiMethod method = classA.getMethods()[0]; + final PsiStatement[] statements = method.getBody().getStatements(); + + final PsiVariable var = ((PsiVariable) ((PsiDeclarationStatement) statements[0]).getDeclaredElements()[0]); + final PsiType varType = var.getType(); + final PsiType typeRawIterator = factory.createTypeFromText("test.Iterator", null); + assertTrue(varType.equals(typeRawIterator)); + + final PsiType initializerType = var.getInitializer().getType(); + assertTrue(initializerType.equals(typeRawIterator)); + assertTrue(varType.isAssignableFrom(initializerType)); + } + + public void testRawTypeExtension() throws Exception { + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiElementFactory factory = psiManager.getElementFactory(); + final PsiClass classA = psiManager.findClass("A"); + assertTrue(classA != null); + + final PsiMethod method = classA.getMethods()[0]; + final PsiStatement[] statements = method.getBody().getStatements(); + + final PsiVariable var = ((PsiVariable) ((PsiDeclarationStatement) statements[0]).getDeclaredElements()[0]); + final PsiType varType = var.getType(); + final PsiType typeRawIterator = factory.createTypeFromText("test.Iterator", null); + assertTrue(varType.equals(typeRawIterator)); + + final PsiType initializerType = var.getInitializer().getType(); + assertTrue(initializerType.equals(typeRawIterator)); + assertTrue(varType.isAssignableFrom(initializerType)); + } + + public void testTypesInGenericClass() { + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiElementFactory factory = psiManager.getElementFactory(); + final PsiClass classA = psiManager.findClass("A"); + assertNotNull(classA); + + final PsiTypeParameter parameterT = classA.getTypeParameters()[0]; + assertEquals("T", parameterT.getName()); + + final PsiMethod method = classA.findMethodsByName("method", false)[0]; + final PsiType type = ((PsiExpressionStatement) method.getBody().getStatements()[0]).getExpression().getType(); + final PsiClassType typeT = factory.createType(parameterT); + assertEquals("T", typeT.getPresentableText()); + + assertTrue(typeT.equals(type)); + } + + public void testAssignableSubinheritor() throws Exception { + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiElementFactory factory = psiManager.getElementFactory(); + final PsiClass classCollection = psiManager.findClass("test.Collection"); + final PsiClass classList = psiManager.findClass("test.List"); + final PsiType collectionType = factory.createType(classCollection, PsiSubstitutor.EMPTY); + final PsiType listType = factory.createType(classList, PsiSubstitutor.EMPTY); + assertEquals(collectionType.getCanonicalText(), "test.Collection"); + assertEquals(listType.getCanonicalText(), "test.List"); + + final PsiType typeListOfString = factory.createTypeFromText("test.List", null); + final PsiType typeCollectionOfString = factory.createTypeFromText("test.Collection", null); + assertTrue(typeCollectionOfString.isAssignableFrom(typeListOfString)); + } + + public void testComplexInheritance() throws Exception { + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiElementFactory factory = psiManager.getElementFactory(); + final PsiClass classA = psiManager.findClass("A"); + assertNotNull(classA); + + final PsiMethod method = classA.findMethodsByName("method", false)[0]; + final PsiExpression expression = ((PsiExpressionStatement) method.getBody().getStatements()[1]).getExpression(); + assertEquals("l.get(0)", expression.getText()); + + final PsiType type = expression.getType(); + final PsiType listOfInteger = factory.createTypeFromText("test.List", null); + assertTrue(listOfInteger.equals(type)); + final PsiType collectionOfInteger = factory.createTypeFromText("test.Collection", null); + assertTrue(collectionOfInteger.isAssignableFrom(type)); + } + + public void testListListInheritance() throws Exception { + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiElementFactory factory = psiManager.getElementFactory(); + final PsiClass classA = psiManager.findClass("A"); + assertNotNull(classA); + + final PsiMethod method = classA.findMethodsByName("method", false)[0]; + + final PsiExpression expression1 = ((PsiExpressionStatement) method.getBody().getStatements()[1]).getExpression(); + assertEquals("l.get(0)", expression1.getText()); + final PsiType type1 = expression1.getType(); + final PsiType typeListOfInteger = factory.createTypeFromText("test.List", null); + assertTrue(typeListOfInteger.equals(type1)); + assertTrue(typeListOfInteger.isAssignableFrom(type1)); + + final PsiExpression expression2 = ((PsiExpressionStatement) method.getBody().getStatements()[3]).getExpression(); + assertEquals("b.get(0)", expression2.getText()); + final PsiType type2 = expression2.getType(); + assertTrue(typeListOfInteger.equals(type2)); + } + + public void testSpaceInTypeParameterList() throws Exception { + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiElementFactory factory = psiManager.getElementFactory(); + final PsiClass classA = psiManager.findClass("A"); + assertNotNull(classA); + + final PsiMethod method = classA.findMethodsByName("method", false)[0]; + + final PsiVariable variable = (PsiVariable) ((PsiDeclarationStatement) method.getBody().getStatements()[0]).getDeclaredElements()[0]; + final PsiType type = variable.getType(); + final PsiType typeListOfListOfInteger = factory.createTypeFromText("test.List>", null); + assertTrue(typeListOfListOfInteger.equals(type)); + } + + public void testMethodTypeParameter() throws Exception { + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiElementFactory factory = psiManager.getElementFactory(); + final PsiClass classA = psiManager.findClass("A"); + assertNotNull(classA); + + final PsiMethod method = classA.findMethodsByName("method", false)[0]; + final PsiStatement[] statements = method.getBody().getStatements(); + + final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) ((PsiExpressionStatement) statements[1]).getExpression(); + isCollectionUtilSort(methodCallExpression, factory.createTypeFromText("java.lang.Integer", null)); + + final PsiMethodCallExpression methodCallExpression1 = (PsiMethodCallExpression) ((PsiExpressionStatement) statements[3]).getExpression(); + isCollectionUtilSort(methodCallExpression1, null); + } + + private void isCollectionUtilSort(final PsiMethodCallExpression methodCallExpression, + final PsiType typeParameterValue) { + final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); + final JavaResolveResult methodResolve = methodExpression.advancedResolve(false); + assertTrue(methodResolve.getElement() instanceof PsiMethod); + final PsiMethod methodSort = (PsiMethod) methodResolve.getElement(); + assertEquals("sort", methodSort.getName()); + assertEquals("test.CollectionUtil", methodSort.getContainingClass().getQualifiedName()); + final PsiTypeParameter methodSortTypeParameter = methodSort.getTypeParameters()[0]; + final PsiType sortParameterActualType = methodResolve.getSubstitutor().substitute(methodSortTypeParameter); + assertTrue(Comparing.equal(sortParameterActualType, typeParameterValue)); + assertTrue( + PsiUtil.isApplicable(methodSort, methodResolve.getSubstitutor(), methodCallExpression.getArgumentList())); + } + + public void testRawArrayTypes() throws Exception { + final JavaPsiFacade psiManager = getJavaFacade(); + final PsiElementFactory factory = psiManager.getElementFactory(); + final PsiClass classA = psiManager.findClass("A"); + assertNotNull(classA); + + final PsiMethod method = classA.findMethodsByName("method", false)[0]; + final PsiStatement[] statements = method.getBody().getStatements(); + + final PsiDeclarationStatement declarationStatement = ((PsiDeclarationStatement) statements[0]); + final PsiClassType typeOfL = (PsiClassType) ((PsiVariable) declarationStatement.getDeclaredElements()[0]).getType(); + final PsiType typeRawList = factory.createTypeFromText("test.List", null); + assertTrue(Comparing.equal(typeOfL, typeRawList)); + final PsiSubstitutor typeOfLSubstitutor = typeOfL.resolveGenerics().getSubstitutor(); + + final PsiMethodCallExpression exprGetArray = (PsiMethodCallExpression) ((PsiExpressionStatement) statements[1]).getExpression(); + final PsiType typeOfGetArrayCall = exprGetArray.getType(); + final PsiType objectArrayType = factory.createTypeFromText("java.lang.Object[]", null); + assertTrue(Comparing.equal(typeOfGetArrayCall, objectArrayType)); + final PsiMethod methodGetArray = (PsiMethod) exprGetArray.getMethodExpression().resolve(); + final PsiType subtitutedGetArrayReturnType = typeOfLSubstitutor.substitute(methodGetArray.getReturnType()); + assertTrue(Comparing.equal(subtitutedGetArrayReturnType, objectArrayType)); + + + final PsiMethodCallExpression exprGetListOfArray = (PsiMethodCallExpression) ((PsiExpressionStatement) statements[2]).getExpression(); + final PsiMethod methodGetListOfArray = (PsiMethod) exprGetListOfArray.getMethodExpression().resolve(); + final PsiType returnType = methodGetListOfArray.getReturnType(); + final PsiType substitutedReturnType = typeOfLSubstitutor.substitute(returnType); + assertTrue(Comparing.equal(substitutedReturnType, typeRawList)); + + final PsiType typeOfGetListOfArrayCall = exprGetListOfArray.getType(); + assertTrue(Comparing.equal(typeOfGetListOfArrayCall, typeRawList)); + } + + public void testWildcardTypeParsing() throws Exception{ + final GlobalSearchScope scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(myModule); + final PsiClassType javaLangObject = PsiType.getJavaLangObject(myPsiManager, scope); + + PsiElement element = ((PsiDeclarationStatement)myJavaFacade.getElementFactory().createStatementFromText("X, ?> x;", null)).getDeclaredElements()[0]; + PsiJavaCodeReferenceElement referenceElement = ((PsiVariable) element).getTypeElement().getInnermostComponentReferenceElement(); + PsiType[] typeArguments = referenceElement.getTypeParameters(); + assertEquals(3, typeArguments.length); + assertTrue(typeArguments[0] instanceof PsiWildcardType); + assertTrue(typeArguments[1] instanceof PsiWildcardType); + assertTrue(typeArguments[2] instanceof PsiWildcardType); + PsiWildcardType extendsWildcard = (PsiWildcardType)typeArguments[0]; + PsiWildcardType superWildcard = (PsiWildcardType)typeArguments[1]; + PsiWildcardType unboundedWildcard = (PsiWildcardType)typeArguments[2]; + + // extends wildcard test + assertTrue(extendsWildcard.isExtends()); + assertFalse(extendsWildcard.isSuper()); + assertEquals("Y", extendsWildcard.getBound().getCanonicalText()); + assertEquals("Y", extendsWildcard.getExtendsBound().getCanonicalText()); + assertTrue(extendsWildcard.getSuperBound().equals(PsiType.NULL)); + + // super wildcard test + assertFalse(superWildcard.isExtends()); + assertTrue(superWildcard.isSuper()); + assertEquals("Z", superWildcard.getBound().getCanonicalText()); + assertTrue(superWildcard.getExtendsBound().equals(javaLangObject)); + assertEquals("Z", superWildcard.getSuperBound().getCanonicalText()); + + // unbounded wildcard test + assertFalse(unboundedWildcard.isExtends()); + assertFalse(unboundedWildcard.isSuper()); + assertTrue(unboundedWildcard.getBound() == null); + assertTrue(unboundedWildcard.getExtendsBound().equals(javaLangObject)); + assertTrue(unboundedWildcard.getSuperBound().equals(PsiType.NULL)); + } + + public void testWildcardTypesAssignable() throws Exception { + PsiClassType listOfExtendsBase = (PsiClassType)myJavaFacade.getElementFactory().createTypeFromText("test.List", null); + PsiClassType.ClassResolveResult classResolveResult = listOfExtendsBase.resolveGenerics(); + PsiClass listClass = classResolveResult.getElement(); + assertNotNull(listClass); + PsiTypeParameter listTypeParameter = PsiUtil.typeParametersIterator(listClass).next(); + PsiType listParameterTypeValue = classResolveResult.getSubstitutor().substitute(listTypeParameter); + assertTrue(listParameterTypeValue instanceof PsiWildcardType); + assertTrue(((PsiWildcardType)listParameterTypeValue).isExtends()); + assertEquals("usages.Base", ((PsiWildcardType)listParameterTypeValue).getBound().getCanonicalText()); + PsiClassType listOfIntermediate = (PsiClassType)myJavaFacade.getElementFactory().createTypeFromText("test.List", null); + assertNotNull(listOfIntermediate.resolve()); + assertTrue(listOfExtendsBase.isAssignableFrom(listOfIntermediate)); + } + + public void testEllipsisType() throws Exception { + PsiElementFactory factory = myJavaFacade.getElementFactory(); + PsiMethod method = factory.createMethodFromText("void foo (int ... args) {}", null); + PsiType paramType = method.getParameterList().getParameters()[0].getType(); + assertTrue(paramType instanceof PsiEllipsisType); + PsiType arrayType = ((PsiEllipsisType)paramType).getComponentType().createArrayType(); + assertTrue(paramType.isAssignableFrom(arrayType)); + assertTrue(arrayType.isAssignableFrom(paramType)); + + PsiType typeFromText = factory.createTypeFromText("int ...", null); + assertTrue(typeFromText instanceof PsiEllipsisType); + } + + public void testBinaryNumericPromotion() throws Exception { + PsiElementFactory factory = myJavaFacade.getElementFactory(); + final PsiExpression conditional = factory.createExpressionFromText("b ? new Integer (0) : new Double(0.0)", null); + assertEquals(conditional.getType(), PsiType.DOUBLE); + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/InnerClassesScannerTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/InnerClassesScannerTest.java new file mode 100644 index 000000000000..5b7295dfa14d --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/InnerClassesScannerTest.java @@ -0,0 +1,118 @@ +package com.intellij.psi.impl.cache.impl; + +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.impl.source.PsiJavaFileImpl; +import com.intellij.psi.impl.source.tree.StdTokenSets; +import com.intellij.testFramework.PsiTestCase; +import com.intellij.lexer.Lexer; +import com.intellij.lexer.FilterLexer; + +import java.io.File; +import java.util.List; +import java.util.ArrayList; + +/** + * @author dsl + */ +public class InnerClassesScannerTest extends PsiTestCase { + public void testClassWithGenericParameters() throws Exception { doTest(); } + + public void testNewInsideNew() throws Exception { doTest(); } + + private void doTest() throws Exception { + configureByFileWithMarker( + PathManagerEx.getTestDataPath() + "/psi/repositoryUse/innerClassesScanner/".replace('/', File.separatorChar) + getTestName(false) + ".java", + ""); + final List list = getInnerClasses(((PsiJavaFile)myFile).getClasses()[0].getMethods()[0], myFile.getViewProvider().getContents()); + assertTrue(list != null && list.size() == 1); + } + + private static List getInnerClasses(PsiElement psiElement, final CharSequence fileBuffer) { + final Ref> ourList = new Ref>(); + ourList.set(null); + + if (psiElement != null && mayContainClassesInside(psiElement, fileBuffer)) { + psiElement.accept(new JavaRecursiveElementWalkingVisitor() { + @Override public void visitClass(PsiClass aClass) { + if (ourList.isNull()) ourList.set(new ArrayList()); + ourList.get().add(aClass); + } + + @Override public void visitTypeParameter(PsiTypeParameter classParameter) { + // just skip (because type parameter is class - bad!) + } + }); + } + + return ourList.get(); + } + + private static boolean mayContainClassesInside(PsiElement psiElement, final CharSequence fileBuffer) { + PsiFile psiFile = psiElement.getContainingFile(); + + boolean mayHaveClassesInside = false; + if (psiFile instanceof PsiJavaFileImpl) { + PsiJavaFileImpl impl = (PsiJavaFileImpl)psiFile; + Lexer originalLexer = impl.createLexer(); + FilterLexer lexer = new FilterLexer(originalLexer, new FilterLexer.SetFilter(StdTokenSets.WHITE_SPACE_OR_COMMENT_BIT_SET)); + final TextRange range = psiElement.getTextRange(); + lexer.start(fileBuffer, range.getStartOffset(), range.getEndOffset()); + boolean isInNewExpression = false; + boolean isRightAfterNewExpression = false; + int angleLevel = 0; + int parenLevel = 0; + do { + IElementType tokenType = lexer.getTokenType(); + if (tokenType == null) break; + + if (tokenType == JavaTokenType.NEW_KEYWORD) { + isInNewExpression = true; + } + else if (tokenType == JavaTokenType.LPARENTH) { + if (isInNewExpression) parenLevel++; + } + else if (tokenType == JavaTokenType.LT) { + if (isInNewExpression) angleLevel++; + } + else if (tokenType == JavaTokenType.GT) { + if (isInNewExpression) angleLevel--; + } + else if (tokenType == JavaTokenType.RPARENTH) { + if (isInNewExpression) { + parenLevel--; + if (parenLevel == 0) { + isRightAfterNewExpression = true; + } + } + } + else if (tokenType == JavaTokenType.LBRACE) { + if (isInNewExpression || isRightAfterNewExpression) { + mayHaveClassesInside = true; + } + } + else if (tokenType == JavaTokenType.LBRACKET) { + if (parenLevel == 0 && angleLevel == 0) isInNewExpression = false; + } + else if (tokenType == JavaTokenType.INTERFACE_KEYWORD || tokenType == JavaTokenType.CLASS_KEYWORD || + tokenType == JavaTokenType.ENUM_KEYWORD) { + mayHaveClassesInside = true; + } + + if (isInNewExpression && isRightAfterNewExpression) { + isInNewExpression = false; + } + else { + isRightAfterNewExpression = false; + } + + lexer.advance(); + } + while (!mayHaveClassesInside); + } + return mayHaveClassesInside; + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/SCR17650Test.java b/java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/SCR17650Test.java new file mode 100644 index 000000000000..a06a770752a5 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/SCR17650Test.java @@ -0,0 +1,71 @@ +package com.intellij.psi.impl.cache.impl; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.PsiTestCase; + +import java.io.File; +import java.io.IOException; + +/** + * @author max + */ +public class SCR17650Test extends PsiTestCase { + private static final String TEST_ROOT = PathManagerEx.getTestDataPath() + "/psi/repositoryUse/cls"; + + private VirtualFile myDir; + + protected void setUp() throws Exception { + super.setUp(); + + final File root = File.createTempFile(getName(), ""); + root.delete(); + root.mkdir(); + myFilesToDelete.add(root); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + try { + VirtualFile rootVFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(root.getAbsolutePath().replace(File.separatorChar, '/')); + + myDir = rootVFile.createChildDirectory(null, "contentAndLibrary"); + + VirtualFile file1 = myDir.createChildData(null, "A.java"); + VfsUtil.saveText(file1, "package p; public class A{ public void foo(); }"); + VfsUtil.copyFile(null, getClassFile(), myDir); + + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + final ContentEntry contentEntry1 = rootModel.addContentEntry(myDir); + contentEntry1.addSourceFolder(myDir, false); + final Library jarLibrary = rootModel.getModuleLibraryTable().createLibrary(); + final Library.ModifiableModel libraryModel = jarLibrary.getModifiableModel(); + libraryModel.addRoot(myDir, OrderRootType.CLASSES); + libraryModel.commit(); + rootModel.commit(); + } + catch (IOException e) { + LOG.error(e); + } + } + }); + } + + private static VirtualFile getClassFile() { + VirtualFile vDir = LocalFileSystem.getInstance().findFileByPath(TEST_ROOT.replace(File.separatorChar, '/')); + VirtualFile child = vDir.findChild("pack").findChild("MyClass.class"); + return child; + } + + public void test17650() throws Exception { + assertEquals("p.A", myJavaFacade.findClass("p.A").getQualifiedName()); + assertEquals("pack.MyClass", myJavaFacade.findClass("pack.MyClass").getQualifiedName()); + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/source/parsing/GTTokensTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/source/parsing/GTTokensTest.java new file mode 100644 index 000000000000..9070b5873696 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/impl/source/parsing/GTTokensTest.java @@ -0,0 +1,40 @@ +package com.intellij.psi.impl.source.parsing; + +import com.intellij.FileSetTestCase; +import com.intellij.lang.ASTFactory; +import com.intellij.lexer.FilterLexer; +import com.intellij.lexer.JavaLexer; +import com.intellij.lexer.Lexer; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.impl.source.tree.*; +import com.intellij.psi.tree.IElementType; +import junit.framework.Test; + +/** + * @author dsl + */ +public class GTTokensTest extends FileSetTestCase { + public GTTokensTest() { + super(PathManagerEx.getTestDataPath() + "/psi/gt-tokens"); + } + + public String transform(String testName, String[] data) throws Exception { + final Lexer lexer = new FilterLexer(new JavaLexer(LanguageLevel.HIGHEST), + new FilterLexer.SetFilter(StdTokenSets.WHITE_SPACE_OR_COMMENT_BIT_SET)); + StringBuffer result = new StringBuffer(); + lexer.start(data[0]); + final CompositeElement parent = ASTFactory.composite(ElementType.CODE_FRAGMENT); + while(true) { + final IElementType tokenType = GTTokens.getTokenType(lexer); + if (tokenType == null) break; + TreeElement token = GTTokens.createTokenElementAndAdvance(tokenType, lexer, ((FileElement)parent).getCharTable()); + parent.rawAddChildren(token); + result.append(token.toString()); + result.append('\n'); + } + return result.toString(); + } + + public static Test suite() throws Exception { return new GTTokensTest(); } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/BindToElementTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/BindToElementTest.java new file mode 100644 index 000000000000..c24fa1096de9 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/BindToElementTest.java @@ -0,0 +1,87 @@ +package com.intellij.psi.impl.source.tree.java; + +import com.intellij.codeInsight.CodeInsightTestCase; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.IncorrectOperationException; + +import java.io.File; + +/** + * @author dsl + */ +public class BindToElementTest extends CodeInsightTestCase { + public static final String TEST_ROOT = PathManagerEx.getTestDataPath() + "/psi/impl/bindToElementTest/".replace('/', File.separatorChar); + + protected void setUp() throws Exception { + super.setUp(); + VirtualFile root = ApplicationManager.getApplication().runWriteAction(new Computable() { + public VirtualFile compute() { + return LocalFileSystem.getInstance().refreshAndFindFileByIoFile( + new File(new File(TEST_ROOT), "prj") + ); + } + }); + assertNotNull(root); + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel(); + final ContentEntry contentEntry = rootModel.addContentEntry(root); + contentEntry.addSourceFolder(root, false); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + rootModel.commit(); + } + }); + } + + public void testSingleClassImport() throws Exception { + doTest(new Runnable() { + public void run() { + PsiElement element = myFile.findElementAt(myEditor.getCaretModel().getOffset()); + final PsiJavaCodeReferenceElement referenceElement = PsiTreeUtil.getParentOfType(element, PsiJavaCodeReferenceElement.class); + final PsiClass aClassA = JavaPsiFacade.getInstance(myProject).findClass("p2.A", GlobalSearchScope.moduleScope(myModule)); + assertNotNull(aClassA); + try { + referenceElement.bindToElement(aClassA); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } + }); + } + + public void testReplacingType() throws Exception { + doTest(new Runnable() { + public void run() { + final PsiElement elementAt = myFile.findElementAt(myEditor.getCaretModel().getOffset()); + final PsiTypeElement typeElement = PsiTreeUtil.getParentOfType(elementAt, PsiTypeElement.class); + final PsiClass aClassA = JavaPsiFacade.getInstance(myProject).findClass("p2.A", GlobalSearchScope.moduleScope(myModule)); + assertNotNull(aClassA); + final PsiElementFactory factory = myJavaFacade.getElementFactory(); + final PsiClassType type = factory.createType(aClassA); + try { + typeElement.replace(factory.createTypeElement(type)); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } + }); + } + + private void doTest(final Runnable runnable) throws Exception { + final String relativeFilePath = "/psi/impl/bindToElementTest/" + getTestName(false); + configureByFile(relativeFilePath + ".java"); + runnable.run(); + checkResultByFile(relativeFilePath + ".java.after"); + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/BindToGenericClassTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/BindToGenericClassTest.java new file mode 100644 index 000000000000..cae9fcd6204b --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/BindToGenericClassTest.java @@ -0,0 +1,53 @@ +package com.intellij.psi.impl.source.tree.java; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.search.GlobalSearchScope; + +/** + * @author dsl + */ +public class BindToGenericClassTest extends GenericsTestCase { + private boolean myOldFQNamesSetting; + + protected void setUp() throws Exception { + super.setUp(); + final ModifiableRootModel rootModel = setupGenericSampleClasses(); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + rootModel.commit(); + } + }); + final CodeStyleSettings currentSettings = CodeStyleSettingsManager.getInstance(myProject).getCurrentSettings(); + + myOldFQNamesSetting = currentSettings.USE_FQ_CLASS_NAMES; + currentSettings.USE_FQ_CLASS_NAMES = true; + } + + protected void tearDown() throws Exception { + final CodeStyleSettings currentSettings = CodeStyleSettingsManager.getInstance(myProject).getCurrentSettings(); + currentSettings.USE_FQ_CLASS_NAMES = myOldFQNamesSetting; + super.tearDown(); + } + + public void testReferenceElement() throws Exception { + final JavaPsiFacade manager = getJavaFacade(); + final PsiClass classA = manager.getElementFactory().createClassFromText("class A extends List{}", null).getInnerClasses()[0]; + final PsiClass classTestList = manager.findClass("test.List", GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(myModule)); + assertNotNull(classTestList); + classA.getExtendsList().getReferenceElements()[0].bindToElement(classTestList); + assertEquals("class A extends test.List{}", classA.getText()); + } + + public void testReference() throws Exception { + final JavaPsiFacade manager = getJavaFacade(); + final PsiExpression psiExpression = manager.getElementFactory().createExpressionFromText("List", null); + final PsiClass classTestList = manager.findClass("test.List", GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(myModule)); + assertNotNull(classTestList); + final PsiElement result = ((PsiReferenceExpression) psiExpression).bindToElement(classTestList); + assertEquals("test.List", result.getText()); + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ExtendsBoundListTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ExtendsBoundListTest.java new file mode 100644 index 000000000000..fb1d177694d3 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ExtendsBoundListTest.java @@ -0,0 +1,90 @@ +package com.intellij.psi.impl.source.tree.java; + +import com.intellij.psi.*; +import com.intellij.testFramework.LightCodeInsightTestCase; + +/** + * @author dsl + */ +public class ExtendsBoundListTest extends LightCodeInsightTestCase { + public void testRemoveBoundFromFront() throws Exception { + PsiTypeParameter typeParameter = getTypeParameter(); + typeParameter.getExtendsList().getReferenceElements()[0].delete(); + check(); + } + public void testRemoveBoundFromEnd() throws Exception { + PsiTypeParameter typeParameter = getTypeParameter(); + typeParameter.getExtendsList().getReferenceElements()[1].delete(); + check(); + } + public void testRemoveBoundFromMiddle() throws Exception { + PsiTypeParameter typeParameter = getTypeParameter(); + typeParameter.getExtendsList().getReferenceElements()[1].delete(); + check(); + } + + public void testAddBoundInTheMiddle() throws Exception { + final PsiTypeParameter typeParameter = getTypeParameter(); + final PsiReferenceList extendsList = typeParameter.getExtendsList(); + final JavaPsiFacade manager = getJavaFacade(); + final PsiClass clonableClass = manager.findClass("java.lang.Cloneable"); + assertNotNull(clonableClass); + final PsiJavaCodeReferenceElement reference = manager.getElementFactory().createClassReferenceElement(clonableClass); + extendsList.addAfter(reference, extendsList.getReferenceElements()[0]); + check(); + } + public void testAddBoundInFront() throws Exception { + final PsiTypeParameter typeParameter = getTypeParameter(); + final PsiReferenceList extendsList = typeParameter.getExtendsList(); + final JavaPsiFacade manager = getJavaFacade(); + final PsiClass clonableClass = manager.findClass("java.lang.Cloneable"); + assertNotNull(clonableClass); + final PsiJavaCodeReferenceElement reference = manager.getElementFactory().createClassReferenceElement(clonableClass); + extendsList.addBefore(reference, extendsList.getReferenceElements()[0]); + check(); + } + + public void testAddBoundInEnd() throws Exception { + final PsiTypeParameter typeParameter = getTypeParameter(); + final PsiReferenceList extendsList = typeParameter.getExtendsList(); + final JavaPsiFacade manager = getJavaFacade(); + final PsiClass clonableClass = manager.findClass("java.lang.Cloneable"); + assertNotNull(clonableClass); + final PsiJavaCodeReferenceElement reference = manager.getElementFactory().createClassReferenceElement(clonableClass); + extendsList.addBefore(reference, null); + check(); + } + + + public void testAddBound() throws Exception { + final PsiTypeParameter typeParameter = getTypeParameter(); + final PsiReferenceList extendsList = typeParameter.getExtendsList(); + final JavaPsiFacade manager = getJavaFacade(); + final PsiClass clonableClass = manager.findClass("java.lang.Runnable"); + assertNotNull(clonableClass); + final PsiJavaCodeReferenceElement reference = manager.getElementFactory().createClassReferenceElement(clonableClass); + extendsList.add(reference); + check(); + } + + + + private void check() throws Exception { + outputFile(getTestName(true) + "_after.java"); + } + + private PsiTypeParameter getTypeParameter() throws Exception { + inputFile(getTestName(true) + ".java"); + final PsiClass aClass = ((PsiJavaFile)getFile()).getClasses()[0]; + final PsiTypeParameter typeParameter = aClass.getTypeParameters()[0]; + return typeParameter; + } + + private void outputFile(String filename) throws Exception { + checkResultByFile("/psi/impl/extendsBoundList/" + filename); + } + + private void inputFile(String filename) throws Exception { + configureByFile("/psi/impl/extendsBoundList/" + filename); + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/JavadocParamTagsTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/JavadocParamTagsTest.java new file mode 100644 index 000000000000..1e6763bc5f0b --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/JavadocParamTagsTest.java @@ -0,0 +1,185 @@ +package com.intellij.psi.impl.source.tree.java; + +import com.intellij.codeInsight.CodeInsightUtilBase; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.psi.*; +import com.intellij.psi.javadoc.PsiDocComment; +import com.intellij.psi.javadoc.PsiDocTag; +import com.intellij.testFramework.LightIdeaTestCase; +import com.intellij.util.IncorrectOperationException; + +/** + * @author dsl + */ +public class JavadocParamTagsTest extends LightIdeaTestCase { + public void testDeleteTag1() throws Exception { + final PsiElementFactory factory = getFactory(); + final PsiMethod method = factory.createMethodFromText( + "/**\n" + + " * Javadoc\n" + + " * @param p1\n" + + " * @param p2\n" + + " */" + + " void m() {}", null); + final PsiDocComment docComment = method.getDocComment(); + assertNotNull(docComment); + final PsiDocTag[] tags = docComment.getTags(); + tags[0].delete(); + assertEquals("/**\n" + + " * Javadoc\n" + + " * @param p2\n" + + " */", docComment.getText()); + + } + + public void testDeleteTag2() throws Exception { + final PsiElementFactory factory = getFactory(); + final PsiMethod method = factory.createMethodFromText( + "/**\n" + + " * Javadoc\n" + + " * @param p1\n" + + " * @param p2\n" + + " */" + + " void m() {}", null); + final PsiDocComment docComment = method.getDocComment(); + assertNotNull(docComment); + final PsiDocTag[] tags = docComment.getTags(); + tags[1].delete(); + assertEquals("/**\n" + + " * Javadoc\n" + + " * @param p1\n" + + " */", docComment.getText()); + + } + + public void testDeleteTag3() throws Exception { + final PsiElementFactory factory = getFactory(); + final PsiMethod method = factory.createMethodFromText( + "/**\n" + + " * Javadoc\n" + + " * @param p1\n" + + " * @param p2\n" + + " * @param p3\n" + + " */" + + " void m() {}", null); + final PsiDocComment docComment = method.getDocComment(); + assertNotNull(docComment); + final PsiDocTag[] tags = docComment.getTags(); + tags[1].delete(); + assertEquals("/**\n" + + " * Javadoc\n" + + " * @param p1\n" + + " * @param p3\n" + + " */", docComment.getText()); + } + + public void testTagCreation() throws Exception { + createAndTestTag("@param p1 Text", "p1", "Text"); + createAndTestTag("@param p2", "p2", ""); + createAndTestTag("@param p2 FirstLine\n * SecondLine", "p2", "FirstLine\nSecondLine"); + } + + public void testAddTag1() throws Exception { + final PsiElementFactory factory = getFactory(); + final PsiMethod method = factory.createMethodFromText( + "/**\n" + + " * Javadoc\n" + + " * @param p1\n" + + " */\n" + + "void m();", null); + final PsiDocComment docComment = method.getDocComment(); + assertNotNull(docComment); + final PsiDocTag[] tags = docComment.getTags(); + final PsiDocTag tag2 = factory.createParamTag("p2", ""); + docComment.addAfter(tag2, tags[0]); + assertEquals( + "/**\n" + + " * Javadoc\n" + + " * @param p1\n" + + " * @param p2\n" + + " */", docComment.getText()); + } + + public void testAddTag2() throws Exception { + final PsiElementFactory factory = getFactory(); + final PsiMethod method = factory.createMethodFromText( + "/**\n" + + " * Javadoc\n" + + " * @param p1\n" + + " */\n" + + "void m();", null); + final PsiDocComment docComment = method.getDocComment(); + assertNotNull(docComment); + final PsiDocTag[] tags = docComment.getTags(); + final PsiDocTag tag2 = factory.createParamTag("p2", ""); + docComment.addBefore(tag2, tags[0]); + assertEquals( + "/**\n" + + " * Javadoc\n" + + " * @param p2\n" + + " * @param p1\n" + + " */", docComment.getText()); + } + + public void testAddTag3() throws Exception { + CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable(){ + public void run() { + final PsiElementFactory factory = getFactory(); + final PsiJavaFile psiFile; + try { + psiFile = (PsiJavaFile)createPseudoPhysicalFile("aaa.java", "class A {/**\n" + " * Javadoc\n" + " * @param p1\n" + " * @param p3\n" + " */\n" + "void m();}"); + final PsiClass psiClass = psiFile.getClasses()[0]; + final PsiMethod method = psiClass.getMethods()[0]; + PsiDocComment docComment = method.getDocComment(); + assertNotNull(docComment); + final PsiDocTag[] tags = docComment.getTags(); + final PsiDocTag tag2 = factory.createParamTag("p2", ""); + docComment.addAfter(tag2, tags[0]); + docComment = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(docComment); + assertEquals( + "/**\n" + + " * Javadoc\n" + + " * @param p1\n" + + " * @param p2\n" + + " * @param p3\n" + + " */", docComment.getText()); + } + catch (IncorrectOperationException e) {} + } + }); + } + }, "", null); + } + + public void testAddTag4() throws Exception { + final PsiElementFactory factory = getFactory(); + final PsiMethod method = factory.createMethodFromText( + "/**\n" + + " * Javadoc\n" + + " */\n" + + "void m();", null); + final PsiDocComment docComment = method.getDocComment(); + assertNotNull(docComment); + final PsiDocTag tag2 = factory.createParamTag("p2", ""); + docComment.add(tag2); + assertEquals( + "/**\n" + + " * Javadoc\n" + + " * @param p2\n" + + " */", docComment.getText()); + } + + private static PsiElementFactory getFactory() { + final PsiManager manager = getPsiManager(); + return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); + } + + private static void createAndTestTag(String expectedText, String parameterName, String description) throws IncorrectOperationException { + PsiElementFactory factory = getFactory(); + final PsiDocTag paramTag = factory.createParamTag(parameterName, description); + assertEquals(expectedText, paramTag.getText()); + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ReferenceParameterListTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ReferenceParameterListTest.java new file mode 100644 index 000000000000..cde48f3bdf76 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ReferenceParameterListTest.java @@ -0,0 +1,68 @@ +package com.intellij.psi.impl.source.tree.java; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.*; +import com.intellij.psi.impl.source.PsiClassReferenceType; +import com.intellij.testFramework.PsiTestCase; +import com.intellij.util.IncorrectOperationException; + +/** + * @author dsl + */ +public class ReferenceParameterListTest extends PsiTestCase { + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.ReferenceParameterListTest"); + public void testParameterListInExtends() throws Exception { + final PsiManager manager = PsiManager.getInstance(myProject); + final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); + final PsiClass classFromText = factory.createClassFromText("class X extends Y {}", null); + final PsiClass classX = classFromText.getInnerClasses()[0]; + final PsiJavaCodeReferenceElement[] extendsOfX = classX.getExtendsList().getReferenceElements(); + assertEquals(1, extendsOfX.length); + final PsiJavaCodeReferenceElement ref = extendsOfX[0]; + assertEquals("Y", ref.getCanonicalText()); + assertEquals("Y", ref.getReferenceName()); + final PsiTypeElement[] refParams = ref.getParameterList().getTypeParameterElements(); + assertEquals(2, refParams.length); + assertEquals("Z", refParams[0].getType().getCanonicalText()); + assertEquals("W", refParams[1].getType().getCanonicalText()); + final PsiType refType = factory.createType(ref); + assertEquals("Y", refType.getCanonicalText()); + final PsiJavaCodeReferenceElement reference = ((PsiClassReferenceType) refType).getReference(); + assertEquals("Y", reference.getCanonicalText()); + } + public void testResolvableParameterListInExtends() throws Exception { + final PsiManager manager = PsiManager.getInstance(myProject); + final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); + final PsiClass classFromText = factory.createClassFromText( + "class Z {} class W{}" + + "class Y {} " + + "class X extends Y {}", + null); + + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + try { + classFromText.setName("Q"); + } catch (IncorrectOperationException e) { + LOG.error(e); + } + } + }); + final PsiClass classX = classFromText.getInnerClasses()[3]; + final PsiJavaCodeReferenceElement[] extendsOfX = classX.getExtendsList().getReferenceElements(); + assertEquals(1, extendsOfX.length); + final PsiJavaCodeReferenceElement ref = extendsOfX[0]; + assertEquals("Q.Y", ref.getCanonicalText()); + assertEquals("Y", ref.getReferenceName()); + final PsiTypeElement[] refParams = ref.getParameterList().getTypeParameterElements(); + assertEquals(2, refParams.length); + assertEquals("Q.Z", refParams[0].getType().getCanonicalText()); + assertEquals("Q.W", refParams[1].getType().getCanonicalText()); + final PsiType refType = factory.createType(ref); + assertEquals("Q.Y", refType.getCanonicalText()); + final PsiJavaCodeReferenceElement reference = ((PsiClassReferenceType) refType).getReference(); + assertEquals("Q.Y", reference.getCanonicalText()); + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ShortenClassReferencesTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ShortenClassReferencesTest.java new file mode 100644 index 000000000000..0d5e97baca12 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ShortenClassReferencesTest.java @@ -0,0 +1,79 @@ +package com.intellij.psi.impl.source.tree.java; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.impl.source.PostprocessReformattingAspect; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.testFramework.PsiTestCase; + +import java.io.File; + +/** + * @author dsl + */ +public class ShortenClassReferencesTest extends PsiTestCase { + private static final String BASE_PATH = PathManagerEx.getTestDataPath() + "/psi/shortenClassRefs"; + + public void testSCR22368() throws Exception { doTest(); } + + public void testSCR37254() throws Exception { doTest(); } + + public void testSCR22368_1() throws Exception { + final PsiElementFactory factory = myJavaFacade.getElementFactory(); + final PsiClass aClass = factory.createClass("X"); + final PsiMethod methodFromText = factory.createMethodFromText( + "void method() {\n" + + " IntelliJIDEARulezz<\n" + + "}", null); + final PsiMethod method = (PsiMethod)aClass.add(methodFromText); + final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) method.getBody().getStatements()[0]; + final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement) declarationStatement.getFirstChild().getFirstChild(); + final PsiClass javaUtilListClass = myJavaFacade.findClass("java.util.List", GlobalSearchScope.allScope(myPsiManager.getProject())); + assertNotNull(javaUtilListClass); + final PsiElement resultingElement = referenceElement.bindToElement(javaUtilListClass); + assertEquals("List<", resultingElement.getText()); + assertEquals("void method() {\n" + + " List<\n" + + "}", method.getText()); + + } + + private void doTest() throws Exception { + String fileName = getTestName(false) + ".java"; + String text = loadFile(fileName); + final PsiFile file = createFile(fileName, text); + CommandProcessor.getInstance().executeCommand( + getProject(), new Runnable() { + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + try { + JavaCodeStyleManager.getInstance(myProject).shortenClassReferences(file); + String textAfter = loadFile(getTestName(false) + "_after.java"); + PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting(); + PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); + String fileText = file.getText(); + assertEquals(textAfter, fileText); + + } + catch (Exception e) { + LOG.error(e); + } + } + }); + } + }, "", ""); + } + + private String loadFile(String name) throws Exception { + String fullName = BASE_PATH + File.separatorChar + name; + String text = new String(FileUtil.loadFileText(new File(fullName))); + text = StringUtil.convertLineSeparators(text); + return text; + } +} From 8eae113fb8720c0957c574df884c1f75e14bdb3f Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 11 Aug 2010 13:12:41 +0400 Subject: [PATCH 04/36] separating jsp --- .../psi/optimizeImports/EmptyImportInJsp.jsp | 1 - .../optimizeImports/EmptyImportInJsp_after.jsp | 1 - .../psi/optimizeImports/UsageInCustomTag.jsp | 4 ---- .../optimizeImports/UsageInCustomTag_after.jsp | 4 ---- .../com/intellij/psi/OptimizeImportsTest.java | 16 +++++++++++++++- 5 files changed, 15 insertions(+), 11 deletions(-) delete mode 100644 java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp.jsp delete mode 100644 java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp_after.jsp delete mode 100644 java/java-tests/testData/psi/optimizeImports/UsageInCustomTag.jsp delete mode 100644 java/java-tests/testData/psi/optimizeImports/UsageInCustomTag_after.jsp diff --git a/java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp.jsp b/java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp.jsp deleted file mode 100644 index 9062b95b1832..000000000000 --- a/java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp.jsp +++ /dev/null @@ -1 +0,0 @@ -<%@ page autoFlush="true" import="java.util.List" %> diff --git a/java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp_after.jsp b/java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp_after.jsp deleted file mode 100644 index 1edc87122114..000000000000 --- a/java/java-tests/testData/psi/optimizeImports/EmptyImportInJsp_after.jsp +++ /dev/null @@ -1 +0,0 @@ -<%@ page autoFlush="true" %> diff --git a/java/java-tests/testData/psi/optimizeImports/UsageInCustomTag.jsp b/java/java-tests/testData/psi/optimizeImports/UsageInCustomTag.jsp deleted file mode 100644 index 92dfb608cd5d..000000000000 --- a/java/java-tests/testData/psi/optimizeImports/UsageInCustomTag.jsp +++ /dev/null @@ -1,4 +0,0 @@ - -<%@ page import="java.util.List" %> - - diff --git a/java/java-tests/testData/psi/optimizeImports/UsageInCustomTag_after.jsp b/java/java-tests/testData/psi/optimizeImports/UsageInCustomTag_after.jsp deleted file mode 100644 index 92dfb608cd5d..000000000000 --- a/java/java-tests/testData/psi/optimizeImports/UsageInCustomTag_after.jsp +++ /dev/null @@ -1,4 +0,0 @@ - -<%@ page import="java.util.List" %> - - diff --git a/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java b/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java index 7bfc6c089d44..7da6db49e7b6 100644 --- a/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java @@ -1,3 +1,18 @@ +/* + * 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 com.intellij.psi; import com.intellij.openapi.application.ApplicationManager; @@ -18,7 +33,6 @@ public class OptimizeImportsTest extends PsiTestCase{ public void testSCR6138() throws Exception { doTest(); } public void testSCR18364() throws Exception { doTest(); } - public void testEmptyImportInJsp() throws Exception { doTest(".jsp"); } public void testStaticImports1() throws Exception { doTest(); } public void testStaticImportsToOptimize() throws Exception { doTest(); } public void testStaticImportsToOptimize2() throws Exception { doTest(); } From 5f1314dc30e10eb84bb9ff426859f45a2065613a Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Wed, 11 Aug 2010 13:29:25 +0400 Subject: [PATCH 05/36] IDEA-57432 report 'create new instance of built-in types' --- .../org/jetbrains/plugins/groovy/GroovyBundle.properties | 1 + .../plugins/groovy/annotator/GroovyAnnotator.java | 9 +++++++++ .../psi/api/statements/expressions/GrNewExpression.java | 4 ++++ .../impl/statements/expressions/GrNewExpressionImpl.java | 6 ++++++ .../plugins/groovy/lang/GroovyHighlightingTest.java | 2 ++ .../highlighting/BuiltInTypeInstantiation.groovy | 1 + 6 files changed, 23 insertions(+) create mode 100644 plugins/groovy/testdata/highlighting/BuiltInTypeInstantiation.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties index e676d65bcdec..353d85422bf0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties @@ -341,3 +341,4 @@ cyclic.inheritance.involving.0=Cyclic inheritance involving ''{0}'' there.is.no.default.constructor.available.in.class.0=There is no default constructor available in class ''{0}'' groovy.library.is.not.configured.for.module=Groovy SDK is not configured for module ''{0}'' configure.groovy.library=Configure Groovy SDK... +create.instance.of.built-in.type=Instantiation of built-in type diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 6f701de2dbd7..39ecd932cd86 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -490,7 +490,16 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { @Override public void visitNewExpression(GrNewExpression newExpression) { + final GrTypeElement typeElement = newExpression.getTypeElement(); + + if (typeElement instanceof GrBuiltInTypeElement) { + if (newExpression.getArrayCount() == 0) { + myHolder.createErrorAnnotation(typeElement, GroovyBundle.message("create.instance.of.built-in.type")); + } + } + if (newExpression.getArrayCount() > 0) return; + GrCodeReferenceElement refElement = newExpression.getReferenceElement(); if (refElement == null) return; final PsiElement element = refElement.resolve(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrNewExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrNewExpression.java index 648a2e418b26..8db00b5e3856 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrNewExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrNewExpression.java @@ -20,6 +20,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; /** * @author ilyas @@ -31,6 +32,9 @@ public interface GrNewExpression extends GrCallExpression, GrConstructorCall { @Nullable GrCodeReferenceElement getReferenceElement(); + @Nullable + GrTypeElement getTypeElement(); + int getArrayCount(); @Nullable diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrNewExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrNewExpressionImpl.java index 22ff2fab9fc6..5d0cdf023224 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrNewExpressionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrNewExpressionImpl.java @@ -34,6 +34,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExp import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrBuiltInTypeElement; 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.GrClassReferenceType; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; @@ -203,4 +204,9 @@ public class GrNewExpressionImpl extends GrCallExpressionImpl implements GrNewEx return result.toArray(new GroovyResolveResult[result.size()]); } + + @Override + public GrTypeElement getTypeElement() { + return findChildByClass(GrTypeElement.class); + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java index 384e207e25c1..4a32219b6727 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java @@ -281,4 +281,6 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase { public void testNumberDuplicatesInMaps() throws Exception {doTest();} public void testMapNotAcceptedAsStringParameter() {doTest();} + + public void testBuiltInTypeInstantiation() {doTest();} } \ No newline at end of file diff --git a/plugins/groovy/testdata/highlighting/BuiltInTypeInstantiation.groovy b/plugins/groovy/testdata/highlighting/BuiltInTypeInstantiation.groovy new file mode 100644 index 000000000000..10566a8ba4ec --- /dev/null +++ b/plugins/groovy/testdata/highlighting/BuiltInTypeInstantiation.groovy @@ -0,0 +1 @@ +def x = new int() \ No newline at end of file From e1e8c1fa6fd4df5dffd50dfb8b251c0f775721e1 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Thu, 5 Aug 2010 18:04:51 +0400 Subject: [PATCH 06/36] "Add Framework Support" UI --- .../AddFrameworkSupportDialog.java | 22 +++++++++++-- .../AddSupportForFrameworksPanel.form | 4 ++- .../AddSupportForFrameworksPanel.java | 31 ++++++++++--------- .../src/messages/ProjectBundle.properties | 2 +- 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/java/idea-ui/src/com/intellij/ide/util/frameworkSupport/AddFrameworkSupportDialog.java b/java/idea-ui/src/com/intellij/ide/util/frameworkSupport/AddFrameworkSupportDialog.java index cc92f53ef971..85faaa5bfe44 100644 --- a/java/idea-ui/src/com/intellij/ide/util/frameworkSupport/AddFrameworkSupportDialog.java +++ b/java/idea-ui/src/com/intellij/ide/util/frameworkSupport/AddFrameworkSupportDialog.java @@ -40,7 +40,15 @@ public class AddFrameworkSupportDialog extends DialogWrapper { public String compute() { return contentRootPath; } - }); + }) { + + @Override + protected void onFrameworkStateChanged() { + setOKActionEnabled(isOKActionEnabled()); + } + }; + + setOKActionEnabled(isOKActionEnabled()); Disposer.register(myDisposable, myAddSupportPanel); init(); } @@ -61,8 +69,13 @@ public class AddFrameworkSupportDialog extends DialogWrapper { return roots.length != 0 && FrameworkSupportUtil.hasProviders(module); } + @Override + public boolean isOKActionEnabled() { + return myAddSupportPanel.hasSelectedFrameworks(); + } + protected void doOKAction() { - if (myAddSupportPanel.haveSelectedFrameworks()) { + if (myAddSupportPanel.hasSelectedFrameworks()) { if (!myAddSupportPanel.downloadLibraries()) { int answer = Messages.showYesNoDialog(myAddSupportPanel.getMainPanel(), ProjectBundle.message("warning.message.some.required.libraries.wasn.t.downloaded"), @@ -96,4 +109,9 @@ public class AddFrameworkSupportDialog extends DialogWrapper { protected JComponent createCenterPanel() { return myAddSupportPanel.getMainPanel(); } + + @Override + public JComponent getPreferredFocusedComponent() { + return myAddSupportPanel.getFrameworksTree(); + } } diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.form b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.form index 0c644bcc775c..a4dcb29384a4 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.form +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.form @@ -31,7 +31,9 @@ - + + + diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java index 64018fe883de..e4a143fc4fb6 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java @@ -48,6 +48,7 @@ import com.intellij.ui.SeparatorFactory; import com.intellij.util.graph.CachingSemiGraph; import com.intellij.util.graph.DFSTBuilder; import com.intellij.util.graph.GraphGenerator; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -64,7 +65,6 @@ import java.util.List; */ public class AddSupportForFrameworksPanel implements Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.newProjectWizard.AddSupportForFrameworksStep"); - @NonNls private static final String UNCHECKED_CARD = "unchecked"; @NonNls private static final String EMPTY_CARD = "empty"; private JPanel myMainPanel; private JPanel myFrameworksPanel; @@ -78,7 +78,6 @@ public class AddSupportForFrameworksPanel implements Disposable { private final FrameworksTree myFrameworksTree; private final Set myInitializedOptionsPanelIds = new HashSet(); private FrameworkSupportNode myLastSelectedNode; - private final JLabel myTickCheckboxLabel; public AddSupportForFrameworksPanel(final List providers, final @NotNull LibrariesContainer librariesContainer, @Nullable ModuleBuilder builder, Computable baseDirForLibrariesGetter) { @@ -100,6 +99,7 @@ public class AddSupportForFrameworksPanel implements Disposable { updateOptionsPanel(); frameworkSupportNode.getConfigurable().onFrameworkSelectionChanged(node.isChecked()); myModel.onFrameworkSelectionChanged(frameworkSupportNode); + onFrameworkStateChanged(); } }; myFrameworksTree.addTreeSelectionListener(new TreeSelectionListener() { @@ -107,17 +107,19 @@ public class AddSupportForFrameworksPanel implements Disposable { onSelectionChanged(); } }); + splitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myFrameworksTree)); myOptionsPanel = new JPanel(new CardLayout()); myOptionsPanel.add(EMPTY_CARD, new JPanel()); - final JPanel uncheckedLabelPanel = new JPanel(new BorderLayout()); - myTickCheckboxLabel = new JLabel("Tick checkbox"); - uncheckedLabelPanel.add(BorderLayout.NORTH, myTickCheckboxLabel); - myOptionsPanel.add(UNCHECKED_CARD, uncheckedLabelPanel); + splitter.setSecondComponent(myOptionsPanel); myFrameworksPanel.add(splitter, BorderLayout.CENTER); + + myFrameworksTree.setSelectionRow(0); } + protected void onFrameworkStateChanged() {} + private void onSelectionChanged() { if (!myFrameworksTree.isProcessingMouseEventOnCheckbox()) { updateOptionsPanel(); @@ -154,14 +156,9 @@ public class AddSupportForFrameworksPanel implements Disposable { private void updateOptionsPanel() { final FrameworkSupportNode node = getSelectedNode(); if (node != null) { - if (node.isChecked()) { - initializeOptionsPanel(node); - showCard(node.getProvider().getId()); - } - else { - myTickCheckboxLabel.setText("Select check box to add '" + node.getTitle() + "' support"); - showCard(UNCHECKED_CARD); - } + initializeOptionsPanel(node); + showCard(node.getProvider().getId()); + UIUtil.setEnabled(myOptionsPanel, node.isChecked(), true); } else { showCard(EMPTY_CARD); @@ -314,7 +311,11 @@ public class AddSupportForFrameworksPanel implements Disposable { return myMainPanel; } - public boolean haveSelectedFrameworks() { + public FrameworksTree getFrameworksTree() { + return myFrameworksTree; + } + + public boolean hasSelectedFrameworks() { return !getFrameworkNodes(true).isEmpty(); } diff --git a/platform/platform-resources-en/src/messages/ProjectBundle.properties b/platform/platform-resources-en/src/messages/ProjectBundle.properties index 41ddcd669d6d..a112246db61b 100644 --- a/platform/platform-resources-en/src/messages/ProjectBundle.properties +++ b/platform/platform-resources-en/src/messages/ProjectBundle.properties @@ -481,7 +481,7 @@ composing.library.name.label=&Name: composing.library.download.missing.jars.to=&Download missing files to: composing.liibrary.new.library.label=The following library will be created composing.library.from.repository.label=&from {0} -dialog.title.add.frameworks.support=Frameworks Support +dialog.title.add.frameworks.support=Add Frameworks Support warning.message.some.required.libraries.wasn.t.downloaded=Some required library wasn't downloaded. Do you want to proceed without it? save.as.library.checkbox=&Move copy to {0} level From 89cd3355eb48acf91a7a448054d68dd5a354b76f Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 6 Aug 2010 17:37:29 +0400 Subject: [PATCH 07/36] default constructor --- .../src/com/intellij/ui/CheckBoxList.java | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/CheckBoxList.java b/platform/platform-api/src/com/intellij/ui/CheckBoxList.java index b396274b5194..64e397964c1a 100644 --- a/platform/platform-api/src/com/intellij/ui/CheckBoxList.java +++ b/platform/platform-api/src/com/intellij/ui/CheckBoxList.java @@ -8,16 +8,26 @@ import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.plaf.basic.BasicRadioButtonUI; import java.awt.*; -import java.awt.event.*; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; /** * @author oleg */ public class CheckBoxList extends JBList { private static final int DEFAULT_CHECK_BOX_WIDTH = 20; + private CheckBoxListListener checkBoxListListener; public CheckBoxList(final ListModel dataModel, final CheckBoxListListener checkBoxListListener) { - super(dataModel); + this(); + setModel(dataModel); + setCheckBoxListListener(checkBoxListListener); + } + + public CheckBoxList() { + super(); setCellRenderer(new CellRenderer()); setSelectionMode(ListSelectionModel.SINGLE_SELECTION); setBorder(BorderFactory.createEtchedBorder()); @@ -29,7 +39,7 @@ public class CheckBoxList extends JBList { for (int index : indices) { if (index >= 0) { JCheckBox checkbox = (JCheckBox)getModel().getElementAt(index); - setSelected(checkbox, index, checkBoxListListener); + setSelected(checkbox, index); } } } @@ -50,7 +60,7 @@ public class CheckBoxList extends JBList { iconArea = DEFAULT_CHECK_BOX_WIDTH; } if (e.getX() < iconArea) { - setSelected(checkbox, index, checkBoxListListener); + setSelected(checkbox, index); } } } @@ -58,11 +68,21 @@ public class CheckBoxList extends JBList { }); } - private void setSelected(JCheckBox checkbox, int index, CheckBoxListListener checkBoxListListener) { + public boolean isItemSelected(int index) { + return ((JCheckBox)getModel().getElementAt(index)).isSelected(); + } + + private void setSelected(JCheckBox checkbox, int index) { boolean value = !checkbox.isSelected(); checkbox.setSelected(value); repaint(); - checkBoxListListener.checkBoxSelectionChanged(index, value); + if (checkBoxListListener != null) { + checkBoxListListener.checkBoxSelectionChanged(index, value); + } + } + + public void setCheckBoxListListener(CheckBoxListListener checkBoxListListener) { + this.checkBoxListListener = checkBoxListListener; } private class CellRenderer implements ListCellRenderer { From 792102d5e702d4f73de7e8b03dc605980581ae3b Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 6 Aug 2010 17:38:00 +0400 Subject: [PATCH 08/36] disabling labels --- platform/util/src/com/intellij/util/ui/UIUtil.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 031921ed0172..1ce45180dc94 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -104,6 +104,12 @@ public class UIUtil { public static void setEnabled(Component component, boolean enabled, boolean recursively) { component.setEnabled(enabled); + if (component instanceof JLabel) { + Color color = UIManager.getColor(enabled ? "Label.foreground" : "Label.disabledForeground"); + if (color != null) { + component.setForeground(color); + } + } if (recursively && enabled == component.isEnabled()) { if (component instanceof Container) { final Container container = (Container)component; From 47ebc178a0f369539db5ad1bcb25f5b1479321ce Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 9 Aug 2010 16:56:09 +0400 Subject: [PATCH 09/36] "Add Framework Support" UI --- .../libraries/DownloadingOptionsDialog.form | 133 +++++++++++++++ .../libraries/DownloadingOptionsDialog.java | 101 ++++++++++++ .../impl/ui/libraries/EditLibraryDialog.form | 81 ++++++++++ .../impl/ui/libraries/EditLibraryDialog.java | 84 ++++++++++ .../LibraryCompositionOptionsPanel.java | 6 +- .../libraries/LibraryCompositionSettings.java | 18 +++ .../ui/libraries/LibraryOptionsPanel.form | 81 ++++++++++ .../ui/libraries/LibraryOptionsPanel.java | 152 ++++++++++++++++++ .../AddSupportForFrameworksPanel.java | 23 +-- .../FrameworkSupportNode.java | 8 +- .../projectRoot/LibrariesContainer.java | 8 +- .../facet/ui/libraries/LibraryInfo.java | 15 ++ 12 files changed, 692 insertions(+), 18 deletions(-) create mode 100644 java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.form create mode 100644 java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.java create mode 100644 java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.form create mode 100644 java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java create mode 100644 java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.form create mode 100644 java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.form b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.form new file mode 100644 index 000000000000..6255628ea536 --- /dev/null +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.form @@ -0,0 +1,133 @@ + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.java new file mode 100644 index 000000000000..0d24748ffbf4 --- /dev/null +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.java @@ -0,0 +1,101 @@ +/* + * 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 com.intellij.facet.impl.ui.libraries; + +import com.intellij.facet.ui.libraries.LibraryInfo; +import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; +import com.intellij.openapi.project.ProjectBundle; +import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.ui.CheckBoxList; +import com.intellij.ui.CollectionListModel; +import com.intellij.ui.EnumComboBoxModel; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; + +import javax.swing.*; +import java.awt.*; + +/** + * @author Dmitry Avdeev + */ +public class DownloadingOptionsDialog extends DialogWrapper { + + private JPanel myPanel; + private CheckBoxList myFilesList; + private TextFieldWithBrowseButton myDirectoryField; + private JTextField myLibraryNameField; + private JComboBox myLevelComboBox; + private JCheckBox myDownloadSourcesCheckBox; + private JLabel myFilesToDownloadLabel; + private JLabel myCopyDownloadedFilesToLabel; + private JCheckBox myDownloadJavadocsCheckBox; + private final LibraryCompositionSettings mySettings; + + protected DownloadingOptionsDialog(Component parent, LibraryCompositionSettings settings) { + super(parent, true); + setTitle("Downloading Options"); + mySettings = settings; + + myFilesList.setModel(new CollectionListModel(ContainerUtil.map2Array(settings.getLibraryInfos(), new Function() { + @Override + public Object fun(LibraryInfo libraryInfo) { + return new JCheckBox(libraryInfo.getPresentableName(), libraryInfo.isSelected()); + } + }))); + myFilesToDownloadLabel.setLabelFor(myFilesList); + + myDirectoryField.addBrowseFolderListener(ProjectBundle.message("file.chooser.directory.for.downloaded.libraries.title"), + ProjectBundle.message("file.chooser.directory.for.downloaded.libraries.description"), null, + FileChooserDescriptorFactory.createSingleFolderDescriptor()); + + myCopyDownloadedFilesToLabel.setLabelFor(myDirectoryField); + myDirectoryField.setText(settings.getDirectoryForDownloadedLibrariesPath()); + + myDownloadSourcesCheckBox.setSelected(settings.isDownloadSources()); + myDownloadJavadocsCheckBox.setSelected(settings.isDownloadJavadocs()); + myLibraryNameField.setText(settings.getLibraryName()); + myLevelComboBox.setModel(new EnumComboBoxModel(LibrariesContainer.LibraryLevel.class)); + myLevelComboBox.setSelectedItem(settings.getLibraryLevel()); + init(); + } + + @Override + protected JComponent createCenterPanel() { + return myPanel; + } + + @Override + public JComponent getPreferredFocusedComponent() { + return myFilesList; + } + + @Override + protected void doOKAction() { + mySettings.setLibraryName(myLibraryNameField.getText()); + mySettings.setLibraryLevel((LibrariesContainer.LibraryLevel)myLevelComboBox.getSelectedItem()); + mySettings.setDirectoryForDownloadedLibrariesPath(myDirectoryField.getText()); + LibraryInfo[] libraryInfos = mySettings.getLibraryInfos(); + for (int i = 0, libraryInfosLength = libraryInfos.length; i < libraryInfosLength; i++) { + LibraryInfo info = libraryInfos[i]; + info.setSelected(myFilesList.isItemSelected(i)); + } + mySettings.setDownloadSources(myDownloadSourcesCheckBox.isSelected()); + mySettings.setDownloadJavadocs(myDownloadJavadocsCheckBox.isSelected()); + super.doOKAction(); + } +} diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.form b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.form new file mode 100644 index 000000000000..8a1edd8da239 --- /dev/null +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.form @@ -0,0 +1,81 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java new file mode 100644 index 000000000000..e25bf7c0f1e1 --- /dev/null +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java @@ -0,0 +1,84 @@ +/* + * 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 com.intellij.facet.impl.ui.libraries; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.roots.impl.libraries.ApplicationLibraryTable; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.roots.libraries.LibraryTable; +import com.intellij.openapi.roots.libraries.LibraryTablePresentation; +import com.intellij.openapi.roots.ui.configuration.LibraryTableModifiableModelProvider; +import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryTableEditor; +import com.intellij.openapi.ui.DialogWrapper; + +import javax.swing.*; +import java.awt.*; + +/** + * @author Dmitry Avdeev + */ +public class EditLibraryDialog extends DialogWrapper { + + private ApplicationLibraryTable myLibraryTable = new ApplicationLibraryTable(); + private Library myLibrary; + private JTextField myTextField1; + private JComboBox myComboBox1; + private JPanel myEditorPanel; + private JPanel myPanel; + + protected EditLibraryDialog(Component parent) { + super(parent, true); + setTitle("Edit Library"); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + myLibrary = myLibraryTable.createLibrary("xxx"); + } + }); + init(); + + } + + @Override + protected JComponent createCenterPanel() { + + JComponent editor = LibraryTableEditor.editLibrary(new LibraryTableModifiableModelProvider() { + + @Override + public LibraryTable.ModifiableModel getModifiableModel() { + return myLibraryTable.getModifiableModel(); + } + + @Override + public String getTableLevel() { + return myLibraryTable.getTableLevel(); + } + + @Override + public LibraryTablePresentation getLibraryTablePresentation() { + return myLibraryTable.getPresentation(); + } + + @Override + public boolean isLibraryTableEditable() { + return false; + } + }, myLibrary).getComponent(); + + myEditorPanel.add(editor, BorderLayout.CENTER); + return myPanel; + } +} diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionOptionsPanel.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionOptionsPanel.java index dbac47342136..1f7d0c5402e8 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionOptionsPanel.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionOptionsPanel.java @@ -33,7 +33,6 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.IdeBorderFactory; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -74,14 +73,15 @@ public class LibraryCompositionOptionsPanel { private final LibraryDownloadingMirrorsMap myMirrorsMap; private List myMirrorPanelsList; - public LibraryCompositionOptionsPanel(final @NotNull LibrariesContainer librariesContainer, final @NotNull LibraryCompositionSettings libraryCompositionSettings, + public LibraryCompositionOptionsPanel(final @NotNull LibrariesContainer librariesContainer, + final @NotNull LibraryCompositionSettings libraryCompositionSettings, final @NotNull LibraryDownloadingMirrorsMap mirrorsMap) { + myLibrariesContainer = librariesContainer; myLibraryCompositionSettings = libraryCompositionSettings; myMirrorsMap = mirrorsMap; addMirrorsPanels(); - myMainPanel.setBorder(BorderFactory.createCompoundBorder(IdeBorderFactory.createTitledBorder(libraryCompositionSettings.getTitle()), IdeBorderFactory.createEmptyBorder(5,5,5,5))); myDirectoryField.addBrowseFolderListener(ProjectBundle.message("file.chooser.directory.for.downloaded.libraries.title"), ProjectBundle.message("file.chooser.directory.for.downloaded.libraries.description"), null, FileChooserDescriptorFactory.createSingleFolderDescriptor()); diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java index 4e9968ec4f11..b17a33933d0a 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java @@ -47,6 +47,8 @@ public class LibraryCompositionSettings { private LibrariesContainer.LibraryLevel myLibraryLevel = LibrariesContainer.LibraryLevel.PROJECT; private String myLibraryName; private final Icon myIcon; + private boolean myDownloadSources = true; + private boolean myDownloadJavadocs = true; public LibraryCompositionSettings(final @NotNull LibraryInfo[] libraryInfos, final @NotNull String defaultLibraryName, @@ -191,4 +193,20 @@ public class LibraryCompositionSettings { } return library; } + + public boolean isDownloadSources() { + return myDownloadSources; + } + + public void setDownloadSources(boolean downloadSources) { + myDownloadSources = downloadSources; + } + + public boolean isDownloadJavadocs() { + return myDownloadJavadocs; + } + + public void setDownloadJavadocs(boolean downloadJavadocs) { + myDownloadJavadocs = downloadJavadocs; + } } diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.form b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.form new file mode 100644 index 000000000000..f9f3a65c530a --- /dev/null +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.form @@ -0,0 +1,81 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java new file mode 100644 index 000000000000..48282ebfe77b --- /dev/null +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java @@ -0,0 +1,152 @@ +/* + * 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 com.intellij.facet.impl.ui.libraries; + +import com.intellij.ide.IdeBundle; +import com.intellij.openapi.fileChooser.FileChooser; +import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.text.MessageFormat; + +/** + * @author Dmitry Avdeev + */ +public class LibraryOptionsPanel { + + private JLabel myMessage; + private JPanel myPanel; + private JRadioButton myDownloadFromMavenButton; + private JRadioButton myDoNotCreateButton; + private JButton myConfigureButton; + private JRadioButton myLocateOnDiskButton; + + private LibraryCompositionSettings myLibraryCompositionSettings; + + public LibraryOptionsPanel(LibraryCompositionSettings libraryCompositionSettings) { + myLibraryCompositionSettings = libraryCompositionSettings; + ActionListener listener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + updateState(); + } + }; + myDownloadFromMavenButton.addActionListener(listener); + myLocateOnDiskButton.addActionListener(listener); + myDoNotCreateButton.addActionListener(listener); + + myConfigureButton.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + final Point point = myConfigureButton.getLocationOnScreen(); + if (myLocateOnDiskButton.isSelected()) { + EditLibraryDialog dialog = new EditLibraryDialog(myConfigureButton) { + @Override + public Point getInitialLocation() { + point.translate(- 50, - getSize().height); + return point; + } + }; + dialog.show(); + } + else { + new DownloadingOptionsDialog(myConfigureButton, myLibraryCompositionSettings) { + @Override + public Point getInitialLocation() { + point.translate(- 50, - getSize().height); + return point; + } + }.show(); + } + } + }); + + updateState(); + } + + + private VirtualFile[] showFileChooser() { + final FileChooserDescriptor descriptor = new FileChooserDescriptor(false, false, true, false, false, true); + descriptor.setTitle(IdeBundle.message("file.chooser.select.paths.title")); + descriptor.setDescription(IdeBundle.message("file.chooser.multiselect.description")); + return FileChooser.chooseFiles(myConfigureButton, descriptor, getBaseDirectory()); + } + + @Nullable + private VirtualFile getBaseDirectory() { + String path = myLibraryCompositionSettings.getBaseDirectoryForDownloadedFiles(); + VirtualFile dir = LocalFileSystem.getInstance().findFileByPath(path); + if (dir == null) { + path = path.substring(0, path.lastIndexOf('/')); + dir = LocalFileSystem.getInstance().findFileByPath(path); + } + return dir; + } + + private void updateState() { + if (myMessage.isEnabled()) { + myMessage.setForeground(Color.black); + } + myConfigureButton.setEnabled(true); + if (myDownloadFromMavenButton.isSelected()) { + String path = myLibraryCompositionSettings.getDirectoryForDownloadedLibrariesPath().substring(myLibraryCompositionSettings.getBaseDirectoryForDownloadedFiles().length()); + String message = MessageFormat.format("{0} jar(s) will be downloaded into {1} directory
" + + "{2} level library {3} will be created", + myLibraryCompositionSettings.getLibraryInfos().length, + path, + myLibraryCompositionSettings.getLibraryLevel(), + myLibraryCompositionSettings.getLibraryName()); + myMessage.setText(message); + } + else if (myLocateOnDiskButton.isSelected()) { + if (myLibraryCompositionSettings.getAddedJars().isEmpty()) { + myMessage.setForeground(Color.red); + myMessage.setText("Press Configure button to add classes to the library"); + } + else { + String message = MessageFormat.format("{0} level library {1}
" + + "with {2} file(s) will be created", + myLibraryCompositionSettings.getLibraryLevel(), + myLibraryCompositionSettings.getLibraryName(), + myLibraryCompositionSettings.getAddedJars().size()); + myMessage.setText(message); + } + } + else { + myMessage.setText("No library will be created
" + + "You can add it later manually"); + myConfigureButton.setEnabled(false); + } + } + + public LibraryCompositionSettings getLibraryCompositionSettings() { + return myLibraryCompositionSettings; + } + + + public void apply() { + + } + + public JComponent getMainPanel() { + return myPanel; + } +} diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java index e4a143fc4fb6..f43eef778f40 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java @@ -16,9 +16,9 @@ package com.intellij.ide.util.newProjectWizard; -import com.intellij.facet.impl.ui.libraries.LibraryCompositionOptionsPanel; import com.intellij.facet.impl.ui.libraries.LibraryCompositionSettings; import com.intellij.facet.impl.ui.libraries.LibraryDownloadingMirrorsMap; +import com.intellij.facet.impl.ui.libraries.LibraryOptionsPanel; import com.intellij.facet.ui.FacetBasedFrameworkSupportProvider; import com.intellij.facet.ui.libraries.LibraryDownloadInfo; import com.intellij.facet.ui.libraries.LibraryInfo; @@ -131,10 +131,7 @@ public class AddSupportForFrameworksPanel implements Disposable { myLastSelectedNode = selectedNode; if (selectedNode != null) { - final LibraryCompositionOptionsPanel newOptionsPanel = selectedNode.getLibraryCompositionOptionsPanel(myLibrariesContainer, myMirrorsMap); - if (newOptionsPanel != null) { - newOptionsPanel.updateRepositoriesMirrors(myMirrorsMap); - } + selectedNode.getLibraryCompositionOptionsPanel(myLibrariesContainer, myMirrorsMap); } } } @@ -145,9 +142,8 @@ public class AddSupportForFrameworksPanel implements Disposable { private void applyLibraryOptionsForSelected() { if (myLastSelectedNode != null) { - final LibraryCompositionOptionsPanel optionsPanel = myLastSelectedNode.getLibraryCompositionOptionsPanel(myLibrariesContainer, myMirrorsMap); + final LibraryOptionsPanel optionsPanel = myLastSelectedNode.getLibraryCompositionOptionsPanel(myLibrariesContainer, myMirrorsMap); if (optionsPanel != null) { - optionsPanel.saveSelectedRepositoriesMirrors(myMirrorsMap); optionsPanel.apply(); } } @@ -174,13 +170,17 @@ public class AddSupportForFrameworksPanel implements Disposable { private void initializeOptionsPanel(final FrameworkSupportNode node) { final String id = node.getProvider().getId(); if (!myInitializedOptionsPanelIds.contains(id)) { - final JPanel optionsPanel = new JPanel(new VerticalFlowLayout()); + VerticalFlowLayout layout = new VerticalFlowLayout(); + layout.setVerticalFill(true); + final JPanel optionsPanel = new JPanel(layout); + JComponent separator = SeparatorFactory.createSeparator(node.getTitle() + " Settings", null); separator.setBorder(IdeBorderFactory.createEmptyBorder(0, 0, 5, 5)); - optionsPanel.add(separator); + final FrameworkSupportConfigurable configurable = node.getConfigurable(); optionsPanel.add(configurable.getComponent()); + final JPanel librariesOptionsPanelWrapper = new JPanel(new BorderLayout()); optionsPanel.add(librariesOptionsPanelWrapper); configurable.addListener(new FrameworkSupportConfigurableListener() { @@ -197,8 +197,11 @@ public class AddSupportForFrameworksPanel implements Disposable { } private void addLibrariesOptionsPanel(FrameworkSupportNode node, JPanel librariesOptionsPanelWrapper) { - final LibraryCompositionOptionsPanel libraryOptionsPanel = node.getLibraryCompositionOptionsPanel(myLibrariesContainer, myMirrorsMap); + final LibraryOptionsPanel libraryOptionsPanel = node.getLibraryCompositionOptionsPanel(myLibrariesContainer, myMirrorsMap); if (libraryOptionsPanel != null) { + JComponent separator = SeparatorFactory.createSeparator("Libraries", null); + separator.setBorder(IdeBorderFactory.createEmptyBorder(5, 0, 5, 5)); + librariesOptionsPanelWrapper.add(BorderLayout.NORTH, separator); librariesOptionsPanelWrapper.add(BorderLayout.CENTER, libraryOptionsPanel.getMainPanel()); } } diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNode.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNode.java index 351b992ec178..e49fffbe98c1 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNode.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNode.java @@ -15,9 +15,9 @@ */ package com.intellij.ide.util.newProjectWizard; -import com.intellij.facet.impl.ui.libraries.LibraryCompositionOptionsPanel; import com.intellij.facet.impl.ui.libraries.LibraryCompositionSettings; import com.intellij.facet.impl.ui.libraries.LibraryDownloadingMirrorsMap; +import com.intellij.facet.impl.ui.libraries.LibraryOptionsPanel; import com.intellij.facet.ui.libraries.LibraryInfo; import com.intellij.ide.util.frameworkSupport.FrameworkSupportConfigurable; import com.intellij.ide.util.frameworkSupport.FrameworkSupportProvider; @@ -50,7 +50,7 @@ public class FrameworkSupportNode extends CheckedTreeNode { private final List myChildren = new ArrayList(); private LibraryCompositionSettings myLibraryCompositionSettings; private final Computable myBaseDirForLibrariesGetter; - private LibraryCompositionOptionsPanel myLibraryCompositionOptionsPanel; + private LibraryOptionsPanel myLibraryCompositionOptionsPanel; public FrameworkSupportNode(final FrameworkSupportProvider provider, final FrameworkSupportNode parentNode, final FrameworkSupportModelImpl model, Computable baseDirForLibrariesGetter, Disposable parentDisposable) { @@ -75,12 +75,12 @@ public class FrameworkSupportNode extends CheckedTreeNode { } @Nullable - public LibraryCompositionOptionsPanel getLibraryCompositionOptionsPanel(LibrariesContainer librariesContainer, + public LibraryOptionsPanel getLibraryCompositionOptionsPanel(LibrariesContainer librariesContainer, LibraryDownloadingMirrorsMap mirrorsMap) { final LibraryCompositionSettings libraryCompositionSettings = getLibraryCompositionSettings(); if (myLibraryCompositionOptionsPanel == null || !myLibraryCompositionOptionsPanel.getLibraryCompositionSettings().equals(libraryCompositionSettings)) { if (libraryCompositionSettings != null) { - myLibraryCompositionOptionsPanel = new LibraryCompositionOptionsPanel(librariesContainer, libraryCompositionSettings, mirrorsMap); + myLibraryCompositionOptionsPanel = new LibraryOptionsPanel(libraryCompositionSettings); } else { myLibraryCompositionOptionsPanel = null; diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/LibrariesContainer.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/LibrariesContainer.java index 25ed711b32c0..7b7cabfcf609 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/LibrariesContainer.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/LibrariesContainer.java @@ -18,6 +18,7 @@ package com.intellij.openapi.roots.ui.configuration.projectRoot; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -31,7 +32,12 @@ public interface LibrariesContainer { @Nullable Project getProject(); - enum LibraryLevel {GLOBAL, PROJECT, MODULE} + enum LibraryLevel {GLOBAL, PROJECT, MODULE; + + public String toString() { + return StringUtil.capitalize(name().toLowerCase()); + } + } @NotNull Library[] getLibraries(@NotNull LibraryLevel libraryLevel); diff --git a/platform/lang-api/src/com/intellij/facet/ui/libraries/LibraryInfo.java b/platform/lang-api/src/com/intellij/facet/ui/libraries/LibraryInfo.java index 2d2534dfe41f..47fbaae8918c 100644 --- a/platform/lang-api/src/com/intellij/facet/ui/libraries/LibraryInfo.java +++ b/platform/lang-api/src/com/intellij/facet/ui/libraries/LibraryInfo.java @@ -26,9 +26,11 @@ import java.util.Arrays; */ public class LibraryInfo { public static final LibraryInfo[] EMPTY_ARRAY = new LibraryInfo[0]; + private @Nullable final LibraryDownloadInfo myDownloadInfo; private @NonNls final String myPresentableName; private @NonNls final String[] myRequiredClasses; + private boolean mySelected = true; public LibraryInfo(final @NonNls String presentableName, final @Nullable @NonNls String version, final @Nullable @NonNls String downloadingUrl, @@ -87,4 +89,17 @@ public class LibraryInfo { result = 31 * result + Arrays.hashCode(myRequiredClasses); return result; } + + @Override + public String toString() { + return getPresentableName(); + } + + public boolean isSelected() { + return mySelected; + } + + public void setSelected(boolean selected) { + mySelected = selected; + } } From 44d32d4ec9c58b21743e9d2f83612f7f1a96dc1d Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 9 Aug 2010 19:40:38 +0400 Subject: [PATCH 10/36] initial location callback --- .../com/intellij/openapi/ui/DialogWrapper.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index 259fd4249c13..306d30497456 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -23,14 +23,12 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.StackingPopupDispatcher; -import com.intellij.openapi.util.AsyncResult; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.IconLoader; -import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.*; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.UIBundle; import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; +import com.intellij.util.Function; import com.intellij.util.ui.AwtVisitor; import com.intellij.util.ui.DialogUtil; import com.intellij.util.ui.UIUtil; @@ -110,6 +108,7 @@ public abstract class DialogWrapper { private DoNotAskOption myDoNotAsk; private JComponent myPreferredFocusedComponent; + private Computable myInitialLocationCallback; protected String getDoNotShowMessage() { return CommonBundle.message("dialog.options.do.not.show"); @@ -335,7 +334,7 @@ public abstract class DialogWrapper { } panel.setBorder(IdeBorderFactory.createEmptyBorder(new Insets(8, 0, 0, 0))); - + return panel; } @@ -1063,7 +1062,11 @@ public abstract class DialogWrapper { */ @Nullable public Point getInitialLocation() { - return null; + return myInitialLocationCallback == null ? null : myInitialLocationCallback.compute(); + } + + public void setInitialLocationCallback(Computable callback) { + myInitialLocationCallback = callback; } private void registerKeyboardShortcuts() { From fe7748133f1ef296404adbcdfe31a3a935c8416e Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 9 Aug 2010 19:41:18 +0400 Subject: [PATCH 11/36] "Add Framework Support" UI --- .../libraries/DownloadingOptionsDialog.form | 65 ++++--------------- .../libraries/DownloadingOptionsDialog.java | 16 ++--- .../impl/ui/libraries/EditLibraryDialog.form | 58 +---------------- .../impl/ui/libraries/EditLibraryDialog.java | 24 +++++-- .../libraries/LibraryNameAndLevelPanel.form | 55 ++++++++++++++++ .../libraries/LibraryNameAndLevelPanel.java | 46 +++++++++++++ .../ui/libraries/LibraryOptionsPanel.java | 44 ++++++++----- 7 files changed, 172 insertions(+), 136 deletions(-) create mode 100644 java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryNameAndLevelPanel.form create mode 100644 java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryNameAndLevelPanel.java diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.form b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.form index 6255628ea536..cb12f61dac8b 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.form +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.form @@ -15,7 +15,7 @@ - + @@ -23,68 +23,21 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -98,7 +51,7 @@ - + @@ -128,6 +81,14 @@ + + + + + + + + diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.java index 0d24748ffbf4..6478aefeb3a4 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/DownloadingOptionsDialog.java @@ -18,12 +18,10 @@ package com.intellij.facet.impl.ui.libraries; import com.intellij.facet.ui.libraries.LibraryInfo; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.project.ProjectBundle; -import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.ui.CheckBoxList; import com.intellij.ui.CollectionListModel; -import com.intellij.ui.EnumComboBoxModel; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -38,13 +36,13 @@ public class DownloadingOptionsDialog extends DialogWrapper { private JPanel myPanel; private CheckBoxList myFilesList; private TextFieldWithBrowseButton myDirectoryField; - private JTextField myLibraryNameField; - private JComboBox myLevelComboBox; private JCheckBox myDownloadSourcesCheckBox; private JLabel myFilesToDownloadLabel; private JLabel myCopyDownloadedFilesToLabel; private JCheckBox myDownloadJavadocsCheckBox; + private JPanel myNameWrappingPanel; private final LibraryCompositionSettings mySettings; + private final LibraryNameAndLevelPanel myNameAndLevelPanel; protected DownloadingOptionsDialog(Component parent, LibraryCompositionSettings settings) { super(parent, true); @@ -68,9 +66,10 @@ public class DownloadingOptionsDialog extends DialogWrapper { myDownloadSourcesCheckBox.setSelected(settings.isDownloadSources()); myDownloadJavadocsCheckBox.setSelected(settings.isDownloadJavadocs()); - myLibraryNameField.setText(settings.getLibraryName()); - myLevelComboBox.setModel(new EnumComboBoxModel(LibrariesContainer.LibraryLevel.class)); - myLevelComboBox.setSelectedItem(settings.getLibraryLevel()); + + myNameAndLevelPanel = new LibraryNameAndLevelPanel(); + myNameWrappingPanel.add(myNameAndLevelPanel.getPanel()); + myNameAndLevelPanel.reset(settings); init(); } @@ -86,8 +85,7 @@ public class DownloadingOptionsDialog extends DialogWrapper { @Override protected void doOKAction() { - mySettings.setLibraryName(myLibraryNameField.getText()); - mySettings.setLibraryLevel((LibrariesContainer.LibraryLevel)myLevelComboBox.getSelectedItem()); + myNameAndLevelPanel.apply(mySettings); mySettings.setDirectoryForDownloadedLibrariesPath(myDirectoryField.getText()); LibraryInfo[] libraryInfos = mySettings.getLibraryInfos(); for (int i = 0, libraryInfosLength = libraryInfos.length; i < libraryInfosLength; i++) { diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.form b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.form index 8a1edd8da239..c9f9c05a80cb 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.form +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.form @@ -1,6 +1,6 @@
- + @@ -16,65 +16,13 @@ - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java index e25bf7c0f1e1..232b7b4ed56f 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java @@ -34,13 +34,15 @@ public class EditLibraryDialog extends DialogWrapper { private ApplicationLibraryTable myLibraryTable = new ApplicationLibraryTable(); private Library myLibrary; - private JTextField myTextField1; - private JComboBox myComboBox1; private JPanel myEditorPanel; private JPanel myPanel; + private JPanel myNameAndLevelPanelWrapper; + private final LibraryNameAndLevelPanel myNameAndLevelPanel; + private LibraryCompositionSettings mySettings; - protected EditLibraryDialog(Component parent) { + public EditLibraryDialog(Component parent, LibraryCompositionSettings settings) { super(parent, true); + mySettings = settings; setTitle("Edit Library"); ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override @@ -48,10 +50,17 @@ public class EditLibraryDialog extends DialogWrapper { myLibrary = myLibraryTable.createLibrary("xxx"); } }); + + myNameAndLevelPanel = new LibraryNameAndLevelPanel(); + myNameAndLevelPanel.reset(mySettings); init(); } + public Library getLibrary() { + return myLibrary; + } + @Override protected JComponent createCenterPanel() { @@ -78,7 +87,14 @@ public class EditLibraryDialog extends DialogWrapper { } }, myLibrary).getComponent(); - myEditorPanel.add(editor, BorderLayout.CENTER); + myEditorPanel.add(editor); + myNameAndLevelPanelWrapper.add(myNameAndLevelPanel.getPanel()); return myPanel; } + + @Override + protected void doOKAction() { + myNameAndLevelPanel.apply(mySettings); + super.doOKAction(); + } } diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryNameAndLevelPanel.form b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryNameAndLevelPanel.form new file mode 100644 index 000000000000..1e6d12ecd07f --- /dev/null +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryNameAndLevelPanel.form @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryNameAndLevelPanel.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryNameAndLevelPanel.java new file mode 100644 index 000000000000..0d80837daa72 --- /dev/null +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryNameAndLevelPanel.java @@ -0,0 +1,46 @@ +/* + * 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 com.intellij.facet.impl.ui.libraries; + +import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer; +import com.intellij.ui.EnumComboBoxModel; + +import javax.swing.*; + +/** + * @author Dmitry Avdeev + */ +class LibraryNameAndLevelPanel { + + private JTextField myLibraryNameField; + private JComboBox myLevelComboBox; + private JPanel myPanel; + + void reset(LibraryCompositionSettings settings) { + myLibraryNameField.setText(settings.getLibraryName()); + myLevelComboBox.setModel(new EnumComboBoxModel(LibrariesContainer.LibraryLevel.class)); + myLevelComboBox.setSelectedItem(settings.getLibraryLevel()); + } + + void apply(LibraryCompositionSettings settings) { + settings.setLibraryName(myLibraryNameField.getText()); + settings.setLibraryLevel((LibrariesContainer.LibraryLevel)myLevelComboBox.getSelectedItem()); + } + + public JPanel getPanel() { + return myPanel; + } +} diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java index 48282ebfe77b..15be376a25c7 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java @@ -18,6 +18,10 @@ package com.intellij.facet.impl.ui.libraries; import com.intellij.ide.IdeBundle; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.Nullable; @@ -56,32 +60,40 @@ public class LibraryOptionsPanel { myConfigureButton.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { - final Point point = myConfigureButton.getLocationOnScreen(); if (myLocateOnDiskButton.isSelected()) { - EditLibraryDialog dialog = new EditLibraryDialog(myConfigureButton) { - @Override - public Point getInitialLocation() { - point.translate(- 50, - getSize().height); - return point; + EditLibraryDialog dialog = new EditLibraryDialog(myConfigureButton, myLibraryCompositionSettings); + if (myLibraryCompositionSettings.getAddedJars().isEmpty()) { + VirtualFile[] files = showFileChooser(); + Library.ModifiableModel modifiableModel = dialog.getLibrary().getModifiableModel(); + for (VirtualFile file : files) { + modifiableModel.addRoot(file, OrderRootType.CLASSES); } - }; - dialog.show(); + modifiableModel.commit(); + } + showDialog(dialog); } else { - new DownloadingOptionsDialog(myConfigureButton, myLibraryCompositionSettings) { - @Override - public Point getInitialLocation() { - point.translate(- 50, - getSize().height); - return point; - } - }.show(); + DownloadingOptionsDialog dialog = new DownloadingOptionsDialog(myConfigureButton, myLibraryCompositionSettings); + showDialog(dialog); } + updateState(); } }); updateState(); } + private void showDialog(final DialogWrapper dialog) { + dialog.setInitialLocationCallback(new Computable() { + @Override + public Point compute() { + Point point = myConfigureButton.getLocationOnScreen(); + point.translate(- 50, - dialog.getSize().height); + return point; + } + }); + dialog.show(); + } private VirtualFile[] showFileChooser() { final FileChooserDescriptor descriptor = new FileChooserDescriptor(false, false, true, false, false, true); @@ -109,7 +121,7 @@ public class LibraryOptionsPanel { if (myDownloadFromMavenButton.isSelected()) { String path = myLibraryCompositionSettings.getDirectoryForDownloadedLibrariesPath().substring(myLibraryCompositionSettings.getBaseDirectoryForDownloadedFiles().length()); String message = MessageFormat.format("{0} jar(s) will be downloaded into {1} directory
" + - "{2} level library {3} will be created", + "{2} library {3} will be created", myLibraryCompositionSettings.getLibraryInfos().length, path, myLibraryCompositionSettings.getLibraryLevel(), From 13da3c27c797f34814378b0b4680a3885cf53a39 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 10 Aug 2010 20:06:45 +0400 Subject: [PATCH 12/36] bind radio buttons to enum --- .../util/ui/RadioButtonEnumModel.java | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 platform/util/src/com/intellij/util/ui/RadioButtonEnumModel.java diff --git a/platform/util/src/com/intellij/util/ui/RadioButtonEnumModel.java b/platform/util/src/com/intellij/util/ui/RadioButtonEnumModel.java new file mode 100644 index 000000000000..b894fed10531 --- /dev/null +++ b/platform/util/src/com/intellij/util/ui/RadioButtonEnumModel.java @@ -0,0 +1,68 @@ +/* + * 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 com.intellij.util.ui; + +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; + +import javax.swing.*; +import java.awt.event.ActionListener; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * @author Dmitry Avdeev + */ +public class RadioButtonEnumModel> { + + private final ButtonGroup myGroup; + private final List myModels; + private final List myEnums; + + public static > RadioButtonEnumModel bindEnum(Class e, ButtonGroup group) { + return new RadioButtonEnumModel(e, group); + } + + private RadioButtonEnumModel(Class e, ButtonGroup group) { + + myGroup = group; + myModels = ContainerUtil.map(Collections.list(myGroup.getElements()), new Function() { + @Override + public ButtonModel fun(AbstractButton abstractButton) { + return abstractButton.getModel(); + } + }); + myEnums = Arrays.asList(e.getEnumConstants()); + } + + public E getSelected() { + ButtonModel selection = myGroup.getSelection(); + int i = myModels.indexOf(selection); + return myEnums.get(i); + } + + public void setSelected(E e) { + int i = myEnums.indexOf(e); + myGroup.setSelected(myModels.get(i), true); + } + + public void addActionListener(ActionListener listener) { + for (AbstractButton button : Collections.list(myGroup.getElements())) { + button.addActionListener(listener); + } + } +} From cae300cc8f3de8b5a275245addda672fc26a8477 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 10 Aug 2010 20:07:14 +0400 Subject: [PATCH 13/36] "Add Framework Support" UI --- .../ui/libraries/ChooseLibrariesDialog.java | 4 +- .../ui/libraries/LibraryOptionsPanel.form | 104 +++++++----- .../ui/libraries/LibraryOptionsPanel.java | 155 ++++++++++++------ .../FrameworkSupportNode.java | 2 +- 4 files changed, 172 insertions(+), 93 deletions(-) diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/ChooseLibrariesDialog.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/ChooseLibrariesDialog.java index 2ff0bd8765be..1e54e93103c6 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/ChooseLibrariesDialog.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/ChooseLibrariesDialog.java @@ -56,8 +56,8 @@ public class ChooseLibrariesDialog extends DialogWrapper { return myChooser.getMarkedElements(); } - private static class LibraryElementChooser extends ElementsChooser { - private LibraryElementChooser(final List elements) { + static class LibraryElementChooser extends ElementsChooser { + LibraryElementChooser(final List elements) { super(elements, false); } diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.form b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.form index f9f3a65c530a..9fafa7145819 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.form +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.form @@ -1,25 +1,16 @@
- + - + - - - - - - - - - - + @@ -30,37 +21,17 @@ - - - - - - - - + - + - - - - - - - - - - - - - - + @@ -68,14 +39,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java index 15be376a25c7..3238e3efc19e 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java @@ -15,15 +15,19 @@ */ package com.intellij.facet.impl.ui.libraries; +import com.intellij.facet.ui.libraries.LibraryInfo; import com.intellij.ide.IdeBundle; +import com.intellij.ide.util.ElementsChooser; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.ui.RadioButtonEnumModel; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -31,6 +35,8 @@ import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; /** * @author Dmitry Avdeev @@ -39,42 +45,67 @@ public class LibraryOptionsPanel { private JLabel myMessage; private JPanel myPanel; - private JRadioButton myDownloadFromMavenButton; - private JRadioButton myDoNotCreateButton; private JButton myConfigureButton; - private JRadioButton myLocateOnDiskButton; + private JPanel myExistingLibrariesPanel; + private JLabel myExistingLibrariesLabel; + private ButtonGroup myButtonGroup; + private ElementsChooser myLibrariesChooser; private LibraryCompositionSettings myLibraryCompositionSettings; + private LibrariesContainer myLibrariesContainer; + + + private enum Choice { + DOWNLOAD, + PICK_FILES, + DO_NOT_CREATE + } + + private RadioButtonEnumModel myButtonEnumModel; + + public LibraryOptionsPanel(LibraryCompositionSettings libraryCompositionSettings, LibrariesContainer librariesContainer) { - public LibraryOptionsPanel(LibraryCompositionSettings libraryCompositionSettings) { myLibraryCompositionSettings = libraryCompositionSettings; + myLibrariesContainer = librariesContainer; + + List suitableLibraries = calculateSuitableLibraries(); + if (!suitableLibraries.isEmpty()) { + myLibraryCompositionSettings.setUsedLibraries(suitableLibraries); + } + + myLibrariesChooser = new ChooseLibrariesDialog.LibraryElementChooser(suitableLibraries); + myLibrariesChooser.getComponents()[0].setPreferredSize(new Dimension(10, 10)); // this makes scrollbars to work + myExistingLibrariesPanel.add(myLibrariesChooser); + myExistingLibrariesLabel.setLabelFor(myLibrariesChooser.getComponent()); + + myButtonEnumModel = RadioButtonEnumModel.bindEnum(Choice.class, myButtonGroup); ActionListener listener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { updateState(); } }; - myDownloadFromMavenButton.addActionListener(listener); - myLocateOnDiskButton.addActionListener(listener); - myDoNotCreateButton.addActionListener(listener); + myButtonEnumModel.addActionListener(listener); myConfigureButton.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { - if (myLocateOnDiskButton.isSelected()) { - EditLibraryDialog dialog = new EditLibraryDialog(myConfigureButton, myLibraryCompositionSettings); - if (myLibraryCompositionSettings.getAddedJars().isEmpty()) { - VirtualFile[] files = showFileChooser(); - Library.ModifiableModel modifiableModel = dialog.getLibrary().getModifiableModel(); - for (VirtualFile file : files) { - modifiableModel.addRoot(file, OrderRootType.CLASSES); + switch (myButtonEnumModel.getSelected()) { + case DOWNLOAD: + showDialog(new DownloadingOptionsDialog(myConfigureButton, myLibraryCompositionSettings)); + break; + case PICK_FILES: + EditLibraryDialog dialog = new EditLibraryDialog(myConfigureButton, myLibraryCompositionSettings); + if (myLibraryCompositionSettings.getAddedJars().isEmpty()) { + VirtualFile[] files = showFileChooser(); + Library.ModifiableModel modifiableModel = dialog.getLibrary().getModifiableModel(); + for (VirtualFile file : files) { + modifiableModel.addRoot(file, OrderRootType.CLASSES); + } } - modifiableModel.commit(); - } - showDialog(dialog); - } - else { - DownloadingOptionsDialog dialog = new DownloadingOptionsDialog(myConfigureButton, myLibraryCompositionSettings); - showDialog(dialog); + showDialog(dialog); + break; + case DO_NOT_CREATE: + break; } updateState(); } @@ -88,13 +119,28 @@ public class LibraryOptionsPanel { @Override public Point compute() { Point point = myConfigureButton.getLocationOnScreen(); - point.translate(- 50, - dialog.getSize().height); + point.translate(- 50, - dialog.getSize().height - 20); return point; } }); dialog.show(); } + private List calculateSuitableLibraries() { + LibraryInfo[] libraryInfos = myLibraryCompositionSettings.getLibraryInfos(); + RequiredLibrariesInfo requiredLibraries = new RequiredLibrariesInfo(libraryInfos); + List suitableLibraries = new ArrayList(); + Library[] libraries = myLibrariesContainer.getAllLibraries(); + for (Library library : libraries) { + RequiredLibrariesInfo.RequiredClassesNotFoundInfo info = + requiredLibraries.checkLibraries(myLibrariesContainer.getLibraryFiles(library, OrderRootType.CLASSES), false); + if (info == null || info.getLibraryInfos().length < libraryInfos.length) { + suitableLibraries.add(library); + } + } + return suitableLibraries; + } + private VirtualFile[] showFileChooser() { final FileChooserDescriptor descriptor = new FileChooserDescriptor(false, false, true, false, false, true); descriptor.setTitle(IdeBundle.message("file.chooser.select.paths.title")); @@ -112,41 +158,46 @@ public class LibraryOptionsPanel { } return dir; } - + private void updateState() { if (myMessage.isEnabled()) { myMessage.setForeground(Color.black); } myConfigureButton.setEnabled(true); - if (myDownloadFromMavenButton.isSelected()) { - String path = myLibraryCompositionSettings.getDirectoryForDownloadedLibrariesPath().substring(myLibraryCompositionSettings.getBaseDirectoryForDownloadedFiles().length()); - String message = MessageFormat.format("{0} jar(s) will be downloaded into {1} directory
" + - "{2} library {3} will be created", - myLibraryCompositionSettings.getLibraryInfos().length, - path, - myLibraryCompositionSettings.getLibraryLevel(), - myLibraryCompositionSettings.getLibraryName()); - myMessage.setText(message); - } - else if (myLocateOnDiskButton.isSelected()) { - if (myLibraryCompositionSettings.getAddedJars().isEmpty()) { - myMessage.setForeground(Color.red); - myMessage.setText("Press Configure button to add classes to the library"); - } - else { - String message = MessageFormat.format("{0} level library {1}
" + - "with {2} file(s) will be created", - myLibraryCompositionSettings.getLibraryLevel(), - myLibraryCompositionSettings.getLibraryName(), - myLibraryCompositionSettings.getAddedJars().size()); - myMessage.setText(message); - } - } - else { - myMessage.setText("No library will be created
" + - "You can add it later manually"); - myConfigureButton.setEnabled(false); + + String message = ""; + + switch (myButtonEnumModel.getSelected()) { + case DOWNLOAD: + String path = myLibraryCompositionSettings.getDirectoryForDownloadedLibrariesPath() + .substring(myLibraryCompositionSettings.getBaseDirectoryForDownloadedFiles().length()); + message = MessageFormat.format("{0} jar(s) will be downloaded into {1} directory
" + + "{2} library {3} will be created", + myLibraryCompositionSettings.getLibraryInfos().length, + path, + myLibraryCompositionSettings.getLibraryLevel(), + myLibraryCompositionSettings.getLibraryName()); + break; + case PICK_FILES: + if (myLibraryCompositionSettings.getAddedJars().isEmpty()) { + myMessage.setForeground(Color.red); + message = "Press Configure button to add classes to the library"; + } + else { + message = MessageFormat.format("{0} level library {1}" + + "with {2} file(s) will be created", + myLibraryCompositionSettings.getLibraryLevel(), + myLibraryCompositionSettings.getLibraryName(), + myLibraryCompositionSettings.getAddedJars().size()); + } + break; + case DO_NOT_CREATE: + message = "No new library will be created"; + myConfigureButton.setEnabled(false); + break; } + + myMessage.setText("" + message + ""); } public LibraryCompositionSettings getLibraryCompositionSettings() { @@ -155,7 +206,7 @@ public class LibraryOptionsPanel { public void apply() { - + myLibraryCompositionSettings.setUsedLibraries(myLibrariesChooser.getMarkedElements()); } public JComponent getMainPanel() { diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNode.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNode.java index e49fffbe98c1..bf9e8a1f3fe3 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNode.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNode.java @@ -80,7 +80,7 @@ public class FrameworkSupportNode extends CheckedTreeNode { final LibraryCompositionSettings libraryCompositionSettings = getLibraryCompositionSettings(); if (myLibraryCompositionOptionsPanel == null || !myLibraryCompositionOptionsPanel.getLibraryCompositionSettings().equals(libraryCompositionSettings)) { if (libraryCompositionSettings != null) { - myLibraryCompositionOptionsPanel = new LibraryOptionsPanel(libraryCompositionSettings); + myLibraryCompositionOptionsPanel = new LibraryOptionsPanel(libraryCompositionSettings, librariesContainer); } else { myLibraryCompositionOptionsPanel = null; From 36af2c48af5a519aadf7845c7ed3f75e55d3488c Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 11 Aug 2010 14:02:20 +0400 Subject: [PATCH 14/36] "Add Framework Support" UI --- .../impl/ui/libraries/EditLibraryDialog.java | 65 +++++++++---------- .../LibraryCompositionOptionsPanel.java | 2 - .../libraries/LibraryCompositionSettings.java | 56 ++++++++++------ .../ui/libraries/LibraryOptionsPanel.java | 60 +++++++++-------- .../AddSupportForFrameworksPanel.java | 2 +- .../FrameworkSupportNode.java | 3 +- 6 files changed, 101 insertions(+), 87 deletions(-) diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java index 232b7b4ed56f..33f61e2cb61e 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java @@ -15,14 +15,13 @@ */ package com.intellij.facet.impl.ui.libraries; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.roots.impl.libraries.ApplicationLibraryTable; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.roots.libraries.LibraryTablePresentation; import com.intellij.openapi.roots.ui.configuration.LibraryTableModifiableModelProvider; import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryTableEditor; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.Disposer; import javax.swing.*; import java.awt.*; @@ -32,24 +31,44 @@ import java.awt.*; */ public class EditLibraryDialog extends DialogWrapper { - private ApplicationLibraryTable myLibraryTable = new ApplicationLibraryTable(); - private Library myLibrary; private JPanel myEditorPanel; private JPanel myPanel; private JPanel myNameAndLevelPanelWrapper; private final LibraryNameAndLevelPanel myNameAndLevelPanel; private LibraryCompositionSettings mySettings; + private LibraryTableEditor myLibraryTableEditor; public EditLibraryDialog(Component parent, LibraryCompositionSettings settings) { super(parent, true); mySettings = settings; - setTitle("Edit Library"); - ApplicationManager.getApplication().runWriteAction(new Runnable() { + final Library library = settings.getOrCreateLibrary(); + + myLibraryTableEditor = LibraryTableEditor.editLibrary(new LibraryTableModifiableModelProvider() { + @Override - public void run() { - myLibrary = myLibraryTable.createLibrary("xxx"); + public LibraryTable.ModifiableModel getModifiableModel() { + return library.getTable().getModifiableModel(); } - }); + + @Override + public String getTableLevel() { + return library.getTable().getTableLevel(); + } + + @Override + public LibraryTablePresentation getLibraryTablePresentation() { + return library.getTable().getPresentation(); + } + + @Override + public boolean isLibraryTableEditable() { + return false; + } + }, library); + + Disposer.register(getDisposable(), myLibraryTableEditor); + + setTitle("Edit Library"); myNameAndLevelPanel = new LibraryNameAndLevelPanel(); myNameAndLevelPanel.reset(mySettings); @@ -57,36 +76,10 @@ public class EditLibraryDialog extends DialogWrapper { } - public Library getLibrary() { - return myLibrary; - } - @Override protected JComponent createCenterPanel() { - JComponent editor = LibraryTableEditor.editLibrary(new LibraryTableModifiableModelProvider() { - - @Override - public LibraryTable.ModifiableModel getModifiableModel() { - return myLibraryTable.getModifiableModel(); - } - - @Override - public String getTableLevel() { - return myLibraryTable.getTableLevel(); - } - - @Override - public LibraryTablePresentation getLibraryTablePresentation() { - return myLibraryTable.getPresentation(); - } - - @Override - public boolean isLibraryTableEditable() { - return false; - } - }, myLibrary).getComponent(); - + JComponent editor = myLibraryTableEditor.getComponent(); myEditorPanel.add(editor); myNameAndLevelPanelWrapper.add(myNameAndLevelPanel.getPanel()); return myPanel; diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionOptionsPanel.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionOptionsPanel.java index 1f7d0c5402e8..4d9f99ef272c 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionOptionsPanel.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionOptionsPanel.java @@ -85,7 +85,6 @@ public class LibraryCompositionOptionsPanel { myDirectoryField.addBrowseFolderListener(ProjectBundle.message("file.chooser.directory.for.downloaded.libraries.title"), ProjectBundle.message("file.chooser.directory.for.downloaded.libraries.description"), null, FileChooserDescriptorFactory.createSingleFolderDescriptor()); - myAddedJars.addAll(myLibraryCompositionSettings.getAddedJars()); myUsedLibraries.addAll(myLibraryCompositionSettings.getUsedLibraries()); myAddJarsButton.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { @@ -245,7 +244,6 @@ public class LibraryCompositionOptionsPanel { myLibraryCompositionSettings.setDownloadLibraries(false); } myLibraryCompositionSettings.setUsedLibraries(myUsedLibraries); - myLibraryCompositionSettings.setAddedJars(myAddedJars); myLibraryCompositionSettings.setLibraryLevel(myLibraryLevels.getKey((String)myLibraryLevelComboBox.getSelectedItem())); myLibraryCompositionSettings.setLibraryName(myLibraryNameField.getText()); } diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java index b17a33933d0a..12381bc1682d 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java @@ -17,11 +17,15 @@ package com.intellij.facet.impl.ui.libraries; import com.intellij.facet.ui.libraries.LibraryDownloadInfo; import com.intellij.facet.ui.libraries.LibraryInfo; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.impl.libraries.ApplicationLibraryTable; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer; import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainerFactory; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.ContainerUtil; @@ -35,13 +39,13 @@ import java.util.*; /** * @author nik */ -public class LibraryCompositionSettings { +public class LibraryCompositionSettings implements Disposable { + @NonNls private static final String DEFAULT_LIB_FOLDER = "lib"; private final LibraryInfo[] myLibraryInfos; private final String myBaseDirectoryForDownloadedFiles; private final String myTitle; private String myDirectoryForDownloadedLibrariesPath; - private final Set myAddedJars = new LinkedHashSet(); private boolean myDownloadLibraries = true; private final Set myUsedLibraries = new LinkedHashSet(); private LibrariesContainer.LibraryLevel myLibraryLevel = LibrariesContainer.LibraryLevel.PROJECT; @@ -49,6 +53,7 @@ public class LibraryCompositionSettings { private final Icon myIcon; private boolean myDownloadSources = true; private boolean myDownloadJavadocs = true; + private Library myLibrary; public LibraryCompositionSettings(final @NotNull LibraryInfo[] libraryInfos, final @NotNull String defaultLibraryName, @@ -75,15 +80,6 @@ public class LibraryCompositionSettings { myDirectoryForDownloadedLibrariesPath = directoryForDownloadedLibrariesPath; } - public Set getAddedJars() { - return myAddedJars; - } - - public void setAddedJars(final Collection addedJars) { - myAddedJars.clear(); - myAddedJars.addAll(addedJars); - } - public boolean isDownloadLibraries() { return myDownloadLibraries; } @@ -116,13 +112,13 @@ public class LibraryCompositionSettings { return myTitle; } - public boolean downloadFiles(final @NotNull LibraryDownloadingMirrorsMap mirrorsMap, @NotNull LibrariesContainer librariesContainer, final @NotNull JComponent parent, + public boolean downloadFiles(final @NotNull LibraryDownloadingMirrorsMap mirrorsMap, + @NotNull LibrariesContainer librariesContainer, final @NotNull JComponent parent, boolean all) { if (myDownloadLibraries) { RequiredLibrariesInfo requiredLibraries = new RequiredLibrariesInfo(getLibraryInfos()); List roots = new ArrayList(); - roots.addAll(myAddedJars); for (Library library : myUsedLibraries) { ContainerUtil.addAll(roots, librariesContainer.getLibraryFiles(library, OrderRootType.CLASSES)); } @@ -138,7 +134,6 @@ public class LibraryCompositionSettings { if (files.length != downloadingInfos.length) { return false; } - ContainerUtil.addAll(myAddedJars, files); } } } @@ -147,8 +142,8 @@ public class LibraryCompositionSettings { @Nullable private Library createLibrary(final ModifiableRootModel rootModel, @Nullable LibrariesContainer additionalContainer) { - if (!myAddedJars.isEmpty()) { - VirtualFile[] roots = VfsUtil.toVirtualFileArray(myAddedJars); + if (myLibrary != null) { + VirtualFile[] roots = myLibrary.getFiles(OrderRootType.CLASSES); return LibrariesContainerFactory.createLibrary(additionalContainer, LibrariesContainerFactory.createContainer(rootModel), myLibraryName, myLibraryLevel, roots, VirtualFile.EMPTY_ARRAY); } @@ -171,14 +166,10 @@ public class LibraryCompositionSettings { return myIcon; } - @Nullable - public Library addLibraries(final ModifiableRootModel rootModel, final List addedLibraries) { - return addLibraries(rootModel, addedLibraries, null); - } - @Nullable public Library addLibraries(final @NotNull ModifiableRootModel rootModel, final @NotNull List addedLibraries, final @Nullable LibrariesContainer librariesContainer) { + Library library = createLibrary(rootModel, librariesContainer); if (library != null) { @@ -209,4 +200,27 @@ public class LibraryCompositionSettings { public void setDownloadJavadocs(boolean downloadJavadocs) { myDownloadJavadocs = downloadJavadocs; } + + @Nullable + public Library getLibrary() { + return myLibrary; + } + + @NotNull + public Library getOrCreateLibrary() { + if (myLibrary == null) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + myLibrary = new ApplicationLibraryTable().createLibrary(); + Disposer.register(LibraryCompositionSettings.this, myLibrary); + } + }); + } + return myLibrary; + } + + @Override + public void dispose() { + } } diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java index 3238e3efc19e..deff8392b746 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java @@ -18,6 +18,7 @@ package com.intellij.facet.impl.ui.libraries; import com.intellij.facet.ui.libraries.LibraryInfo; import com.intellij.ide.IdeBundle; import com.intellij.ide.util.ElementsChooser; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.roots.OrderRootType; @@ -51,7 +52,7 @@ public class LibraryOptionsPanel { private ButtonGroup myButtonGroup; private ElementsChooser myLibrariesChooser; - private LibraryCompositionSettings myLibraryCompositionSettings; + private LibraryCompositionSettings mySettings; private LibrariesContainer myLibrariesContainer; @@ -63,14 +64,14 @@ public class LibraryOptionsPanel { private RadioButtonEnumModel myButtonEnumModel; - public LibraryOptionsPanel(LibraryCompositionSettings libraryCompositionSettings, LibrariesContainer librariesContainer) { + public LibraryOptionsPanel(LibraryCompositionSettings settings, LibrariesContainer librariesContainer) { - myLibraryCompositionSettings = libraryCompositionSettings; + mySettings = settings; myLibrariesContainer = librariesContainer; List suitableLibraries = calculateSuitableLibraries(); if (!suitableLibraries.isEmpty()) { - myLibraryCompositionSettings.setUsedLibraries(suitableLibraries); + mySettings.setUsedLibraries(suitableLibraries); } myLibrariesChooser = new ChooseLibrariesDialog.LibraryElementChooser(suitableLibraries); @@ -79,29 +80,34 @@ public class LibraryOptionsPanel { myExistingLibrariesLabel.setLabelFor(myLibrariesChooser.getComponent()); myButtonEnumModel = RadioButtonEnumModel.bindEnum(Choice.class, myButtonGroup); - ActionListener listener = new ActionListener() { + myButtonEnumModel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { updateState(); } - }; - myButtonEnumModel.addActionListener(listener); + }); myConfigureButton.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { switch (myButtonEnumModel.getSelected()) { case DOWNLOAD: - showDialog(new DownloadingOptionsDialog(myConfigureButton, myLibraryCompositionSettings)); + showDialog(new DownloadingOptionsDialog(myConfigureButton, mySettings)); break; case PICK_FILES: - EditLibraryDialog dialog = new EditLibraryDialog(myConfigureButton, myLibraryCompositionSettings); - if (myLibraryCompositionSettings.getAddedJars().isEmpty()) { + if (mySettings.getLibrary() == null) { VirtualFile[] files = showFileChooser(); - Library.ModifiableModel modifiableModel = dialog.getLibrary().getModifiableModel(); + final Library.ModifiableModel modifiableModel = mySettings.getOrCreateLibrary().getModifiableModel(); for (VirtualFile file : files) { modifiableModel.addRoot(file, OrderRootType.CLASSES); } + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + modifiableModel.commit(); + } + }); } + EditLibraryDialog dialog = new EditLibraryDialog(myConfigureButton, mySettings); showDialog(dialog); break; case DO_NOT_CREATE: @@ -127,7 +133,7 @@ public class LibraryOptionsPanel { } private List calculateSuitableLibraries() { - LibraryInfo[] libraryInfos = myLibraryCompositionSettings.getLibraryInfos(); + LibraryInfo[] libraryInfos = mySettings.getLibraryInfos(); RequiredLibrariesInfo requiredLibraries = new RequiredLibrariesInfo(libraryInfos); List suitableLibraries = new ArrayList(); Library[] libraries = myLibrariesContainer.getAllLibraries(); @@ -150,7 +156,7 @@ public class LibraryOptionsPanel { @Nullable private VirtualFile getBaseDirectory() { - String path = myLibraryCompositionSettings.getBaseDirectoryForDownloadedFiles(); + String path = mySettings.getBaseDirectoryForDownloadedFiles(); VirtualFile dir = LocalFileSystem.getInstance().findFileByPath(path); if (dir == null) { path = path.substring(0, path.lastIndexOf('/')); @@ -169,26 +175,27 @@ public class LibraryOptionsPanel { switch (myButtonEnumModel.getSelected()) { case DOWNLOAD: - String path = myLibraryCompositionSettings.getDirectoryForDownloadedLibrariesPath() - .substring(myLibraryCompositionSettings.getBaseDirectoryForDownloadedFiles().length()); + String path = mySettings.getDirectoryForDownloadedLibrariesPath() + .substring(mySettings.getBaseDirectoryForDownloadedFiles().length()); message = MessageFormat.format("{0} jar(s) will be downloaded into {1} directory
" + "{2} library {3} will be created", - myLibraryCompositionSettings.getLibraryInfos().length, + mySettings.getLibraryInfos().length, path, - myLibraryCompositionSettings.getLibraryLevel(), - myLibraryCompositionSettings.getLibraryName()); + mySettings.getLibraryLevel(), + mySettings.getLibraryName()); break; case PICK_FILES: - if (myLibraryCompositionSettings.getAddedJars().isEmpty()) { + Library library = mySettings.getLibrary(); + if (library == null) { myMessage.setForeground(Color.red); message = "Press Configure button to add classes to the library"; } else { message = MessageFormat.format("{0} level library {1}" + - "with {2} file(s) will be created", - myLibraryCompositionSettings.getLibraryLevel(), - myLibraryCompositionSettings.getLibraryName(), - myLibraryCompositionSettings.getAddedJars().size()); + " with {2} file(s) will be created", + mySettings.getLibraryLevel(), + mySettings.getLibraryName(), + library.getFiles(OrderRootType.CLASSES).length); } break; case DO_NOT_CREATE: @@ -200,13 +207,14 @@ public class LibraryOptionsPanel { myMessage.setText("" + message + ""); } - public LibraryCompositionSettings getLibraryCompositionSettings() { - return myLibraryCompositionSettings; + public LibraryCompositionSettings getSettings() { + return mySettings; } public void apply() { - myLibraryCompositionSettings.setUsedLibraries(myLibrariesChooser.getMarkedElements()); + mySettings.setUsedLibraries(myLibrariesChooser.getMarkedElements()); + mySettings.setDownloadLibraries(myButtonEnumModel.getSelected() == Choice.DOWNLOAD); } public JComponent getMainPanel() { diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java index f43eef778f40..6918dfc79187 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java @@ -351,7 +351,7 @@ public class AddSupportForFrameworksPanel implements Disposable { FrameworkSupportConfigurable configurable = node.getConfigurable(); selectedConfigurables.add(configurable); final LibraryCompositionSettings settings = node.getLibraryCompositionSettings(); - Library library = settings != null ? settings.addLibraries(rootModel, addedLibraries) : null; + Library library = settings != null ? settings.addLibraries(rootModel, addedLibraries, null) : null; configurable.addSupport(module, rootModel, library); } for (FrameworkSupportNode node : selectedFrameworks) { diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNode.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNode.java index bf9e8a1f3fe3..dacc5f229ee1 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNode.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNode.java @@ -78,7 +78,7 @@ public class FrameworkSupportNode extends CheckedTreeNode { public LibraryOptionsPanel getLibraryCompositionOptionsPanel(LibrariesContainer librariesContainer, LibraryDownloadingMirrorsMap mirrorsMap) { final LibraryCompositionSettings libraryCompositionSettings = getLibraryCompositionSettings(); - if (myLibraryCompositionOptionsPanel == null || !myLibraryCompositionOptionsPanel.getLibraryCompositionSettings().equals(libraryCompositionSettings)) { + if (myLibraryCompositionOptionsPanel == null || !myLibraryCompositionOptionsPanel.getSettings().equals(libraryCompositionSettings)) { if (libraryCompositionSettings != null) { myLibraryCompositionOptionsPanel = new LibraryOptionsPanel(libraryCompositionSettings, librariesContainer); } @@ -126,6 +126,7 @@ public class FrameworkSupportNode extends CheckedTreeNode { if (libraries.length != 0) { myLibraryCompositionSettings = new LibraryCompositionSettings(libraries, myConfigurable.getSelectedVersion().getLibraryName(), myBaseDirForLibrariesGetter.compute(), "Libraries", myProvider.getIcon()); + Disposer.register(myConfigurable, myLibraryCompositionSettings); } else { myLibraryCompositionSettings = null; From 8aa7607162422a6d01a569107e24d66b9b0c5063 Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 11 Aug 2010 14:06:49 +0400 Subject: [PATCH 15/36] VCS: diff from annotations: jump to the line on which diff was invoked --- .../ui/views/DirectoryHistoryDialog.java | 6 +- .../openapi/diff/DiffNavigationContext.java | 34 ++++ .../com/intellij/openapi/diff/DiffTool.java | 3 + .../openapi/diff/impl/DiffPanelImpl.java | 135 +++++++++++++++ .../util/containers/CacheOneStepIterator.java | 54 ++++++ .../vcs/actions/AnnotateToggleAction.java | 160 +++++++++++++++++- .../vcs/changes/actions/ShowDiffAction.java | 44 ++--- .../changes/actions/ShowDiffUIContext.java | 58 +++++++ .../patch/ApplyPatchDifferentiatedDialog.java | 3 +- .../shelf/DiffShelvedChangesAction.java | 7 +- .../vcs/changes/ui/ChangesBrowser.java | 5 +- .../vcs/update/ShowUpdatedDiffAction.java | 6 +- 12 files changed, 474 insertions(+), 41 deletions(-) create mode 100644 platform/platform-api/src/com/intellij/openapi/diff/DiffNavigationContext.java create mode 100644 platform/util/src/com/intellij/util/containers/CacheOneStepIterator.java create mode 100644 platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffUIContext.java diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/DirectoryHistoryDialog.java b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/DirectoryHistoryDialog.java index f8b66fc6ad78..6c737c2c781a 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/DirectoryHistoryDialog.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/DirectoryHistoryDialog.java @@ -21,14 +21,13 @@ import com.intellij.history.core.revisions.Difference; import com.intellij.history.integration.IdeaGateway; import com.intellij.history.integration.ui.models.DirectoryHistoryDialogModel; import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.diff.DiffManager; -import com.intellij.openapi.diff.DiffRequest; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.actions.ShowDiffAction; +import com.intellij.openapi.vcs.changes.actions.ShowDiffUIContext; import com.intellij.openapi.vcs.changes.ui.ChangeNodeDecorator; import com.intellij.openapi.vcs.changes.ui.ChangesBrowserNode; import com.intellij.openapi.vcs.changes.ui.ChangesTreeList; @@ -38,7 +37,6 @@ import com.intellij.ui.DocumentAdapter; import com.intellij.ui.ExcludingTraversalPolicy; import com.intellij.ui.SearchTextField; import com.intellij.ui.SearchTextFieldWithStoredHistory; -import com.intellij.ui.treeStructure.actions.CollapseAllAction; import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; @@ -210,7 +208,7 @@ public class DirectoryHistoryDialog extends HistoryDialog iterFileChanges() { diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffNavigationContext.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffNavigationContext.java new file mode 100644 index 000000000000..3d306aad9573 --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffNavigationContext.java @@ -0,0 +1,34 @@ +/* + * 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 com.intellij.openapi.diff; + +public class DiffNavigationContext { + private final String myTargetString; + private final Iterable myPreviousLinesIterable; + + public DiffNavigationContext(Iterable previousLinesIterable, String targetString) { + myPreviousLinesIterable = previousLinesIterable; + myTargetString = targetString; + } + + public Iterable getPreviousLinesIterable() { + return myPreviousLinesIterable; + } + + public String getTargetString() { + return myTargetString; + } +} diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffTool.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffTool.java index 00458e7b73cc..3a39af9d98f0 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DiffTool.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffTool.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.diff; +import com.intellij.openapi.actionSystem.DataKey; import org.jetbrains.annotations.NonNls; @@ -41,6 +42,8 @@ public interface DiffTool { @NonNls Object HINT_ALLOW_NO_DIFFERENCES = "allowNoDifferences"; + @NonNls DataKey SCROLL_TO_LINE = DataKey.create("scrollToLine"); + /** * Opens window to compare contents. Clients should call {@link #canShow(com.intellij.openapi.diff.DiffRequest)} first. */ diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java index c291de734e3c..097af6a2c19c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java @@ -19,18 +19,21 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.*; import com.intellij.openapi.diff.actions.MergeActionGroup; import com.intellij.openapi.diff.ex.DiffPanelEx; import com.intellij.openapi.diff.ex.DiffPanelOptions; import com.intellij.openapi.diff.impl.external.DiffManagerImpl; +import com.intellij.openapi.diff.impl.fragments.Fragment; import com.intellij.openapi.diff.impl.fragments.FragmentList; import com.intellij.openapi.diff.impl.highlighting.DiffPanelState; import com.intellij.openapi.diff.impl.highlighting.FragmentSide; import com.intellij.openapi.diff.impl.splitter.DiffDividerPaint; import com.intellij.openapi.diff.impl.splitter.LineBlocks; import com.intellij.openapi.diff.impl.util.*; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollingModel; import com.intellij.openapi.editor.event.VisibleAreaListener; @@ -41,15 +44,20 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.PopupHandler; +import com.intellij.util.containers.CacheOneStepIterator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.security.InvalidParameterException; +import java.util.Iterator; +import java.util.LinkedList; public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSidesContainer { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.DiffPanelImpl"); @@ -328,6 +336,7 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid } final JComponent newBottomComponent = data.getBottomComponent(); myPanel.setBottomComponent(newBottomComponent); + myPanel.requestScrollEditors(); } private static void setWindowTitle(Window window, String title) { @@ -360,11 +369,137 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid public void scrollEditors() { getOptions().onNewContent(myCurrentSide); + final DiffNavigationContext scrollContext = (DiffNavigationContext) myDiffRequest.getGenericData().get(DiffTool.SCROLL_TO_LINE.getName()); + if (scrollContext == null) { + scrollCurrentToFirstDiff(); + } else { + final Document document = myRightSide.getEditor().getDocument(); + + final FragmentList fragmentList = getFragments(); + + final ChangedLinesIterator changedLinesIterator = new ChangedLinesIterator(fragmentList.iterator(), document); + final CacheOneStepIterator> cacheOneStepIterator = + new CacheOneStepIterator>(changedLinesIterator); + final NavigationContextChecker checker = new NavigationContextChecker(cacheOneStepIterator, scrollContext); + int line = checker.contextMatchCheck(); + if (line < 0) { + /*final ChangedLinesIterator changedLinesIterator2 = new ChangedLinesIterator(fragmentList.iterator(), document); + final CacheOneStepIterator> cacheOneStepIterator2 = + new CacheOneStepIterator>(changedLinesIterator2); + final NavigationContextChecker checker2 = new NavigationContextChecker(cacheOneStepIterator2, + new DiffNavigationContext(Collections.emptyList(), scrollContext.getTargetString())); + line = checker2.contextMatchCheck(); + if (line >= 0) { + myRightSide.scrollToFirstDiff(line); + } else {*/ + scrollCurrentToFirstDiff(); + //} + } else { + myRightSide.scrollToFirstDiff(line); + } + } + } + + private void scrollCurrentToFirstDiff() { int[] fragments = getFragmentBeginnings(); if (fragments.length > 0) myCurrentSide.scrollToFirstDiff(fragments[0]); } } + private static class ChangedLinesIterator implements Iterator> { + private final Document myDocument; + private final Iterator myFragmentsIterator; + private java.util.List> myBuffer; + + private ChangedLinesIterator(Iterator fragmentsIterator, Document document) { + myFragmentsIterator = fragmentsIterator; + myDocument = document; + myBuffer = new LinkedList>(); + } + + @Override + public boolean hasNext() { + return (! myBuffer.isEmpty()) || myFragmentsIterator.hasNext(); + } + + @Override + public Pair next() { + if (! myBuffer.isEmpty()) { + return myBuffer.remove(0); + } + + Fragment fragment = null; + while (myFragmentsIterator.hasNext()) { + fragment = myFragmentsIterator.next(); + final TextDiffTypeEnum type = fragment.getType(); + if ((type == null) || TextDiffTypeEnum.DELETED.equals(type) || TextDiffTypeEnum.NONE.equals(type)) continue; + break; + } + if (fragment == null) return null; + + final TextRange textRange = fragment.getRange(FragmentSide.SIDE2); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + final int startLine = myDocument.getLineNumber(textRange.getStartOffset()); + final int endLine = myDocument.getLineNumber(textRange.getEndOffset()); + for (int i = startLine; i <= endLine; i++) { + String text = myDocument.getText().substring(myDocument.getLineStartOffset(i), myDocument.getLineEndOffset(i)); + //text = text.endsWith("\r\n") ? text.substring(0, text.length() - 2) : text.substring(0, text.length() - 1); + myBuffer.add(new Pair(i, text)); + } + } + }); + if (myBuffer.isEmpty()) return null; + return myBuffer.remove(0); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + private static class NavigationContextChecker { + private final Iterator> myChangedLinesIterator; + private final DiffNavigationContext myContext; + + private NavigationContextChecker(Iterator> changedLinesIterator, DiffNavigationContext context) { + myChangedLinesIterator = changedLinesIterator; + myContext = context; + } + + public int contextMatchCheck() { + final Iterable contextLines = myContext.getPreviousLinesIterable(); + + final Iterator iterator = contextLines.iterator(); + if (iterator.hasNext()) { + String contextLine = iterator.next(); + + while (myChangedLinesIterator.hasNext()) { + final Pair pair = myChangedLinesIterator.next(); + if (pair.getSecond().equals(contextLine)) { + if (! iterator.hasNext()) break; + contextLine = iterator.next(); + } + } + if (iterator.hasNext()) { + return -1; + } + } + if (! myChangedLinesIterator.hasNext()) return -1; + + final String targetLine = myContext.getTargetString(); + while (myChangedLinesIterator.hasNext()) { + final Pair pair = myChangedLinesIterator.next(); + if (pair.getSecond().equals(targetLine)) { + return pair.getFirst(); + } + } + return -1; + } + } + private class MyGenericDataProvider extends GenericDataProvider { private final DiffPanelImpl myDiffPanel; diff --git a/platform/util/src/com/intellij/util/containers/CacheOneStepIterator.java b/platform/util/src/com/intellij/util/containers/CacheOneStepIterator.java new file mode 100644 index 000000000000..e6b51aa8ea41 --- /dev/null +++ b/platform/util/src/com/intellij/util/containers/CacheOneStepIterator.java @@ -0,0 +1,54 @@ +/* + * 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 com.intellij.util.containers; + +import java.util.Iterator; + +// only for those who cannot return null +public class CacheOneStepIterator implements Iterator { + private final Iterator myProbableIterator; + private T myPreCalculated; + + public CacheOneStepIterator(final Iterator probableIterator) { + myProbableIterator = probableIterator; + step(); + } + + private void step() { + if (! myProbableIterator.hasNext()) { + myPreCalculated = null; + } else { + myPreCalculated = myProbableIterator.next(); + } + } + + @Override + public boolean hasNext() { + return myPreCalculated != null; + } + + @Override + public T next() { + final T result = myPreCalculated; + step(); + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java index b7b6cff18f3a..dc0fbfa4c360 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java @@ -17,6 +17,7 @@ package com.intellij.openapi.vcs.actions; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.diff.DiffNavigationContext; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.colors.ColorKey; import com.intellij.openapi.editor.colors.EditorFontType; @@ -39,11 +40,13 @@ import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.annotate.*; import com.intellij.openapi.vcs.changes.BackgroundFromStartOption; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.actions.ShowDiffAction; +import com.intellij.openapi.vcs.changes.actions.ShowDiffUIContext; import com.intellij.openapi.vcs.changes.ui.ChangesComparator; import com.intellij.openapi.vcs.changes.ui.ChangesViewBalloonProblemNotifier; import com.intellij.openapi.vcs.history.VcsFileRevision; @@ -55,6 +58,7 @@ import com.intellij.openapi.vcs.impl.VcsBackgroundableActions; import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; +import com.intellij.util.containers.CacheOneStepIterator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -550,7 +554,9 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware { ChangesViewBalloonProblemNotifier.showMe(myVcs.getProject(), "Can not show diff: " + exc[0].getMessage(), MessageType.ERROR); } else if (! changes.isEmpty()) { int idx = findSelfInList(changes); - ShowDiffAction.showDiffForChange(changes.toArray(new Change[changes.size()]), idx, myVcs.getProject()); + final ShowDiffUIContext context = new ShowDiffUIContext(true); + context.setDiffNavigationContext(createDiffNavigationContext(actualNumber)); + ShowDiffAction.showDiffForChange(changes.toArray(new Change[changes.size()]), idx, myVcs.getProject(), context); } } }); @@ -581,5 +587,157 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware { return idx; } + + // for current line number + private DiffNavigationContext createDiffNavigationContext(final int actualLine) { + final MyContentsLines contentsLines = new MyContentsLines(myFileAnnotation.getAnnotatedContent()); + + return new DiffNavigationContext(new Iterable() { + @Override + public Iterator iterator() { + return new CacheOneStepIterator(new ContextLineIterator(contentsLines, myFileAnnotation, actualLine)); + } + }, contentsLines.getLineContents(actualLine)); + } + + private static class MySplittingIterator implements Iterator { + private final String myContents; + // always at the beginning of the _next_ line + private int myOffset; + + private MySplittingIterator(final String contents) { + myContents = contents; + myOffset = 0; + } + + @Override + public boolean hasNext() { + return myOffset < myContents.length(); + } + + @Override + public Integer next() { + final int start = myOffset; + while (myOffset < myContents.length()) { + // \r, \n, or \r\n + final char c = myContents.charAt(myOffset); + if ('\n' == c) { + ++ myOffset; + break; + } else if ('\r' == c) { + if (myOffset + 1 == myContents.length()) { + // at the end + ++ myOffset; + break; + } else { + myOffset += (('\n' == myContents.charAt(myOffset + 1)) ? 2 : 1); + break; + } + } + ++ myOffset; + } + + return start; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + private static class MyContentsLines { + private final MySplittingIterator mySplittingIterator; + private final List myLinesStartOffsets; + private final String myContents; + private boolean myLineEndsFinished; + + private MyContentsLines(final String contents) { + myContents = contents; + mySplittingIterator = new MySplittingIterator(contents); + myLinesStartOffsets = new LinkedList(); + } + + public String getLineContents(final int number) { + assert (! myLineEndsFinished) || (myLineEndsFinished && (myLinesStartOffsets.size() > number)); + + // we need to know end + if (myLineEndsFinished || (myLinesStartOffsets.size() > (number + 1))) { + return extractCalculated(number); + } + while (((myLinesStartOffsets.size() - 1) < (number + 1)) && (! myLineEndsFinished) && mySplittingIterator.hasNext()) { + final Integer nextStart = mySplittingIterator.next(); + myLinesStartOffsets.add(nextStart); + } + myLineEndsFinished = myLinesStartOffsets.size() < (number + 1); + return extractCalculated(number); + } + + private String extractCalculated(int number) { + String text = myContents.substring(myLinesStartOffsets.get(number), + (number > (myLinesStartOffsets.size() - 1)) + ? myContents.length() + : myLinesStartOffsets.get(number + 1)); + text = text.endsWith("\r\n") ? text.substring(0, text.length() - 2) : text.substring(0, text.length() - 1); + return text; + } + + public int getKnownLinesNumber() { + return myLineEndsFinished ? myLinesStartOffsets.size() : -1; + } + } + + /** + * Slightly break the contract: can return null from next() while had claimed hasNext() + */ + private static class ContextLineIterator implements Iterator { + private final MyContentsLines myContentsLines; + + private final VcsRevisionNumber myRevisionNumber; + private final FileAnnotation myAnnotation; + private final int myStopAtLine; + // we assume file has at least one line ;) + private int myCurrentLine; // to start looking for next line with revision from + + private ContextLineIterator(final MyContentsLines contentLines, final FileAnnotation annotation, final int stopAtLine) { + myAnnotation = annotation; + myRevisionNumber = myAnnotation.originalRevision(stopAtLine); + myStopAtLine = stopAtLine; + myContentsLines = contentLines; + } + + @Override + public boolean hasNext() { + return lineNumberInBounds(); + } + + private boolean lineNumberInBounds() { + final int knownLinesNumber = myContentsLines.getKnownLinesNumber(); + return ((knownLinesNumber == -1) || (myCurrentLine < knownLinesNumber)) && (myCurrentLine < myStopAtLine); + } + + @Override + public String next() { + int nextLine = -1; + while (lineNumberInBounds()) { + final VcsRevisionNumber vcsRevisionNumber = myAnnotation.originalRevision(myCurrentLine); + if (myRevisionNumber.equals(vcsRevisionNumber)) { + nextLine = myCurrentLine; + final String text = myContentsLines.getLineContents(nextLine); + if (! StringUtil.isEmptyOrSpaces(text)) { + ++ myCurrentLine; + return text; + } + } + ++ myCurrentLine; + } + return null; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffAction.java index 0d51f67fa26e..522bb795966f 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffAction.java @@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diff.DiffManager; +import com.intellij.openapi.diff.DiffNavigationContext; import com.intellij.openapi.diff.DiffRequest; import com.intellij.openapi.diff.DiffTool; import com.intellij.openapi.fileTypes.FileType; @@ -32,7 +33,6 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.*; -import com.intellij.util.NotNullFunction; import com.intellij.util.containers.Convertor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -123,7 +123,7 @@ public class ShowDiffAction extends AnAction implements DumbAware { } public static void showDiffForChange(final Change[] changes, final int index, final Project project) { - showDiffForChange(changes, index, project, DiffExtendUIFactory.NONE, true); + showDiffForChange(changes, index, project, new ShowDiffUIContext(true)); } private boolean checkIfThereAreFakeRevisions(final Project project, final Change[] changes) { @@ -170,7 +170,7 @@ public class ShowDiffAction extends AnAction implements DumbAware { } public static void showDiffForChange(final Iterable changes, final Condition selectionChecker, - final Project project, @NotNull DiffExtendUIFactory actionsFactory, final boolean showFrame) { + final Project project, @NotNull ShowDiffUIContext context) { int cnt = 0; int newIndex = -1; final List changeList = new ArrayList(); @@ -195,38 +195,30 @@ public class ShowDiffAction extends AnAction implements DumbAware { public ChangeDiffRequestPresentable convert(Change o) { return new ChangeDiffRequestPresentable(project, o); } - }), newIndex, actionsFactory, showFrame); + }), newIndex, context); } - public static void showDiffForChange(Change[] changes, int index, final Project project, @NotNull DiffExtendUIFactory actionsFactory, - final boolean showFrame) { - Change selectedChange = changes [index]; - final List changeList = filterDirectoryAndBinaryChanges(changes); - if (changeList.isEmpty()) { - return; - } - index = 0; - for (int i = 0; i < changeList.size(); i++) { - if (changeList.get(i) == selectedChange) { - index = i; - break; + public static void showDiffForChange(final Change[] changes, int index, final Project project, @NotNull ShowDiffUIContext context) { + final Change selected = index >= 0 ? changes[index] : null; + showDiffForChange(Arrays.asList(changes), new Condition() { + @Override + public boolean value(final Change change) { + return selected == null ? false : selected.equals(change); } - } - showDiffImpl(project, ObjectsConvertor.convert(changeList, - new Convertor() { - public ChangeDiffRequestPresentable convert(Change o) { - return new ChangeDiffRequestPresentable(project, o); - } - }), index, actionsFactory, showFrame); + }, project, context); } - public static void showDiffImpl(final Project project, List changeList, int index, DiffExtendUIFactory actionsFactory, boolean showFrame) { - final ChangeDiffRequest request = new ChangeDiffRequest(project, changeList, actionsFactory, showFrame); - + public static void showDiffImpl(final Project project, List changeList, int index, @NotNull final ShowDiffUIContext context) { + final ChangeDiffRequest request = new ChangeDiffRequest(project, changeList, context.getActionsFactory(), context.isShowFrame()); final DiffTool tool = DiffManager.getInstance().getDiffTool(); if (! request.quickCheckHaveStuff()) return; final DiffRequest simpleRequest = request.init(index); + if (simpleRequest != null) { + final DiffNavigationContext navigationContext = context.getDiffNavigationContext(); + if (navigationContext != null) { + simpleRequest.passForDataContext(DiffTool.SCROLL_TO_LINE, navigationContext); + } tool.show(simpleRequest); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffUIContext.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffUIContext.java new file mode 100644 index 000000000000..1809c650db5e --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffUIContext.java @@ -0,0 +1,58 @@ +/* + * 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 com.intellij.openapi.vcs.changes.actions; + +import com.intellij.openapi.diff.DiffNavigationContext; +import org.jetbrains.annotations.NotNull; + +public class ShowDiffUIContext { + private ShowDiffAction.DiffExtendUIFactory myActionsFactory; + private boolean myShowFrame; + private DiffNavigationContext myDiffNavigationContext; + + public ShowDiffUIContext() { + myActionsFactory = ShowDiffAction.DiffExtendUIFactory.NONE; + } + + public ShowDiffUIContext(boolean showFrame) { + myShowFrame = showFrame; + myActionsFactory = ShowDiffAction.DiffExtendUIFactory.NONE; + } + + public ShowDiffAction.DiffExtendUIFactory getActionsFactory() { + return myActionsFactory; + } + + public void setActionsFactory(@NotNull ShowDiffAction.DiffExtendUIFactory actionsFactory) { + this.myActionsFactory = actionsFactory; + } + + public DiffNavigationContext getDiffNavigationContext() { + return myDiffNavigationContext; + } + + public void setDiffNavigationContext(DiffNavigationContext diffNavigationContext) { + myDiffNavigationContext = diffNavigationContext; + } + + public boolean isShowFrame() { + return myShowFrame; + } + + public void setShowFrame(boolean showFrame) { + this.myShowFrame = showFrame; + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java index a4b70f637325..7e351534066e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java @@ -41,6 +41,7 @@ import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.LocalChangeList; import com.intellij.openapi.vcs.changes.actions.DiffRequestPresentable; import com.intellij.openapi.vcs.changes.actions.ShowDiffAction; +import com.intellij.openapi.vcs.changes.actions.ShowDiffUIContext; import com.intellij.openapi.vcs.changes.ui.*; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; @@ -851,7 +852,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } } if (diffRequestPresentables.isEmpty()) return; - ShowDiffAction.showDiffImpl(myProject, diffRequestPresentables, selectedIdx, ShowDiffAction.DiffExtendUIFactory.NONE, false); + ShowDiffAction.showDiffImpl(myProject, diffRequestPresentables, selectedIdx, new ShowDiffUIContext(false)); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/DiffShelvedChangesAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/DiffShelvedChangesAction.java index 33fb014f80fc..cd198408e961 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/DiffShelvedChangesAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/DiffShelvedChangesAction.java @@ -29,10 +29,7 @@ import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ContentRevision; -import com.intellij.openapi.vcs.changes.actions.ChangeDiffRequestPresentable; -import com.intellij.openapi.vcs.changes.actions.DiffRequestPresentable; -import com.intellij.openapi.vcs.changes.actions.DiffRequestPresentableProxy; -import com.intellij.openapi.vcs.changes.actions.ShowDiffAction; +import com.intellij.openapi.vcs.changes.actions.*; import com.intellij.openapi.vcs.changes.patch.ApplyPatchForBaseRevisionTexts; import com.intellij.openapi.vcs.changes.patch.MergedDiffRequestPresentable; import com.intellij.openapi.vcs.changes.patch.PatchMergeRequestFactory; @@ -122,7 +119,7 @@ public class DiffShelvedChangesAction extends AnAction implements DumbAware { ChangesViewBalloonProblemNotifier.showMe(project, "Show Diff: Cannot find base for: " + StringUtil.join(missing, ",\n"), MessageType.WARNING); } - ShowDiffAction.showDiffImpl(project, diffRequestPresentables, toSelectIdx, ShowDiffAction.DiffExtendUIFactory.NONE, false); + ShowDiffAction.showDiffImpl(project, diffRequestPresentables, toSelectIdx, new ShowDiffUIContext(false)); } private static class PatchesPreloader { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowser.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowser.java index 75195cc7ae41..e13c6d895e37 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowser.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowser.java @@ -24,6 +24,7 @@ import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vcs.changes.actions.ShowDiffAction; +import com.intellij.openapi.vcs.changes.actions.ShowDiffUIContext; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.Nullable; @@ -197,7 +198,9 @@ public class ChangesBrowser extends JPanel implements TypeSafeDataProvider { } protected void showDiffForChanges(Change[] changesArray, final int indexInSelection) { - ShowDiffAction.showDiffForChange(changesArray, indexInSelection, myProject, myDiffExtendUIFactory, isInFrame()); + final ShowDiffUIContext context = new ShowDiffUIContext(isInFrame()); + context.setActionsFactory(myDiffExtendUIFactory); + ShowDiffAction.showDiffForChange(changesArray, indexInSelection, myProject, context); } private void showDiff() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/ShowUpdatedDiffAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/ShowUpdatedDiffAction.java index db31cfb2b5f1..e176fe800847 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/ShowUpdatedDiffAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/ShowUpdatedDiffAction.java @@ -19,8 +19,8 @@ import com.intellij.history.ByteContent; import com.intellij.history.Label; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.fileEditor.impl.LoadTextUtil; -import com.intellij.openapi.project.Project; import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.io.FileUtil; @@ -28,11 +28,11 @@ import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ContentRevision; import com.intellij.openapi.vcs.changes.actions.ShowDiffAction; +import com.intellij.openapi.vcs.changes.actions.ShowDiffUIContext; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.encoding.EncodingManager; import com.intellij.openapi.vfs.pointers.VirtualFilePointer; -import com.intellij.util.NotNullFunction; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -91,7 +91,7 @@ public class ShowUpdatedDiffAction extends AnAction implements DumbAware { final String selectedUrl = VcsDataKeys.UPDATE_VIEW_SELECTED_PATH.getData(dc); ShowDiffAction.showDiffForChange(new MyIterableWrapper(iterable.iterator(), before, after), new MySelectionMarker(selectedUrl), - project, ShowDiffAction.DiffExtendUIFactory.NONE, true); + project, new ShowDiffUIContext(true)); } private static class MySelectionMarker implements Condition { From 08a4c9e4b38a1dd8b3c6f8ebb590849c3b435f07 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Wed, 11 Aug 2010 14:28:26 +0400 Subject: [PATCH 16/36] IDEA-50353 Wrong invalid method arguments warning in case of overloaded method --- .../processors/MethodResolverProcessor.java | 17 ++++++++++++++++- .../groovy/lang/GppFunctionalTest.groovy | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java index 302737d3fc76..a76c4821db80 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java @@ -23,6 +23,7 @@ import com.intellij.psi.scope.JavaScopeProcessorEvent; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.containers.hash.HashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; @@ -225,11 +226,25 @@ public class MethodResolverProcessor extends ResolverProcessor { return filterCandidates(); } if (!myInapplicableCandidates.isEmpty()) { - return ResolveUtil.filterSameSignatureCandidates(myInapplicableCandidates, myArgumentTypes != null ? myArgumentTypes.length : -1); + final Set resultSet = filterCorrectParameterCount(myInapplicableCandidates); + return ResolveUtil.filterSameSignatureCandidates(resultSet, myArgumentTypes != null ? myArgumentTypes.length : -1); } return GroovyResolveResult.EMPTY_ARRAY; } + private Set filterCorrectParameterCount(Set candidates) { + if (myArgumentTypes == null) return candidates; + Set result = new HashSet(); + for (GroovyResolveResult candidate : candidates) { + final PsiElement element = candidate.getElement(); + if (element instanceof PsiMethod && ((PsiMethod)element).getParameterList().getParametersCount() == myArgumentTypes.length) { + result.add(candidate); + } + } + if (result.size() > 0) return result; + return candidates; + } + private GroovyResolveResult[] filterCandidates() { GroovyResolveResult[] array = myCandidates.toArray(new GroovyResolveResult[myCandidates.size()]); if (array.length == 1) return array; diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy index be7676560517..d8038e4f1e06 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy @@ -404,7 +404,7 @@ class Point { assertEquals point.constructors[0], resolveReference() configureGppScript "Point p = ['super': 'a']" - assertEquals 2, multiResolveReference().size() + assertEquals 1, multiResolveReference().size() } public void testGotoSuperConstructorFromLiteralOnsets() throws Exception { From bd81a6067aaafb5b317eb6d75ef117a653aa313b Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 11 Aug 2010 14:57:06 +0400 Subject: [PATCH 17/36] cleanup --- .../com/intellij/psi/impl/source/PsiFileImpl.java | 14 ++++++++------ .../html/HtmlConditionalCommentInjector.java | 8 ++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java index c78054c1ec27..c9e38e57e05e 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java @@ -389,13 +389,15 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF @SuppressWarnings({"CloneDoesntDeclareCloneNotSupportedException", "CloneDoesntCallSuperClone"}) protected PsiFileImpl clone() { - FileViewProvider provider = getViewProvider().clone(); + FileViewProvider viewProvider = getViewProvider(); + FileViewProvider providerCopy = viewProvider.clone(); final Language language = getLanguage(); - if (provider == null) { - throw new AssertionError("Unable to clone the view provider: " + getViewProvider() + "; " + language); + if (providerCopy == null) { + throw new AssertionError("Unable to clone the view provider: " + viewProvider + "; " + language); } - PsiFileImpl clone = (PsiFileImpl)provider.getPsi(language); - assert clone != null:"Cannot find psi file with language:"+language + " from viewprovider:"+provider+" virtual file:"+getVirtualFile(); + PsiFileImpl clone = (PsiFileImpl)providerCopy.getPsi(language); + assert clone != null : "Cannot find psi file with language:" + language + " from viewprovider:" + + providerCopy + " virtual file:" + getVirtualFile(); copyCopyableDataTo(clone); @@ -406,7 +408,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF treeClone.setPsi(clone); } - if (getViewProvider().isEventSystemEnabled()) { + if (viewProvider.isEventSystemEnabled()) { clone.myOriginalFile = this; } else if (myOriginalFile != null) { diff --git a/xml/impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java b/xml/impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java index 91cc8c55c7ce..270baad289b8 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java +++ b/xml/impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java @@ -16,6 +16,7 @@ package com.intellij.psi.impl.source.html; import com.intellij.lang.ASTNode; +import com.intellij.lang.Language; import com.intellij.lang.injection.MultiHostInjector; import com.intellij.lang.injection.MultiHostRegistrar; import com.intellij.openapi.util.TextRange; @@ -46,10 +47,9 @@ public class HtmlConditionalCommentInjector implements MultiHostInjector { if (endOfEnd != null) { final TextRange textRange = host.getTextRange(); final int startOffset = textRange.getStartOffset(); - registrar.startInjecting(host.getParent().getLanguage()).addPlace(null, null, (PsiLanguageInjectionHost)host, - new TextRange( - conditionalStart.getTextRange().getEndOffset() - startOffset, - conditionalEnd.getStartOffset() - startOffset)).doneInjecting(); + Language language = host.getParent().getLanguage(); + TextRange range = new TextRange(conditionalStart.getTextRange().getEndOffset() - startOffset, conditionalEnd.getStartOffset() - startOffset); + registrar.startInjecting(language).addPlace(null, null, (PsiLanguageInjectionHost)host, range).doneInjecting(); } } } From b9fb70aec2cbfbb907cdd6df82b601e631dc1de6 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 11 Aug 2010 15:07:26 +0400 Subject: [PATCH 18/36] Maven: exception when adding modules from UI (IDEA-54927, IDEA-53197) --- .../ui/configuration/ModulesConfigurator.java | 58 +++++++++---------- ...factsStructureConfigurableContextImpl.java | 2 +- .../MavenUIModifiableModelsProvider.java | 2 +- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java index 17c7ddc6cc91..058d8b732a6d 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java @@ -151,42 +151,19 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change } public ModuleRootModel getRootModel(@NotNull Module module) { - return getEditor(module).getRootModel(); + return getOrCreateModuleEditor(module).getRootModel(); } - public ModuleEditor getEditor(Module module) { + public ModuleEditor getOrCreateModuleEditor(Module module) { LOG.assertTrue(getModule(module.getName()) != null, "Module has been deleted"); ModuleEditor editor = getModuleEditor(module); if (editor == null) { - editor = createModuleEditor(module); + editor = doCreateModuleEditor(module); } return editor; } - public FacetModel getFacetModel(@NotNull Module module) { - return myFacetsConfigurator.getOrCreateModifiableModel(module); - } - - public void resetModuleEditors() { - myModuleModel = ModuleManager.getInstance(myProject).getModifiableModel(); - - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - assert myModuleEditors.isEmpty(); - final Module[] modules = myModuleModel.getModules(); - if (modules.length > 0) { - for (Module module : modules) { - createModuleEditor(module); - } - Collections.sort(myModuleEditors, myModuleEditorComparator); - } - } - }); - myFacetsConfigurator.resetEditors(); - myModified = false; - } - - public ModuleEditor createModuleEditor(final Module module) { + private ModuleEditor doCreateModuleEditor(final Module module) { final ModuleEditor moduleEditor = new ModuleEditor(myProject, this, module) { @Override public ProjectFacetsConfigurator getFacetsConfigurator() { @@ -208,6 +185,29 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change return moduleEditor; } + public FacetModel getFacetModel(@NotNull Module module) { + return myFacetsConfigurator.getOrCreateModifiableModel(module); + } + + public void resetModuleEditors() { + myModuleModel = ModuleManager.getInstance(myProject).getModifiableModel(); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + assert myModuleEditors.isEmpty(); + final Module[] modules = myModuleModel.getModules(); + if (modules.length > 0) { + for (Module module : modules) { + getOrCreateModuleEditor(module); + } + Collections.sort(myModuleEditors, myModuleEditorComparator); + } + } + }); + myFacetsConfigurator.resetEditors(); + myModified = false; + } + public void moduleStateChanged(final ModifiableRootModel moduleRootModel) { myProjectConfigurable.updateCircularDependencyWarning(); for (ModuleEditor.ChangeListener listener : myAllModulesChangeListeners) { @@ -368,7 +368,7 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { for (Module module : modules) { - createModuleEditor(module); + getOrCreateModuleEditor(module); } } }); @@ -404,7 +404,7 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change if (module != null) { ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { - createModuleEditor(module); + getOrCreateModuleEditor(module); Collections.sort(myModuleEditors, myModuleEditorComparator); } }); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurableContextImpl.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurableContextImpl.java index 06dc0a84390c..a241432298ba 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurableContextImpl.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurableContextImpl.java @@ -252,7 +252,7 @@ public class ArtifactsStructureConfigurableContextImpl implements ArtifactsStruc } public ModifiableRootModel getOrCreateModifiableRootModel(Module module) { - final ModuleEditor editor = myContext.getModulesConfigurator().getEditor(module); + final ModuleEditor editor = myContext.getModulesConfigurator().getOrCreateModuleEditor(module); return editor.getModifiableRootModelProxy(); } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenUIModifiableModelsProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenUIModifiableModelsProvider.java index d152f72a39ec..c88ae4457b7d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenUIModifiableModelsProvider.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenUIModifiableModelsProvider.java @@ -59,7 +59,7 @@ public class MavenUIModifiableModelsProvider extends MavenBaseModifiableModelsPr @Override protected ModifiableRootModel doGetRootModel(Module module) { - return myModulesConfigurator.getEditor(module).getModifiableRootModel(); + return myModulesConfigurator.getOrCreateModuleEditor(module).getModifiableRootModel(); } @Override From 35fa4b10b489f50171d6916fac64d2f9321a336c Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Wed, 11 Aug 2010 15:06:57 +0400 Subject: [PATCH 19/36] IDEA-56405 Soft wrap, editing: typing on line split border replaces wrap sign with line feed; AssertionError at SoftWrapModelImpl.beforeDocumentChangeAtCaret() 1. Corrected soft wraps processing on document change; 2. Implemented soft wraps resources releasing on editor disposing; 3. Corrected 'active row' background painting algorithm for soft-wrapped lines; 4. Changed default 'soft wrap arrows' to another unicode symbols (they are supposed to correctly represented by Windows 7 fonts); --- .../injected/editor/CaretModelWindow.java | 9 +- .../intellij/openapi/editor/CaretModel.java | 15 ++- .../editor/EditorModificationUtil.java | 4 +- .../editor/actions/BackspaceAction.java | 2 +- .../openapi/editor/actions/DeleteAction.java | 1 + .../openapi/editor/impl/CaretModelImpl.java | 30 ++++- .../openapi/editor/impl/EditorImpl.java | 118 ++++++++++------- .../editor/impl/EditorMarkupModelImpl.java | 4 +- .../editor/impl/SoftWrapModelImpl.java | 44 +++++-- .../softwrap/CompositeSoftWrapPainter.java | 4 +- .../DefaultSoftWrapApplianceManager.java | 30 ++--- .../SoftWrapDocumentChangeManager.java | 119 +++++++++--------- .../editor/impl/softwrap/SoftWrapHelper.java | 91 ++++++++++++++ .../editor/impl/softwrap/TextChangeImpl.java | 3 +- .../textarea/TextComponentCaretModel.java | 9 +- 15 files changed, 332 insertions(+), 151 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapHelper.java diff --git a/platform/lang-impl/src/com/intellij/injected/editor/CaretModelWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/CaretModelWindow.java index 7e11bf4e3554..0ca9958af275 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/CaretModelWindow.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/CaretModelWindow.java @@ -56,9 +56,14 @@ public class CaretModelWindow implements CaretModel { myDelegate.moveToLogicalPosition(hostPos); } - public void moveToOffset(final int offset) { + @Override + public void moveToOffset(int offset) { + moveToOffset(offset, false); + } + + public void moveToOffset(final int offset, boolean locateBeforeSoftWrap) { int hostOffset = myEditorWindow.getDocument().injectedToHost(offset); - myDelegate.moveToOffset(hostOffset); + myDelegate.moveToOffset(hostOffset, locateBeforeSoftWrap); } public LogicalPosition getLogicalPosition() { diff --git a/platform/platform-api/src/com/intellij/openapi/editor/CaretModel.java b/platform/platform-api/src/com/intellij/openapi/editor/CaretModel.java index 0b56a2bad9ff..84c5ad3c2ca3 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/CaretModel.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/CaretModel.java @@ -55,12 +55,23 @@ public interface CaretModel { void moveToVisualPosition(VisualPosition pos); /** - * Moves the caret to the specified offset in the document. + * Short hand for calling {@link #moveToOffset(int, boolean)} with 'false' as a second argument. * - * @param offset the offset to move to. + * @param offset the offset to move to */ void moveToOffset(int offset); + /** + * Moves the caret to the specified offset in the document. + * + * @param offset the offset to move to. + * @param locateBeforeSoftWrap there is a possible case that there is a soft wrap at the given offset, hence, the same offset + * corresponds to two different visual positions - just before soft wrap and just after soft wrap. + * We may want to clearly indicate where to put the caret then. Given parameter allows to do that. + * Note: it's ignored if there is no soft wrap at the given offset + */ + void moveToOffset(int offset, boolean locateBeforeSoftWrap); + /** * Returns the logical position of the caret. * diff --git a/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java b/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java index 1371104f5af3..13279c0295c9 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java @@ -81,7 +81,7 @@ public class EditorModificationUtil { public static int insertStringAtCaret(Editor editor, String s, boolean toProcessOverwriteMode, boolean toMoveCaret) { final SelectionModel selectionModel = editor.getSelectionModel(); if (selectionModel.hasSelection()) { - editor.getCaretModel().moveToOffset(selectionModel.getSelectionStart()); + editor.getCaretModel().moveToOffset(selectionModel.getSelectionStart(), true); } // There is a possible case that particular soft wraps become hard wraps if the caret is located at soft wrap-introduced virtual @@ -114,7 +114,7 @@ public class EditorModificationUtil { int offset = oldOffset + s.length(); if (toMoveCaret){ - editor.getCaretModel().moveToOffset(offset); + editor.getCaretModel().moveToOffset(offset, true); editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); selectionModel.removeSelection(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java index 24327465e86e..86b8b771ee11 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java @@ -81,10 +81,10 @@ public class BackspaceAction extends EditorAction { } else { int offset = editor.getCaretModel().getOffset(); - editor.getCaretModel().moveToOffset(offset-1); editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); editor.getSelectionModel().removeSelection(); document.deleteString(offset-1, offset); + editor.getCaretModel().moveToOffset(offset - 1, true); } } else if(lineNumber > 0) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteAction.java index af8466bd9231..6bfb0a282bed 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteAction.java @@ -97,6 +97,7 @@ public class DeleteAction extends EditorAction { if(afterLineEnd < 0) { int offset = editor.getCaretModel().getOffset(); document.deleteString(offset, offset + 1); + editor.getCaretModel().moveToOffset(offset); return; } if(lineNumber + 1 >= document.getLineCount()) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java index 2dc7161ef06e..503ff6715dfd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java @@ -35,6 +35,7 @@ import com.intellij.openapi.editor.ex.EditorGutterComponentEx; import com.intellij.openapi.editor.ex.PrioritizedDocumentListener; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.editor.impl.event.DocumentEventImpl; +import com.intellij.openapi.editor.impl.softwrap.SoftWrapHelper; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; @@ -133,9 +134,13 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener { } public void moveToOffset(int offset) { + moveToOffset(offset, false); + } + + public void moveToOffset(int offset, boolean locateBeforeSoftWrap) { assertIsDispatchThread(); validateCallContext(); - moveToLogicalPosition(myEditor.offsetToLogicalPosition(offset)); + moveToLogicalPosition(myEditor.offsetToLogicalPosition(offset), locateBeforeSoftWrap); if (!myEditor.offsetToLogicalPosition(myOffset).equals(myEditor.offsetToLogicalPosition(offset))) { LOG.error("caret moved to wrong offset. Requested:" + offset + " but actual:" + myOffset); } @@ -244,6 +249,10 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener { } public void moveToLogicalPosition(LogicalPosition pos) { + moveToLogicalPosition(pos, false); + } + + private void moveToLogicalPosition(LogicalPosition pos, boolean locateBeforeSoftWrap) { assertIsDispatchThread(); validateCallContext(); int column = pos.column; @@ -325,6 +334,14 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener { myEditor.updateCaretCursor(); requestRepaint(oldInfo); + if (locateBeforeSoftWrap && SoftWrapHelper.isCaretAfterSoftWrap(myEditor)) { + int lineToUse = myVisibleCaret.line - 1; + if (lineToUse >= 0) { + moveToVisualPosition(new VisualPosition(lineToUse, EditorUtil.getLastVisualLineColumnNumber(myEditor, lineToUse))); + return; + } + } + if (!oldCaretPosition.toVisualPosition().equals(myLogicalCaret.toVisualPosition())) { CaretEvent event = new CaretEvent(myEditor, oldCaretPosition, myLogicalCaret); for (CaretListener listener : myCaretListeners) { @@ -408,15 +425,19 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener { DocumentEventImpl event = (DocumentEventImpl)e; final Document document = myEditor.getDocument(); + boolean performSoftWrapAdjustment = e.getNewLength() > 0 // We want to put caret just after the last added symbol + // There is a possible case that the user removes text just before the soft wrap. We want to keep caret + // on a visual line with soft wrap start then. + || myEditor.getSoftWrapModel().getSoftWrap(e.getOffset()) != null; if (event.isWholeTextReplaced()) { int newLength = document.getTextLength(); if (myOffset == newLength - e.getNewLength() + e.getOldLength() || newLength == 0) { - moveToOffset(newLength); + moveToOffset(newLength, performSoftWrapAdjustment); } else { final int line = event.translateLineViaDiff(myLogicalCaret.line); - moveToLogicalPosition(new LogicalPosition(line, myLogicalCaret.column)); + moveToLogicalPosition(new LogicalPosition(line, myLogicalCaret.column), performSoftWrapAdjustment); } } else { @@ -435,9 +456,8 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener { newOffset = Math.min(newOffset, document.getTextLength()); - //TODO:ask max about this code // if (newOffset != myOffset) { - moveToOffset(newOffset); + moveToOffset(newOffset, performSoftWrapAdjustment); //} //else { // moveToVisualPosition(oldPosition); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 90778c6723a0..1e07bbfe6381 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -50,6 +50,7 @@ import com.intellij.openapi.editor.highlighter.HighlighterClient; import com.intellij.openapi.editor.impl.event.MarkupModelEvent; import com.intellij.openapi.editor.impl.event.MarkupModelListener; import com.intellij.openapi.editor.impl.softwrap.SoftWrapDrawingType; +import com.intellij.openapi.editor.impl.softwrap.SoftWrapHelper; import com.intellij.openapi.editor.markup.*; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProgressManager; @@ -294,6 +295,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi myDocument.addDocumentListener(myCaretModel); myDocument.addDocumentListener(mySelectionModel); myDocument.addDocumentListener(myEditorDocumentAdapter); + myDocument.addDocumentListener(mySoftWrapModel); myIndentsModel = new IndentsModelImpl(this); myCaretModel.addCaretListener(new CaretListener() { @@ -522,6 +524,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi myDocument.removeDocumentListener(myFoldingModel); myDocument.removeDocumentListener(myCaretModel); myDocument.removeDocumentListener(mySelectionModel); + myDocument.removeDocumentListener(mySoftWrapModel); MarkupModelEx markupModel = (MarkupModelEx)myDocument.getMarkupModel(myProject, false); if (markupModel instanceof MarkupModelImpl) { @@ -1126,7 +1129,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } // We need to consider 'before soft wrap drawing'. TextChange softWrap = getSoftWrapModel().getSoftWrap(offset); - if (softWrap != null) { + if (softWrap != null && offset > startOffset) { column++; x += getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED); if (column >= length) { @@ -1585,6 +1588,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi @SuppressWarnings({"StatementWithEmptyBody"}) private void paintBackgrounds(Graphics g, Rectangle clip) { + boolean locateBeforeSoftWrap = !SoftWrapHelper.isCaretAfterSoftWrap(this); Color defaultBackground = getBackgroundColor(); g.setColor(defaultBackground); g.fillRect(clip.x, clip.y, clip.width, clip.height); @@ -1702,6 +1706,22 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (lIterator.getLineNumber() >= lastLineIndex && position.y <= clip.y + clip.height) { paintAfterFileEndBackground(iterationState, g, position, clip, lineHeight, defaultBackground); } + + // Perform additional activity if soft wrap is added or removed during repainting. + if (mySoftWrapsChanged) { + mySoftWrapsChanged = false; + validateSize(); + + // Repaint editor to the bottom in order to ensure that its content is shown correctly after new soft wrap introduction. + repaintToScreenBottom(xyToLogicalPosition(position).line); + + // Repaint gutter at all space that is located after active clip in order to ensure that line numbers are correctly redrawn + // in accordance with the newly introduced soft wrap(s). + myGutterComponent.repaint(0, clip.y, myGutterComponent.getWidth(), myGutterComponent.getHeight() - clip.y); + + // Ask caret model to update visual caret position. + getCaretModel().moveToOffset(getCaretModel().getOffset(), locateBeforeSoftWrap); + } } private void paintRectangularSelection(Graphics g) { @@ -1756,7 +1776,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (startToUse < softWrapStart) { position.x = drawBackground(g, backColor, text.subSequence(startToUse, softWrapStart), position, fontType, defaultBackground, clip); } - drawSoftWrap(g, backColor, softWrap, position, fontType, defaultBackground, clip); + drawSoftWrap(g, softWrap, position, fontType, defaultBackground, clip); startToUse = softWrapStart; } @@ -1766,37 +1786,61 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi return position.x; } - private void drawSoftWrap(Graphics g, Color backColor, TextChange softWrap, Point position, - int fontType, Color defaultBackground, Rectangle clip) - { - position.x = drawBackground( - g, backColor, getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED), position, - defaultBackground, clip - ); + private void drawSoftWrap(Graphics g, TextChange softWrap, Point position, int fontType, Color defaultBackground, Rectangle clip) { + // The main idea is to to do the following: + // *) update given drawing position coordinates in accordance with the current soft wrap; + // *) draw 'active line' background at soft wrap-introduced virtual space if necessary; CharSequence softWrapText = softWrap.getText(); - int start = 0; - for ( - int end = CharArrayUtil.shiftForwardUntil(softWrapText, start, "\n"); - start < softWrapText.length() && end < softWrapText.length(); - end = CharArrayUtil.shiftForwardUntil(softWrapText, start, "\n")) - { - drawBackground(g, backColor, softWrapText.subSequence(start, end), position, fontType, defaultBackground, clip); - start = end + 1; - position.x = 0; - position.y += getLineHeight(); + int activeRowY = getCaretModel().getVisualPosition().line * getLineHeight(); + if (position.y == activeRowY) { + // Draw 'active line' background after soft wrap. + Color caretRowColor = getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR); + drawBackground(g, caretRowColor, clip.x + clip.width - position.x, position, defaultBackground, clip); } - if (start < softWrapText.length()) { - position.x = drawBackground( - g, backColor, softWrapText.subSequence(start, softWrapText.length()), position, fontType, defaultBackground, clip - ); + int i = CharArrayUtil.lastIndexOf(softWrapText, "\n", softWrapText.length()) + 1; + position.x = getTextSegmentWidth(softWrapText.subSequence(i, softWrapText.length()), 0, fontType, clip); + position.x += getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP); + position.y += getLineHeight(); + + if (position.y == activeRowY) { + // Draw 'active line' background for the soft wrap-introduced virtual space. + Color caretRowColor = getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR); + drawBackground(g, caretRowColor, position.x, new Point(0, activeRowY), defaultBackground, clip); } - position.x = drawBackground( - g, backColor, getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP), position, - defaultBackground, clip - ); + // The code below draws background for soft wrap-introduced virtual space. It's is considered that we don't want + // to do that for now. Uncomment if that decision is changed. + + //position.x = drawBackground( + // g, backColor, getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED), position, + // defaultBackground, clip + //); + // + //CharSequence softWrapText = softWrap.getText(); + //int start = 0; + //for ( + // int end = CharArrayUtil.shiftForwardUntil(softWrapText, start, "\n"); + // start < softWrapText.length() && end < softWrapText.length(); + // end = CharArrayUtil.shiftForwardUntil(softWrapText, start, "\n")) + //{ + // drawBackground(g, backColor, softWrapText.subSequence(start, end), position, fontType, defaultBackground, clip); + // start = end + 1; + // position.x = 0; + // position.y += getLineHeight(); + //} + // + //if (start < softWrapText.length()) { + // position.x = drawBackground( + // g, backColor, softWrapText.subSequence(start, softWrapText.length()), position, fontType, defaultBackground, clip + // ); + //} + // + //position.x = drawBackground( + // g, backColor, getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP), position, + // defaultBackground, clip + //); } private int drawBackground(Graphics g, Color backColor, CharSequence text, Point position, int fontType, Color defaultBackground, @@ -1861,7 +1905,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi // We use AtomicReference here just as a holder for LogicalPosition // The main idea is that there is a possible case that we need to perform painting starting from soft-wrapped logical line. - // We may want to skip necessary of visual lines then. Hence, we remember logical position that corresponds to the starting + // We may want to skip necessary number of visual lines then. Hence, we remember logical position that corresponds to the starting // visual line in order to use it for further processing. As soon as necessary number of visual lines is skipped, logical // position is expected to be set to null as an indication that no soft wrap-introduced visual lines should be skipped on // current painting iteration. @@ -1975,22 +2019,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } flushCachedChars(g); - - // Perform additional activity if soft wrap is added or removed during repainting. - if (mySoftWrapsChanged) { - mySoftWrapsChanged = false; - validateSize(); - - // Repaint editor to the bottom in order to ensure that its content is shown correctly after new soft wrap introduction. - repaintToScreenBottom(xyToLogicalPosition(position).line); - - // Repaint gutter at all space that is located after active clip in order to ensure that line numbers are correctly redrawn - // in accordance with the newly introduced soft wrap(s). - myGutterComponent.repaint(0, clip.y, myGutterComponent.getWidth(), myGutterComponent.getHeight() - clip.y); - - // Ask caret model to update visual caret position. - getCaretModel().moveToOffset(getCaretModel().getOffset()); - } } private boolean paintSelection() { @@ -3536,7 +3564,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi super(orientation); } - void setPersistendUI(ScrollBarUI ui) { + void setPersistentUI(ScrollBarUI ui) { myPersistentUI = ui; setUI(ui); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java index 405de6210f6f..0bacaf8c4731 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java @@ -463,10 +463,10 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark public void setErrorStripeVisible(boolean val) { if (val) { - myEditor.getVerticalScrollBar().setPersistendUI(new MyErrorPanel()); + myEditor.getVerticalScrollBar().setPersistentUI(new MyErrorPanel()); } else { - myEditor.getVerticalScrollBar().setPersistendUI(ButtonlessScrollBarUI.createNormal()); + myEditor.getVerticalScrollBar().setPersistentUI(ButtonlessScrollBarUI.createNormal()); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index c1283a0b4a02..1c8967076f5f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -16,6 +16,8 @@ package com.intellij.openapi.editor.impl; import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.event.DocumentEvent; +import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.SoftWrapChangeListener; import com.intellij.openapi.editor.ex.SoftWrapModelEx; @@ -27,6 +29,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -41,7 +44,9 @@ import java.util.List; * @author Denis Zhdanov * @since Jun 8, 2010 12:47:32 PM */ -public class SoftWrapModelImpl implements SoftWrapModelEx { +public class SoftWrapModelImpl implements SoftWrapModelEx, DocumentListener { + + private final List myDocumentListeners = new ArrayList(); private final SoftWrapDataMapper myDataMapper; private final SoftWrapsStorage myStorage; @@ -69,6 +74,14 @@ public class SoftWrapModelImpl implements SoftWrapModelEx { ); } + public SoftWrapModelImpl(@NotNull EditorEx editor, @NotNull SoftWrapsStorage storage, @NotNull SoftWrapPainter painter, + @NotNull DefaultSoftWrapApplianceManager applianceManager, @NotNull SoftWrapDataMapper dataMapper, + @NotNull SoftWrapDocumentChangeManager documentChangeManager) + { + this(editor, storage, painter, (SoftWrapApplianceManager)applianceManager, dataMapper, documentChangeManager); + myDocumentListeners.add(applianceManager.getDocumentListener()); + } + public SoftWrapModelImpl(@NotNull EditorEx editor, @NotNull SoftWrapsStorage storage, @NotNull SoftWrapPainter painter, @NotNull SoftWrapApplianceManager applianceManager, @NotNull SoftWrapDataMapper dataMapper, @NotNull SoftWrapDocumentChangeManager documentChangeManager) @@ -79,6 +92,8 @@ public class SoftWrapModelImpl implements SoftWrapModelEx { myApplianceManager = applianceManager; myDataMapper = dataMapper; myDocumentChangeManager = documentChangeManager; + + myDocumentListeners.add(myDocumentChangeManager); } public boolean isSoftWrappingEnabled() { @@ -349,26 +364,35 @@ public class SoftWrapModelImpl implements SoftWrapModelEx { return result; } + @Override public void beforeDocumentChangeAtCaret() { CaretModel caretModel = myEditor.getCaretModel(); VisualPosition visualCaretPosition = caretModel.getVisualPosition(); if (!isInsideSoftWrap(visualCaretPosition)) { return; } - int offset = caretModel.getOffset(); - TextChangeImpl softWrap = myStorage.getSoftWrap(offset); - if (softWrap == null) { - return; + if (myDocumentChangeManager.makeHardWrap(caretModel.getOffset())) { + // Restore caret position. + caretModel.moveToVisualPosition(visualCaretPosition); } - - myDocumentChangeManager.makeHardWrap(softWrap); - - // Restore caret position. - caretModel.moveToVisualPosition(visualCaretPosition); } @Override public boolean addSoftWrapChangeListener(@NotNull SoftWrapChangeListener listener) { return myStorage.addSoftWrapChangeListener(listener); } + + @Override + public void beforeDocumentChange(DocumentEvent event) { + for (DocumentListener listener : myDocumentListeners) { + listener.beforeDocumentChange(event); + } + } + + @Override + public void documentChanged(DocumentEvent event) { + for (DocumentListener listener : myDocumentListeners) { + listener.documentChanged(event); + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/CompositeSoftWrapPainter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/CompositeSoftWrapPainter.java index b5eef3985a10..57d9ba6c69bc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/CompositeSoftWrapPainter.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/CompositeSoftWrapPainter.java @@ -45,10 +45,10 @@ import static java.util.Arrays.asList; public class CompositeSoftWrapPainter implements SoftWrapPainter { private static final List> SYMBOLS = asList( - asMap(asList(BEFORE_SOFT_WRAP_LINE_FEED, AFTER_SOFT_WRAP), - asList('\uE48B', '\uE48C')), asMap(asList(BEFORE_SOFT_WRAP_LINE_FEED, AFTER_SOFT_WRAP), asList('\u2926', '\u2925')), + asMap(asList(BEFORE_SOFT_WRAP_LINE_FEED, AFTER_SOFT_WRAP), + asList('\uE48B', '\uE48C')), asMap(asList(BEFORE_SOFT_WRAP_LINE_FEED, AFTER_SOFT_WRAP), asList('\u21B2', '\u21B3')), asMap(asList(BEFORE_SOFT_WRAP_LINE_FEED, AFTER_SOFT_WRAP), diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManager.java index d3583b094aa7..5ba742fd8b46 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManager.java @@ -18,6 +18,7 @@ package com.intellij.openapi.editor.impl.softwrap; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.VisualPosition; import com.intellij.openapi.editor.actions.EditorActionUtil; +import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; @@ -58,7 +59,6 @@ import java.nio.CharBuffer; */ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager { - /** Enumerates possible type of soft wrap indents to use. */ enum IndentType { /** Don't apply special indent to soft-wrapped line at all. */ @@ -103,6 +103,18 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager } private final TIntHashSet myProcessedLogicalLines = new TIntHashSet(); + private final DocumentListener myDocumentListener = new LineOrientedDocumentChangeAdapter() { + @Override + public void beforeDocumentChange(int startLine, int endLine, int symbolsDifference) { + for (int i = startLine; i <= endLine; i++) { + myProcessedLogicalLines.remove(i); + } + } + + @Override + public void afterDocumentChange(int startLine, int endLine, int symbolsDifference) { + } + }; private final EditorTextRepresentationHelper myTextRepresentationHelper; private final SoftWrapsStorage myStorage; @@ -120,7 +132,6 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager myEditor = editor; myPainter = painter; myTextRepresentationHelper = textRepresentationHelper; - init(editor.getDocument()); } @SuppressWarnings({"AssignmentToForLoopParameter"}) @@ -147,19 +158,8 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager } } - private void init(final Document document) { - document.addDocumentListener(new LineOrientedDocumentChangeAdapter() { - @Override - public void beforeDocumentChange(int startLine, int endLine, int symbolsDifference) { - for (int i = startLine; i <= endLine; i++) { - myProcessedLogicalLines.remove(i); - } - } - - @Override - public void afterDocumentChange(int startLine, int endLine, int symbolsDifference) { - } - }); + public DocumentListener getDocumentListener() { + return myDocumentListener; } private void dropDataIfNecessary() { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDocumentChangeManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDocumentChangeManager.java index ac32e135de49..4ca0cf4f654f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDocumentChangeManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDocumentChangeManager.java @@ -17,11 +17,12 @@ package com.intellij.openapi.editor.impl.softwrap; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.event.DocumentEvent; +import com.intellij.openapi.editor.event.DocumentListener; import gnu.trove.TIntHashSet; import gnu.trove.TIntProcedure; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; import java.util.List; /** @@ -30,9 +31,9 @@ import java.util.List; * @author Denis Zhdanov * @since Jul 7, 2010 2:28:10 PM */ -public class SoftWrapDocumentChangeManager { +public class SoftWrapDocumentChangeManager implements DocumentListener { - private final List myDeferredChanges = new ArrayList(); + private final TIntHashSet mySoftWrapsToRemoveIndices = new TIntHashSet(); private final SoftWrapsStorage myStorage; private final Editor myEditor; @@ -40,16 +41,23 @@ public class SoftWrapDocumentChangeManager { public SoftWrapDocumentChangeManager(@NotNull Editor editor, @NotNull SoftWrapsStorage storage) { myStorage = storage; myEditor = editor; - init(editor.getDocument()); } /** - * Performs {@code 'soft wrap' -> 'hard wrap'} conversion for the given soft wrap. + * Performs {@code 'soft wrap' -> 'hard wrap'} conversion for soft wrap at the given offset if any. * - * @param softWrap soft wrap to make hard wrap + * @param offset offset that may point to soft wrap to make hard wrap + * @return true if given offset points to soft wrap that was made hard wrap; false otherwise */ - public void makeHardWrap(@NotNull TextChangeImpl softWrap) { + public boolean makeHardWrap(int offset) { + TextChangeImpl softWrap = myStorage.getSoftWrap(offset); + if (softWrap == null) { + return false; + } + + myStorage.removeByIndex(myStorage.getSoftWrapIndex(offset)); myEditor.getDocument().replaceString(softWrap.getStart(), softWrap.getEnd(), softWrap.getText()); + return true; } /** @@ -59,74 +67,63 @@ public class SoftWrapDocumentChangeManager { * until this method is called. */ public void syncSoftWraps() { - Document document = myEditor.getDocument(); - - TIntHashSet softWrapsToRemoveIndices = new TIntHashSet(); - - // Update offsets for soft wraps that remain after the changed line(s). - List softWraps = myStorage.getSoftWraps(); - for (DeferredChange change : myDeferredChanges) { - if (change.startOffset >= document.getTextLength()) { - continue; - } - int index = myStorage.getSoftWrapIndex(change.startOffset); - if (index < 0) { - index = -index -1; - } - for (int i = index; i < softWraps.size(); i++) { - TextChangeImpl softWrap = softWraps.get(i); - if (softWrapsToRemoveIndices.contains(i)) { - continue; - } - if (softWrap.getStart() < change.endOffset || softWrap.getStart() >= document.getTextLength()) { - softWrapsToRemoveIndices.add(i); - continue; - } - softWrap.advance(change.symbolsDifference); - } - } - - // Removes soft wraps from changed lines. - softWrapsToRemoveIndices.forEach(new TIntProcedure() { + mySoftWrapsToRemoveIndices.forEach(new TIntProcedure() { @Override public boolean execute(int value) { myStorage.removeByIndex(value); return true; } }); - - myDeferredChanges.clear(); + mySoftWrapsToRemoveIndices.clear(); } - private void init(final Document document) { - document.addDocumentListener(new LineOrientedDocumentChangeAdapter() { - @Override - public void beforeDocumentChange(int startLine, int endLine, int symbolsDifference) { - myDeferredChanges.add( - new DeferredChange(document.getLineStartOffset(startLine), document.getLineEndOffset(endLine), symbolsDifference) - ); - } + @Override + public void beforeDocumentChange(DocumentEvent event) { + // Mark soft wraps to be removed. + Document document = myEditor.getDocument(); + int startLine = document.getLineNumber(event.getOffset()); + int startOffset = document.getLineStartOffset(startLine); + int endLine = document.getLineNumber(event.getOffset() + event.getOldLength()); + int endOffset = document.getLineEndOffset(endLine); + markSoftWrapsForDeletion(startOffset, endOffset); - @Override - public void afterDocumentChange(int startLine, int endLine, int symbolsDifference) { - } - }); + // Update offsets for soft wraps that remain after the changed line(s). + applyDocumentChangeDiff(event); } - private static class DeferredChange { - final int startOffset; - final int endOffset; - final int symbolsDifference; + @Override + public void documentChanged(DocumentEvent event) { + } - DeferredChange(int startOffset, int endOffset, int symbolsDifference) { - this.startOffset = startOffset; - this.endOffset = endOffset; - this.symbolsDifference = symbolsDifference; + private void markSoftWrapsForDeletion(int startOffset, int endOffset) { + List softWraps = myStorage.getSoftWraps(); + int index = myStorage.getSoftWrapIndex(startOffset); + if (index < 0) { + index = -index - 1; + } + for (int i = index; i < softWraps.size(); i++) { + TextChangeImpl softWrap = softWraps.get(i); + if (softWrap.getStart() >= endOffset) { + break; + } + mySoftWrapsToRemoveIndices.add(i); + } + } + + private void applyDocumentChangeDiff(DocumentEvent event) { + List softWraps = myStorage.getSoftWraps(); + + // We use 'offset + 1' here because soft wrap is represented before the document symbol at the same offset, hence, document + // modification at particular offset doesn't affect soft wrap registered for the same offset. + int index = myStorage.getSoftWrapIndex(event.getOffset() + 1); + if (index < 0) { + index = -index - 1; } - @Override - public String toString() { - return startOffset + "-" + endOffset + ": " + symbolsDifference; + int diff = event.getNewLength() - event.getOldLength(); + for (int i = index; i < softWraps.size(); i++) { + TextChangeImpl softWrap = softWraps.get(i); + softWrap.advance(diff); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapHelper.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapHelper.java new file mode 100644 index 000000000000..f213fac8ac36 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapHelper.java @@ -0,0 +1,91 @@ +/* + * 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 com.intellij.openapi.editor.impl.softwrap; + +import com.intellij.openapi.editor.CaretModel; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.SoftWrapModel; +import com.intellij.openapi.editor.TextChange; + +/** + * Holds utility methods for soft wraps-related processing. + * + * @author Denis Zhdanov + * @since Aug 11, 2010 11:03:43 AM + */ +public class SoftWrapHelper { + + private SoftWrapHelper() { + } + + /** + * Every soft wrap implies that multiple visual positions correspond to the same document offset. We can classify + * such positions by the following criteria: + *
+   * 
    + *
  • positions from visual line with soft wrap start;
  • + *
  • positions from visual line with soft wrap end;
  • + *
+ *
+ *

+ * This method allows to answer if caret offset of the given editor points to soft wrap and visual caret position + * belongs to the visual line where soft wrap start is located. + * + * @param editor target editor + * @return true if caret offset of the given editor points to visual position that belongs to + * visual line before the soft wrap + */ + public static boolean isCaretBeforeSoftWrap(Editor editor) { + CaretModel caretModel = editor.getCaretModel(); + SoftWrapModel softWrapModel = editor.getSoftWrapModel(); + int offset = caretModel.getOffset(); + TextChange softWrap = softWrapModel.getSoftWrap(offset); + if (softWrap == null) { + return false; + } + + return editor.offsetToVisualPosition(offset).line != caretModel.getVisualPosition().line; + } + + /** + * Every soft wrap implies that multiple visual positions correspond to the same document offset. We can classify + * such positions by the following criteria: + *

+   * 
    + *
  • positions from visual line with soft wrap start;
  • + *
  • positions from visual line with soft wrap end;
  • + *
+ *
+ *

+ * This method allows to answer if caret offset of the given editor points to soft wrap and visual caret position + * belongs to the visual line where soft wrap end is located. + * + * @param editor target editor + * @return true if caret offset of the given editor points to visual position that belongs to + * visual line where soft wrap end is located + */ + public static boolean isCaretAfterSoftWrap(Editor editor) { + CaretModel caretModel = editor.getCaretModel(); + SoftWrapModel softWrapModel = editor.getSoftWrapModel(); + int offset = caretModel.getOffset(); + TextChange softWrap = softWrapModel.getSoftWrap(offset); + if (softWrap == null) { + return false; + } + + return editor.offsetToVisualPosition(offset).line == caretModel.getVisualPosition().line; + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/TextChangeImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/TextChangeImpl.java index d2f62f48c029..0a676dcb94f4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/TextChangeImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/TextChangeImpl.java @@ -134,8 +134,7 @@ public class TextChangeImpl implements TextChange { } /** - * Creates new {@link TextChange} on the basis of the current object with given offset applied to its {@link #getStart() start} - * and {@link #getEnd() end} properties. + * Applies given offset applied to the {@link #getStart() start} and {@link #getEnd() end} properties of current text change object. * * @param offset offset to apply to the current change object * @return text change that is built on the basis of the current object that with {@link #getStart() start} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaretModel.java b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaretModel.java index 0e133324936d..79439578f2ad 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaretModel.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaretModel.java @@ -44,14 +44,19 @@ public class TextComponentCaretModel implements CaretModel { } public void moveToLogicalPosition(final LogicalPosition pos) { - moveToOffset(myEditor.logicalPositionToOffset(pos)); + moveToOffset(myEditor.logicalPositionToOffset(pos), false); } public void moveToVisualPosition(final VisualPosition pos) { moveToLogicalPosition(myEditor.visualToLogicalPosition(pos)); } - public void moveToOffset(final int offset) { + @Override + public void moveToOffset(int offset) { + moveToOffset(offset, false); + } + + public void moveToOffset(final int offset, boolean locateBeforeSoftWrap) { myTextComponent.setCaretPosition(Math.min(offset, myTextComponent.getText().length())); } From ec81b8f41f63d910c627f63bd22566337fa9d93d Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Wed, 11 Aug 2010 15:22:18 +0400 Subject: [PATCH 20/36] IDEA-56405 Soft wrap, editing: typing on line split border replaces wrap sign with line feed; AssertionError at SoftWrapModelImpl.beforeDocumentChangeAtCaret() Avoiding processing soft wraps for removed document regions --- .../impl/softwrap/SoftWrapDocumentChangeManager.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDocumentChangeManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDocumentChangeManager.java index 4ca0cf4f654f..7191bf369c4f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDocumentChangeManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDocumentChangeManager.java @@ -123,7 +123,12 @@ public class SoftWrapDocumentChangeManager implements DocumentListener { int diff = event.getNewLength() - event.getOldLength(); for (int i = index; i < softWraps.size(); i++) { TextChangeImpl softWrap = softWraps.get(i); - softWrap.advance(diff); + + // Process only soft wraps not affected by the document change. E.g. there is a possible case that whole document text + // is replaced, hence, all registered soft wraps are affected by that and no offset advance should be performed. + if (softWrap.getStart() >= event.getOffset() + event.getOldLength()) { + softWrap.advance(diff); + } } } } From 047bbdd65d56bb18bb5a38a7521894f7b18cda03 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 11 Aug 2010 15:58:19 +0400 Subject: [PATCH 21/36] Empty import list placement and comment binding (fixed) --- .../java/stubs/JavaImportListElementType.java | 2 +- .../psi/impl/source/parsing/ParseUtil.java | 51 ++++++++++--------- .../commonParsing/ImportListBug.txt | 4 +- .../class/ExtraOpeningBraceInMethod.txt | 2 +- .../class/IncompleteAnnotation.txt | 2 +- .../commentBinding/BindBeforeClass1.txt | 2 +- .../commentBinding/BindBeforeClass3.txt | 4 +- .../commentBinding/BindBeforeClass4.txt | 4 +- .../commentBinding/BindBeforeClass6.java | 1 + .../commentBinding/BindBeforeClass6.txt | 20 ++++++++ .../declarationParsing/method/Errors0.txt | 4 +- .../parser-partial/files/BindDocComment1.txt | 2 +- .../CommentBindingTest.java | 1 + 13 files changed, 62 insertions(+), 37 deletions(-) create mode 100644 java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass6.java create mode 100644 java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass6.txt diff --git a/java/java-impl/src/com/intellij/psi/impl/java/stubs/JavaImportListElementType.java b/java/java-impl/src/com/intellij/psi/impl/java/stubs/JavaImportListElementType.java index 89866ec8fd04..addf040c23aa 100644 --- a/java/java-impl/src/com/intellij/psi/impl/java/stubs/JavaImportListElementType.java +++ b/java/java-impl/src/com/intellij/psi/impl/java/stubs/JavaImportListElementType.java @@ -32,7 +32,7 @@ import java.io.IOException; public class JavaImportListElementType extends JavaStubElementType { public JavaImportListElementType() { - super("IMPORT_LIST", true); + super("IMPORT_LIST"); } public PsiImportList createPsi(final PsiImportListStub stub) { diff --git a/java/java-impl/src/com/intellij/psi/impl/source/parsing/ParseUtil.java b/java/java-impl/src/com/intellij/psi/impl/source/parsing/ParseUtil.java index 2875cd7f6705..c0d9cece2e5e 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/parsing/ParseUtil.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/parsing/ParseUtil.java @@ -88,19 +88,17 @@ public class ParseUtil extends ParseUtilBase { return treeNext instanceof ModifierListElement; } - private static void moveEmptyImportList(ASTNode root) { - TreeElement first = (TreeElement)root.getFirstChildNode(); - TreeElement next = (TreeElement)TreeUtil.skipElements(first, ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET); - if (next == null) return; + private static final TokenSet BEFORE_IMPORT_BIT_SET = TokenSet.orSet(ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET, + TokenSet.create(JavaElementType.PACKAGE_STATEMENT)); - if (next.getElementType() == JavaElementType.PACKAGE_STATEMENT) { - first = next.getTreeNext(); - next = (TreeElement)TreeUtil.skipElements(first, ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET); - } + private static void moveEmptyImportList(final ASTNode root) { + final TreeElement anImport = (TreeElement)TreeUtil.skipElements(root.getFirstChildNode(), BEFORE_IMPORT_BIT_SET); + if (anImport == null || !isEmptyImportList(anImport)) return; - if (next != null && next != first && isEmptyImportList(next)) { - next.rawRemove(); - first.rawInsertBeforeMe(next); + final TreeElement next = (TreeElement)TreeUtil.skipElements(anImport.getTreeNext(), ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET); + if (next != null && next != anImport) { + anImport.rawRemove(); + next.rawInsertBeforeMe(anImport); } } @@ -124,23 +122,28 @@ public class ParseUtil extends ParseUtilBase { // we'll only bind additional preceding comments in pass 2 when the declaration does not yet have a "doc comment" iterator = comments.listIterator(); while (iterator.hasNext()) { - ASTNode child = iterator.next(); - IElementType type = child.getElementType(); + ASTNode comment = iterator.next(); + IElementType type = comment.getElementType(); if (type == JavaDocElementType.DOC_COMMENT) { - if (bindDocComment((TreeElement)child)) iterator.remove(); + if (bindDocComment((TreeElement)comment)) iterator.remove(); } // bind "trailing comments" (like "int a; // comment") else if (type == JavaTokenType.END_OF_LINE_COMMENT || type == JavaTokenType.C_STYLE_COMMENT) { - if (bindTrailingComment((TreeElement)child)) iterator.remove(); + if (bindTrailingComment((TreeElement)comment)) iterator.remove(); } } // pass 2: bind preceding comments (like "// comment \n void f();") iterator = comments.listIterator(comments.size()); while (iterator.hasPrevious()) { - ASTNode child = iterator.previous(); - TreeElement next = (TreeElement)TreeUtil.skipElements(child.getTreeNext(), ElementType.JAVA_WHITESPACE_BIT_SET); - bindPrecedingComment((TreeElement)child, next); + final ASTNode comment = iterator.previous(); + + TreeElement next = (TreeElement)TreeUtil.skipElements(comment.getTreeNext(), ElementType.JAVA_WHITESPACE_BIT_SET); + if (next != null && isEmptyImportList(next)) { + next = (TreeElement)TreeUtil.skipElements(next.getTreeNext(), ElementType.JAVA_WHITESPACE_BIT_SET); + } + + bindPrecedingComment((TreeElement)comment, next); } } @@ -220,22 +223,22 @@ public class ParseUtil extends ParseUtilBase { TreeElement child = comment; while (child != bindTo) { final TreeElement next = child.getTreeNext(); - child.rawRemove(); - first.rawInsertBeforeMe(child); + if (!isEmptyImportList(child)) { + child.rawRemove(); + first.rawInsertBeforeMe(child); + } child = next; } } private static boolean isBindingComment(final ASTNode comment) { - ASTNode prev = comment.getTreePrev(); - if (isEmptyImportList(prev)) prev = prev.getTreePrev(); + final ASTNode prev = comment.getTreePrev(); final boolean prevOk = prev == null || (prev.getElementType() == TokenType.WHITE_SPACE && prev.textContains('\n')); final ASTNode next = comment.getTreeNext(); final boolean nextOk = next != null && - next.getElementType() == TokenType.WHITE_SPACE && - StringUtil.getLineBreakCount(next.getText()) < 2; + (next.getElementType() != TokenType.WHITE_SPACE || StringUtil.getLineBreakCount(next.getText()) < 2); return prevOk && nextOk; } diff --git a/java/java-tests/testData/psi/parser-full/commonParsing/ImportListBug.txt b/java/java-tests/testData/psi/parser-full/commonParsing/ImportListBug.txt index 1240b05efda3..27e45ed74f16 100644 --- a/java/java-tests/testData/psi/parser-full/commonParsing/ImportListBug.txt +++ b/java/java-tests/testData/psi/parser-full/commonParsing/ImportListBug.txt @@ -1,8 +1,8 @@ PsiJavaFile:ImportListBug.java - PsiImportList - PsiDocComment PsiDocToken:DOC_COMMENT_END('/**/') + PsiImportList + PsiClass:AClass PsiDocComment PsiDocToken:DOC_COMMENT_START('/**') diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/class/ExtraOpeningBraceInMethod.txt b/java/java-tests/testData/psi/parser-full/declarationParsing/class/ExtraOpeningBraceInMethod.txt index 4f2592e789a4..c070d1e4522f 100644 --- a/java/java-tests/testData/psi/parser-full/declarationParsing/class/ExtraOpeningBraceInMethod.txt +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/class/ExtraOpeningBraceInMethod.txt @@ -7,9 +7,9 @@ PsiJavaFile:ExtraOpeningBraceInMethod.java PsiReferenceParameterList PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace('\n\n') PsiImportList - PsiWhiteSpace('\n\n') PsiClass:Foo PsiModifierList:public PsiKeyword:public('public') diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/class/IncompleteAnnotation.txt b/java/java-tests/testData/psi/parser-full/declarationParsing/class/IncompleteAnnotation.txt index ff2223e78f99..55dba34d5ed9 100644 --- a/java/java-tests/testData/psi/parser-full/declarationParsing/class/IncompleteAnnotation.txt +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/class/IncompleteAnnotation.txt @@ -7,9 +7,9 @@ PsiJavaFile:IncompleteAnnotation.java PsiReferenceParameterList PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace('\n\n') PsiImportList - PsiWhiteSpace('\n\n') PsiClass:Foo PsiModifierList:public PsiKeyword:public('public') diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass1.txt b/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass1.txt index cea6a9fd048b..313cbba303bf 100644 --- a/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass1.txt +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass1.txt @@ -7,9 +7,9 @@ PsiJavaFile:BindBeforeClass1.java PsiReferenceParameterList PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace('\n\n') PsiImportList - PsiWhiteSpace('\n\n') PsiClass:A PsiComment(END_OF_LINE_COMMENT)('// comment') PsiWhiteSpace('\n') diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass3.txt b/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass3.txt index fb9bfe97a11e..483844eead72 100644 --- a/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass3.txt +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass3.txt @@ -1,8 +1,8 @@ PsiJavaFile:BindBeforeClass3.java - PsiImportList - PsiComment(END_OF_LINE_COMMENT)('// comment') PsiWhiteSpace('\n\n') + PsiImportList + PsiClass:A PsiModifierList: diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass4.txt b/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass4.txt index dd29e7d71f22..212dd6ae67f6 100644 --- a/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass4.txt +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass4.txt @@ -7,10 +7,10 @@ PsiJavaFile:BindBeforeClass4.java PsiReferenceParameterList PsiJavaToken:SEMICOLON(';') + PsiComment(END_OF_LINE_COMMENT)('// comment') + PsiWhiteSpace('\n') PsiImportList - PsiComment(END_OF_LINE_COMMENT)('// comment') - PsiWhiteSpace('\n') PsiClass:A PsiModifierList: diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass6.java b/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass6.java new file mode 100644 index 000000000000..bffac86bb3fa --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass6.java @@ -0,0 +1 @@ +/* comment */class A { } \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass6.txt b/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass6.txt new file mode 100644 index 000000000000..032500077226 --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/commentBinding/BindBeforeClass6.txt @@ -0,0 +1,20 @@ +PsiJavaFile:BindBeforeClass6.java + PsiImportList + + PsiClass:A + PsiComment(C_STYLE_COMMENT)('/* comment */') + PsiModifierList: + + PsiKeyword:class('class') + PsiWhiteSpace(' ') + PsiIdentifier:A('A') + PsiTypeParameterList + + PsiReferenceList + + PsiReferenceList + + PsiWhiteSpace(' ') + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/method/Errors0.txt b/java/java-tests/testData/psi/parser-full/declarationParsing/method/Errors0.txt index e778448e7665..a18a705db37e 100644 --- a/java/java-tests/testData/psi/parser-full/declarationParsing/method/Errors0.txt +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/method/Errors0.txt @@ -1,8 +1,8 @@ PsiJavaFile:Errors0.java - PsiImportList - PsiComment(END_OF_LINE_COMMENT)('// illegal modifier combinations') PsiWhiteSpace('\n\n') + PsiImportList + PsiClass:a PsiModifierList:abstract public PsiKeyword:abstract('abstract') diff --git a/java/java-tests/testData/psi/parser-partial/files/BindDocComment1.txt b/java/java-tests/testData/psi/parser-partial/files/BindDocComment1.txt index bc038a924357..44939cacd57f 100644 --- a/java/java-tests/testData/psi/parser-partial/files/BindDocComment1.txt +++ b/java/java-tests/testData/psi/parser-partial/files/BindDocComment1.txt @@ -13,9 +13,9 @@ PsiJavaFile:BindDocComment1.java PsiReferenceParameterList PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace('\n') PsiImportList - PsiWhiteSpace('\n') PsiClass:A PsiModifierList: diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/CommentBindingTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/CommentBindingTest.java index 7ba6894f30ea..55b61a535152 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/CommentBindingTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/CommentBindingTest.java @@ -21,4 +21,5 @@ public class CommentBindingTest extends JavaParsingTestCase { public void testBindBeforeClass3() { doTest(true); } public void testBindBeforeClass4() { doTest(true); } public void testBindBeforeClass5() { doTest(true); } + public void testBindBeforeClass6() { doTest(true); } } \ No newline at end of file From 716348d4bb22adf4b7d536bcb9211ab1d2bd72ed Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 11 Aug 2010 16:07:37 +0400 Subject: [PATCH 22/36] VCS: diff from annotations: correctly find "get committed list" inside VCS provider itself (fix CVS); correctly jump to change when having ignored space changes in revision; calculate jump line in pooled thred; other small fixes --- .../openapi/diff/impl/DiffPanelImpl.java | 76 +++++++++++-------- .../openapi/vcs/CommittedChangesProvider.java | 3 +- .../vcs/actions/AnnotateToggleAction.java | 7 +- .../CompositeCommittedChangesProvider.java | 3 +- .../CvsCommittedChangesProvider.java | 4 +- .../GitCommittedChangeListProvider.java | 4 +- .../HgCachingCommitedChangesProvider.java | 6 +- .../history/SvnCommittedChangesProvider.java | 11 ++- 8 files changed, 67 insertions(+), 47 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java index 097af6a2c19c..215f5632b3fd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java @@ -19,7 +19,9 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.*; import com.intellij.openapi.diff.actions.MergeActionGroup; @@ -377,26 +379,37 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid final FragmentList fragmentList = getFragments(); - final ChangedLinesIterator changedLinesIterator = new ChangedLinesIterator(fragmentList.iterator(), document); - final CacheOneStepIterator> cacheOneStepIterator = - new CacheOneStepIterator>(changedLinesIterator); - final NavigationContextChecker checker = new NavigationContextChecker(cacheOneStepIterator, scrollContext); - int line = checker.contextMatchCheck(); - if (line < 0) { - /*final ChangedLinesIterator changedLinesIterator2 = new ChangedLinesIterator(fragmentList.iterator(), document); - final CacheOneStepIterator> cacheOneStepIterator2 = - new CacheOneStepIterator>(changedLinesIterator2); - final NavigationContextChecker checker2 = new NavigationContextChecker(cacheOneStepIterator2, - new DiffNavigationContext(Collections.emptyList(), scrollContext.getTargetString())); - line = checker2.contextMatchCheck(); - if (line >= 0) { - myRightSide.scrollToFirstDiff(line); - } else {*/ - scrollCurrentToFirstDiff(); - //} - } else { - myRightSide.scrollToFirstDiff(line); - } + final Application application = ApplicationManager.getApplication(); + application.executeOnPooledThread(new Runnable() { + @Override + public void run() { + final ChangedLinesIterator changedLinesIterator = new ChangedLinesIterator(fragmentList.iterator(), document, false); + final CacheOneStepIterator> cacheOneStepIterator = + new CacheOneStepIterator>(changedLinesIterator); + final NavigationContextChecker checker = new NavigationContextChecker(cacheOneStepIterator, scrollContext); + int line = checker.contextMatchCheck(); + if (line < 0) { + // this will work for the case, when spaces changes are ignored, and corresponding fragments are not reported as changed + // just try to find target line -> +- + final ChangedLinesIterator changedLinesIterator2 = new ChangedLinesIterator(fragmentList.iterator(), document, true); + final CacheOneStepIterator> cacheOneStepIterator2 = + new CacheOneStepIterator>(changedLinesIterator2); + final NavigationContextChecker checker2 = new NavigationContextChecker(cacheOneStepIterator2, scrollContext); + line = checker2.contextMatchCheck(); + } + final int finalLine = line; + application.invokeLater(new Runnable() { + @Override + public void run() { + if (finalLine >= 0) { + myRightSide.scrollToFirstDiff(finalLine); + } else { + scrollCurrentToFirstDiff(); + } + } + }, ModalityState.stateForComponent(myOwnerWindow)); + } + }); } } @@ -408,12 +421,14 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid private static class ChangedLinesIterator implements Iterator> { private final Document myDocument; + private final boolean myIgnoreFragmentsType; private final Iterator myFragmentsIterator; private java.util.List> myBuffer; - private ChangedLinesIterator(Iterator fragmentsIterator, Document document) { + private ChangedLinesIterator(Iterator fragmentsIterator, Document document, final boolean ignoreFragmentsType) { myFragmentsIterator = fragmentsIterator; myDocument = document; + myIgnoreFragmentsType = ignoreFragmentsType; myBuffer = new LinkedList>(); } @@ -428,16 +443,17 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid return myBuffer.remove(0); } + final TextRange textRange; Fragment fragment = null; while (myFragmentsIterator.hasNext()) { fragment = myFragmentsIterator.next(); final TextDiffTypeEnum type = fragment.getType(); - if ((type == null) || TextDiffTypeEnum.DELETED.equals(type) || TextDiffTypeEnum.NONE.equals(type)) continue; + if ((! myIgnoreFragmentsType) && ((type == null) || TextDiffTypeEnum.DELETED.equals(type) || TextDiffTypeEnum.NONE.equals(type))) continue; break; } if (fragment == null) return null; - - final TextRange textRange = fragment.getRange(FragmentSide.SIDE2); + + textRange = fragment.getRange(FragmentSide.SIDE2); ApplicationManager.getApplication().runReadAction(new Runnable() { @Override public void run() { @@ -445,7 +461,6 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid final int endLine = myDocument.getLineNumber(textRange.getEndOffset()); for (int i = startLine; i <= endLine; i++) { String text = myDocument.getText().substring(myDocument.getLineStartOffset(i), myDocument.getLineEndOffset(i)); - //text = text.endsWith("\r\n") ? text.substring(0, text.length() - 2) : text.substring(0, text.length() - 1); myBuffer.add(new Pair(i, text)); } } @@ -472,15 +487,16 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid public int contextMatchCheck() { final Iterable contextLines = myContext.getPreviousLinesIterable(); + // we ignore spaces.. at least at start/end, since some version controls could ignore their changes when doing annotate final Iterator iterator = contextLines.iterator(); if (iterator.hasNext()) { - String contextLine = iterator.next(); + String contextLine = iterator.next().trim(); while (myChangedLinesIterator.hasNext()) { final Pair pair = myChangedLinesIterator.next(); - if (pair.getSecond().equals(contextLine)) { + if (pair.getSecond().trim().equals(contextLine)) { if (! iterator.hasNext()) break; - contextLine = iterator.next(); + contextLine = iterator.next().trim(); } } if (iterator.hasNext()) { @@ -489,10 +505,10 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid } if (! myChangedLinesIterator.hasNext()) return -1; - final String targetLine = myContext.getTargetString(); + final String targetLine = myContext.getTargetString().trim(); while (myChangedLinesIterator.hasNext()) { final Pair pair = myChangedLinesIterator.next(); - if (pair.getSecond().equals(targetLine)) { + if (pair.getSecond().trim().equals(targetLine)) { return pair.getFirst(); } } diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/CommittedChangesProvider.java b/platform/vcs-api/src/com/intellij/openapi/vcs/CommittedChangesProvider.java index 2c4bcc8a9d7f..9aa5d7f829c8 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/CommittedChangesProvider.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/CommittedChangesProvider.java @@ -23,6 +23,7 @@ import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; import com.intellij.openapi.vcs.versionBrowser.ChangesBrowserSettingsEditor; import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.AsynchConsumer; import org.jetbrains.annotations.Nullable; @@ -58,5 +59,5 @@ public interface CommittedChangesProvider (myLinesStartOffsets.size() - 1)) + (number + 1 >= myLinesStartOffsets.size()) ? myContents.length() : myLinesStartOffsets.get(number + 1)); text = text.endsWith("\r\n") ? text.substring(0, text.length() - 2) : text.substring(0, text.length() - 1); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CompositeCommittedChangesProvider.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CompositeCommittedChangesProvider.java index 161437057e83..8b4c287f54f9 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CompositeCommittedChangesProvider.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CompositeCommittedChangesProvider.java @@ -24,6 +24,7 @@ import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; import com.intellij.openapi.vcs.versionBrowser.ChangesBrowserSettingsEditor; import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; import com.intellij.openapi.vcs.versionBrowser.DateFilterComponent; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.AsynchConsumer; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; @@ -153,7 +154,7 @@ public class CompositeCommittedChangesProvider implements CommittedChangesProvid } @Override - public CommittedChangeList getOneList(RepositoryLocation location, VcsRevisionNumber number) { + public CommittedChangeList getOneList(VirtualFile file, VcsRevisionNumber number) { throw new UnsupportedOperationException(); } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java index e75f05c3cadb..17ce14d514ef 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java @@ -132,8 +132,8 @@ public class CvsCommittedChangesProvider implements CachingCommittedChangesProvi @Nullable @Override - public CvsChangeList getOneList(RepositoryLocation location, final VcsRevisionNumber number) throws VcsException { - CvsRepositoryLocation cvsLocation = (CvsRepositoryLocation) location; + public CvsChangeList getOneList(VirtualFile file, final VcsRevisionNumber number) throws VcsException { + CvsRepositoryLocation cvsLocation = (CvsRepositoryLocation) getLocationFor(new FilePathImpl(file)); final String module = cvsLocation.getModuleName(); final CvsEnvironment connectionSettings = cvsLocation.getEnvironment(); if (connectionSettings.isOffline()) { diff --git a/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java b/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java index 569d888a7ffb..0b15782eb351 100644 --- a/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java +++ b/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java @@ -225,8 +225,8 @@ public class GitCommittedChangeListProvider implements CommittedChangesProvider< } @Override - public CommittedChangeList getOneList(RepositoryLocation location, final VcsRevisionNumber number) throws VcsException { - final GitRepositoryLocation l = (GitRepositoryLocation)location; + public CommittedChangeList getOneList(VirtualFile file, final VcsRevisionNumber number) throws VcsException { + final GitRepositoryLocation l = (GitRepositoryLocation) getLocationFor(new FilePathImpl(file)); VirtualFile root = LocalFileSystem.getInstance().findFileByIoFile(l.getRoot()); if (root == null) { throw new VcsException("The repository does not exists anymore: " + l.getRoot()); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java index bad269b1dcaf..156acceb9274 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java @@ -14,6 +14,7 @@ package org.zmlx.hg4idea.provider; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.actions.VcsContextFactory; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.committed.DecoratorManager; import com.intellij.openapi.vcs.changes.committed.VcsCommittedListsZipper; @@ -270,13 +271,14 @@ public class HgCachingCommitedChangesProvider } @Override - public CommittedChangeList getOneList(RepositoryLocation location, VcsRevisionNumber number) throws VcsException { + public CommittedChangeList getOneList(VirtualFile file, VcsRevisionNumber number) throws VcsException { final ChangeBrowserSettings settings = createDefaultSettings(); settings.USE_CHANGE_AFTER_FILTER = true; settings.USE_CHANGE_BEFORE_FILTER = true; settings.CHANGE_AFTER = number.asString(); settings.CHANGE_BEFORE = number.asString(); - final List list = getCommittedChanges(settings, location, 1); + final List list = getCommittedChanges(settings, getLocationFor( + VcsContextFactory.SERVICE.getInstance().createFilePathOn(file)), 1); if (list.size() == 1) { return list.get(0); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java index daff6f2f5c95..84f9d8b7530e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java @@ -491,8 +491,11 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi } @Override - public SvnChangeList getOneList(final RepositoryLocation location, VcsRevisionNumber number) throws VcsException { - final String url = ((SvnRepositoryLocation)location).getURL(); + public SvnChangeList getOneList(final VirtualFile file, VcsRevisionNumber number) throws VcsException { + final VirtualFile root = ProjectLevelVcsManager.getInstance(myProject).getVcsRootFor(file); + final SvnRepositoryLocation svnRootLocation = (SvnRepositoryLocation)getLocationFor(new FilePathImpl(root)); + if (svnRootLocation == null) return null; + final String url = svnRootLocation.getURL(); final long revision; try { revision = Long.parseLong(number.asString()); @@ -521,11 +524,11 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi throw new VcsException(e); } - tryExactHit((SvnRepositoryLocation)location, result, logger, revisionBefore, repositoryUrl, svnurl); + tryExactHit(svnRootLocation, result, logger, revisionBefore, repositoryUrl, svnurl); if (result[0] == null) { tryByRoot(result, logger, revisionBefore, repositoryUrl); if (result[0] == null) { - tryStepByStep((SvnRepositoryLocation)location, result, logger, revisionBefore, repositoryUrl, svnurl); + tryStepByStep(svnRootLocation, result, logger, revisionBefore, repositoryUrl, svnurl); } } return result[0]; From 06225646b7f6ce0715c7dba011001b9f988e924e Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 11 Aug 2010 16:25:24 +0400 Subject: [PATCH 23/36] VCS: NPE in shelve's path verifier --- .../openapi/diff/impl/patch/formove/PathsVerifier.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java index f6f5b20f91bf..f747b1f6aa0b 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java @@ -548,11 +548,15 @@ public class PathsVerifier { "\nThe following files should be created by patch, but they already exist.\nDo you want to override them?\n", title, "The following file should be created by patch, but it already exists.\nDo you want to override it?\n{0}", VcsShowConfirmationOption.STATIC_SHOW_CONFIRMATION); - for (FilePath path : selected) { - myOverrideExisting.remove(path); + if (selected != null) { + for (FilePath path : selected) { + myOverrideExisting.remove(path); + } } result.addAll(myOverrideExisting.values()); - myOverridenPaths.addAll(selected); + if (selected != null) { + myOverridenPaths.addAll(selected); + } } result.addAll(mySkipDeleted.values()); return result; From 641be6fa1a3ed7f9571d27f8633b42102f97b6d2 Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Wed, 11 Aug 2010 16:25:49 +0400 Subject: [PATCH 24/36] fix wizard popups background on macs --- .../src/com/intellij/ui/popup/AbstractPopup.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index db179130e98b..5bfb2e92403c 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -1025,6 +1025,10 @@ public class AbstractPopup implements JBPopup { else { setBorder(border); } + + if (drawMacCorner && UIUtil.isUnderAquaLookAndFeel()) { + setBackground(new Color(UIUtil.getPanelBackgound().getRGB())); + } } public void paint(Graphics g) { From cff8ef4962c1a9b9061a170b2c421858b027a0d2 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Wed, 11 Aug 2010 16:49:48 +0400 Subject: [PATCH 25/36] IDEA-53596 Soft wrap for editors (x; y) <-> visual position mapping algorithm is corrected --- .../openapi/editor/impl/EditorImpl.java | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 1e07bbfe6381..8c2c112542ad 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -878,6 +878,18 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi // There is a possible case that soft wrap contains more than one line feed inside and we need to start counting not // from its first line. int softWrapLinesToSkip = activeSoftWrapProcessed ? 0 : logicalPosition.softWrapLinesOnCurrentLogicalLine; + + // Process 'before soft wrap' drawing. + if (softWrapLinesToSkip <= 0) { + prevX = x; + charWidth = getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED); + x += charWidth; + if (x >= px) { + break outer; + } + column++; + } + CharSequence softWrapText = softWrap.getText(); for (int i = 0; i < softWrapText.length(); i++) { c = softWrapText.charAt(i); @@ -888,8 +900,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi continue; } prevX = x; + charWidth = charToVisibleWidth(c, fontType, x); if (charWidth == 0) { + charWidth = spaceSize; break outer; } @@ -946,7 +960,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if ((x - px) * 2 < charWidth) column++; } else { - column += (px - x) / EditorUtil.getSpaceWidth(fontType, this); + column += (px - x) / spaceSize; + if ((px - x) * 2 >= spaceSize) { + column++; + } } } @@ -1132,9 +1149,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (softWrap != null && offset > startOffset) { column++; x += getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED); - if (column >= length) { - break; - } + // Assuming that first soft wrap symbol is line feed or all soft wrap symbols before the first line feed are spaces. + break; } FoldRegion region = state.getCurrentFold(); From bd63e8b0969fa7d0056ace13a72781f372d93b71 Mon Sep 17 00:00:00 2001 From: Roman Chernyatchik Date: Wed, 11 Aug 2010 16:41:15 +0400 Subject: [PATCH 26/36] NPE fixed --- .../src/com/intellij/openapi/vcs/ex/LineStatusTracker.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java index 8f1c951e03f6..2b9064585150 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java @@ -234,7 +234,12 @@ public class LineStatusTracker { } } + @Nullable private static Color brighter(final Color color) { + if (color == null) { + return null; + } + final float[] hsbStripeColor = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null); if (hsbStripeColor[1] < 0.02f) { From 5e07f78373f32f3e7eb4e4f86f760212c00bbe65 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 11 Aug 2010 17:42:27 +0400 Subject: [PATCH 27/36] toHex/fromHex methods --- .../codeInsight/javadoc/ColorUtil.java | 16 +----- .../util/src/com/intellij/ui/ColorUtil.java | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java index 745693b94d71..0ae045a61d51 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java @@ -29,22 +29,8 @@ public class ColorUtil { private ColorUtil() { } - public static String toHex(@NotNull final Color color) { - final StringBuffer sb = new StringBuffer(); - for (int i = 0; i < 3; i++) { - String s = Integer.toHexString(i == 0 ? color.getRed() : i == 1 ? color.getGreen() : color.getBlue()); - if (s.length() < 2) { - sb.append('0'); - } - - sb.append(s); - } - - return sb.toString(); - } - public static String generatePreviewHtml(@NotNull final Color color) { - return String.format("

 
", toHex(color)); + return String.format("
 
", com.intellij.ui.ColorUtil.toHex(color)); } public static void appendColorPreview(final PsiVariable variable, final StringBuilder buffer) { diff --git a/platform/util/src/com/intellij/ui/ColorUtil.java b/platform/util/src/com/intellij/ui/ColorUtil.java index 96beb3d05dc6..7a0ee5b85f6c 100644 --- a/platform/util/src/com/intellij/ui/ColorUtil.java +++ b/platform/util/src/com/intellij/ui/ColorUtil.java @@ -19,8 +19,14 @@ */ package com.intellij.ui; +import org.jetbrains.annotations.NotNull; + import java.awt.*; +/** + * @author max + * @author Konstantin Bulenkov + */ public class ColorUtil { private ColorUtil() { } @@ -36,4 +42,49 @@ public class ColorUtil { public static Color withAlphaAdjustingDarkness(Color c, double d) { return shift(withAlpha(c, d), d); } + + public static String toHex(@NotNull final Color c) { + final String R = Integer.toHexString(c.getRed()); + final String G = Integer.toHexString(c.getGreen()); + final String B = Integer.toHexString(c.getBlue()); + return new StringBuffer() + .append(R.length() < 2 ? "0" : "").append(R) + .append(G.length() < 2 ? "0" : "").append(G) + .append(B.length() < 2 ? "0" : "").append(B) + .toString(); + } + + /** + * Return Color object from string. The following formats are allowed: + * #abc123, + * ABC123, + * ab5, + * #FFF. + * + * @param str hex string + * @return Color object + */ + public static Color fromHex(String str) { + if (str.startsWith("#")) { + str = str.substring(1); + } + if (str.length() == 3) { + return new Color( + 17 * Integer.valueOf(String.valueOf(str.charAt(0)), 16).intValue(), + 17 * Integer.valueOf(String.valueOf(str.charAt(1)), 16).intValue(), + 17 * Integer.valueOf(String.valueOf(str.charAt(2)), 16).intValue()); + } else if (str.length() == 6) { + return Color.decode("0x" + str); + } else { + throw new IllegalArgumentException("Should be String of 3 or 6 chars length."); + } + } + + public static Color fromHex(String str, Color defaultValue) { + try { + return fromHex(str); + } catch (Exception e) { + return defaultValue; + } + } } From 38b3a388906ff5c8e96052dd4f8475a4e39deb45 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 11 Aug 2010 17:43:41 +0400 Subject: [PATCH 28/36] make it possible to select color for non-project files --- .../ui/tabs/FileColorManagerImpl.java | 17 ++- .../ui/tabs/FileColorsConfigurablePanel.java | 7 +- .../intellij/ui/CheckBoxWithColorChooser.java | 110 ++++++++++++++++++ 3 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 platform/platform-api/src/com/intellij/ui/CheckBoxWithColorChooser.java diff --git a/platform/lang-impl/src/com/intellij/ui/tabs/FileColorManagerImpl.java b/platform/lang-impl/src/com/intellij/ui/tabs/FileColorManagerImpl.java index 40ea7834ed48..7860954753c2 100644 --- a/platform/lang-impl/src/com/intellij/ui/tabs/FileColorManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/ui/tabs/FileColorManagerImpl.java @@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; +import com.intellij.ui.ColorUtil; import com.intellij.ui.FileColorManager; import com.intellij.ui.LightColors; import com.intellij.util.containers.hash.LinkedHashMap; @@ -45,6 +46,7 @@ import java.util.List; id = "other", file = "$WORKSPACE_FILE$")}) public class FileColorManagerImpl extends FileColorManager implements PersistentStateComponent { + public static final Color DEFAULT_NON_PROJECT_FILES_COLOR = new Color(255, 255, 228); private boolean myEnabled = true; private final FileColorsModel myModel; @@ -54,6 +56,7 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent private final Project myProject; private boolean myEnabledForTabs = true; private boolean myHighlightNonProjectFiles = true; + private Color myNonProjectFilesColor = DEFAULT_NON_PROJECT_FILES_COLOR; private static final Map ourDefaultColors; private static final Map ourHiddenColors; @@ -69,8 +72,6 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent ourDefaultColors.put("Rose", new Color(242, 206, 202)); ourDefaultColors.put("Violet", new Color(222, 213, 241)); ourDefaultColors.put("Yellow", new Color(247, 241, 203)); - - ourHiddenColors.put(OUT_OF_PROJECT_SCOPE_COLOR, new Color(255, 255, 228)); } public FileColorManagerImpl(@NotNull final Project project) { @@ -114,6 +115,7 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent element.setAttribute("enabled", Boolean.toString(myEnabled)); element.setAttribute("enabledForTabs", Boolean.toString(myEnabledForTabs)); element.setAttribute("highlightNonProjectFiles", Boolean.toString(myHighlightNonProjectFiles)); + element.setAttribute("nonProjectFilesColor", ColorUtil.toHex(myNonProjectFilesColor)); } myModel.save(element, shared); @@ -124,6 +126,7 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent @SuppressWarnings({"MethodMayBeStatic"}) @Nullable public Color getColor(@NotNull final String name) { + if (OUT_OF_PROJECT_SCOPE_COLOR.equals(name)) return myNonProjectFilesColor; final Color color = ourDefaultColors.get(name); return color == null ? ourHiddenColors.get(name) : color; } @@ -152,6 +155,8 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent final String highlightNonProjectFiles = state.getAttributeValue("highlightNonProjectFiles"); myHighlightNonProjectFiles = highlightNonProjectFiles == null ? true : Boolean.valueOf(highlightNonProjectFiles); + + myNonProjectFilesColor = ColorUtil.fromHex(state.getAttributeValue("nonProjectFilesColor"), DEFAULT_NON_PROJECT_FILES_COLOR); } myModel.load(state, shared); @@ -227,4 +232,12 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent public List getSharedConfigurations() { return myModel.getSharedConfigurations(); } + + public Color getNonProjectFilesColor() { + return myNonProjectFilesColor; + } + + public void setNonProjectFilesColor(Color color) { + myNonProjectFilesColor = color; + } } diff --git a/platform/lang-impl/src/com/intellij/ui/tabs/FileColorsConfigurablePanel.java b/platform/lang-impl/src/com/intellij/ui/tabs/FileColorsConfigurablePanel.java index 5693b316a581..3b2ae1a2754f 100644 --- a/platform/lang-impl/src/com/intellij/ui/tabs/FileColorsConfigurablePanel.java +++ b/platform/lang-impl/src/com/intellij/ui/tabs/FileColorsConfigurablePanel.java @@ -21,6 +21,7 @@ import com.intellij.ide.util.scopeChooser.EditScopesDialog; import com.intellij.openapi.Disposable; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.StripeTable; +import com.intellij.ui.CheckBoxWithColorChooser; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -37,7 +38,7 @@ public class FileColorsConfigurablePanel extends JPanel implements Disposable { private FileColorManagerImpl myManager; private final JCheckBox myEnabledCheckBox; private final JCheckBox myTabsEnabledCheckBox; - private final JCheckBox myHighlightNonProjectFilesCheckBox; + private final CheckBoxWithColorChooser myHighlightNonProjectFilesCheckBox; private final FileColorSettingsTable myLocalTable; private final FileColorSettingsTable mySharedTable; @@ -58,7 +59,7 @@ public class FileColorsConfigurablePanel extends JPanel implements Disposable { myTabsEnabledCheckBox.setMnemonic('T'); topPanel.add(myTabsEnabledCheckBox); - myHighlightNonProjectFilesCheckBox = new JCheckBox("Highlight Non-Project Files"); + myHighlightNonProjectFilesCheckBox = new CheckBoxWithColorChooser("Highlight Non-Project Files", false, myManager.getNonProjectFilesColor()); myHighlightNonProjectFilesCheckBox.setMnemonic('N'); topPanel.add(myHighlightNonProjectFilesCheckBox); topPanel.add(Box.createHorizontalGlue()); @@ -236,6 +237,7 @@ public class FileColorsConfigurablePanel extends JPanel implements Disposable { modified |= myTabsEnabledCheckBox.isSelected() != myManager.isEnabledForTabs(); modified |= myHighlightNonProjectFilesCheckBox.isSelected() != myManager.isHighlightNonProjectFiles(); modified |= myLocalTable.isModified() || mySharedTable.isModified(); + modified |= myHighlightNonProjectFilesCheckBox.getColor().getRGB() != myManager.getNonProjectFilesColor().getRGB(); return modified; } @@ -244,6 +246,7 @@ public class FileColorsConfigurablePanel extends JPanel implements Disposable { myManager.setEnabled(myEnabledCheckBox.isSelected()); myManager.setEnabledForTabs(myTabsEnabledCheckBox.isSelected()); myManager.setHighlightNonProjectFiles(myHighlightNonProjectFilesCheckBox.isSelected()); + myManager.setNonProjectFilesColor(myHighlightNonProjectFilesCheckBox.getColor()); myLocalTable.apply(); mySharedTable.apply(); diff --git a/platform/platform-api/src/com/intellij/ui/CheckBoxWithColorChooser.java b/platform/platform-api/src/com/intellij/ui/CheckBoxWithColorChooser.java new file mode 100644 index 000000000000..592c30780954 --- /dev/null +++ b/platform/platform-api/src/com/intellij/ui/CheckBoxWithColorChooser.java @@ -0,0 +1,110 @@ +/* + * 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 com.intellij.ui; + +import com.intellij.openapi.util.SystemInfo; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * @author Konstantin Bulenkov + */ +public class CheckBoxWithColorChooser extends JPanel { + private Color myColor; + private final JCheckBox myCheckbox; + + public CheckBoxWithColorChooser(String text, boolean selected, Color color) { + setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + myColor = color; + myCheckbox = new JCheckBox(text, selected); + add(myCheckbox); + add(new MyColorButton()); + } + + public CheckBoxWithColorChooser(String text, boolean selected) { + this(text, selected, Color.WHITE); + } + + public CheckBoxWithColorChooser(String text) { + this(text, false); + } + + public void setMnemonic(char c) { + myCheckbox.setMnemonic(c); + } + + public Color getColor() { + return myColor; + } + + public void setColor(Color color) { + myColor = color; + } + + public void setSelected(boolean selected) { + myCheckbox.setSelected(selected); + } + + + public boolean isSelected() { + return myCheckbox.isSelected(); + } + + private class MyColorButton extends JButton { + MyColorButton() { + setMargin(new Insets(0, 0, 0, 0)); + setDefaultCapable(false); + setFocusable(false); + if (SystemInfo.isMac) { + putClientProperty("JButton.buttonType", "square"); + } + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (myCheckbox.isSelected()) { + final Color color = ColorChooser.chooseColor(myCheckbox, "Chose color", CheckBoxWithColorChooser.this.myColor); + if (color != null) { + myColor = color; + } + } + } + }); + } + + @Override + public void paint(Graphics g) { + final Color color = g.getColor(); + g.setColor(myColor); + g.fillRect(0, 0, getWidth(), getHeight()); + g.setColor(color); + } + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + public Dimension getMaximumSize() { + return getPreferredSize(); + } + + public Dimension getPreferredSize() { + return new Dimension(12, 12); + } + } +} From 4ae699956b4da74a36f6a674b308bc242c90162c Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Wed, 11 Aug 2010 17:58:15 +0400 Subject: [PATCH 29/36] fix mac popups bg color [finally] --- .../src/com/intellij/ui/popup/AbstractPopup.java | 4 ---- .../src/com/intellij/ui/popup/PopupComponent.java | 7 +++++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index 5bfb2e92403c..db179130e98b 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -1025,10 +1025,6 @@ public class AbstractPopup implements JBPopup { else { setBorder(border); } - - if (drawMacCorner && UIUtil.isUnderAquaLookAndFeel()) { - setBackground(new Color(UIUtil.getPanelBackgound().getRGB())); - } } public void paint(Graphics g) { diff --git a/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java b/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java index 445c642a0e0a..94b4bbbdee29 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java @@ -17,7 +17,9 @@ package com.intellij.ui.popup; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.ui.popup.util.PopupUtil; +import com.intellij.openapi.util.SystemInfo; import com.intellij.util.ReflectionUtil; +import com.intellij.util.ui.UIUtil; import javax.swing.*; import java.awt.*; @@ -133,6 +135,11 @@ public interface PopupComponent { public AwtPopupWrapper(Popup popup) { myPopup = popup; + + if (SystemInfo.isMac && UIUtil.isUnderAquaLookAndFeel()) { + final Component c = (Component)ReflectionUtil.getField(Popup.class, myPopup, Component.class, "component"); + c.setBackground(UIUtil.getPanelBackgound()); + } } public void hide(boolean dispose) { From 8dfb665829618534b8a4d8ff6379d03d082697bf Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Wed, 11 Aug 2010 18:50:45 +0400 Subject: [PATCH 30/36] IDEA-53596 Soft wrap for editors Symbol width caching algorihtm is corrected --- .../DefaultEditorTextRepresentationHelper.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/DefaultEditorTextRepresentationHelper.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/DefaultEditorTextRepresentationHelper.java index af2e6edf8e4e..182ca872f136 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/DefaultEditorTextRepresentationHelper.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/DefaultEditorTextRepresentationHelper.java @@ -76,6 +76,7 @@ public class DefaultEditorTextRepresentationHelper implements EditorTextRepresen for (int i = startToUse; i < end; i++) { char c = text.charAt(i); if (c != '\t') { + mySharedKey.c = c; result += charWidth(c); continue; } @@ -102,23 +103,25 @@ public class DefaultEditorTextRepresentationHelper implements EditorTextRepresen } private static class Key { - public String fontName; - private int fontSize; - private int fontType; + public String fontName; + private int fontSize; + private int fontType; + private char c; private Key() { - this(null, 0, 0); + this(null, 0, 0, ' '); } - Key(String fontName, int fontSize, int fontType) { + Key(String fontName, int fontSize, int fontType, char c) { this.fontName = fontName; this.fontSize = fontSize; this.fontType = fontType; + this.c = c; } @Override protected Key clone() { - return new Key(fontName, fontSize, fontType); + return new Key(fontName, fontSize, fontType, c); } @Override @@ -126,6 +129,7 @@ public class DefaultEditorTextRepresentationHelper implements EditorTextRepresen int result = fontName != null ? fontName.hashCode() : 0; result = 31 * result + fontSize; result = 31 * result + fontType; + result = 31 * result + c; return result; } @@ -138,6 +142,7 @@ public class DefaultEditorTextRepresentationHelper implements EditorTextRepresen if (fontSize != key.fontSize) return false; if (fontType != key.fontType) return false; + if (c != key.c) return false; if (fontName != null ? !fontName.equals(key.fontName) : key.fontName != null) return false; return true; From 28b60e99a5ab606da9dd20149a7e856cbf8aba11 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 11 Aug 2010 18:34:42 +0400 Subject: [PATCH 31/36] JspPrefixRefactoringTest fixed --- .../impl/include/FileIncludeManagerImpl.java | 8 +++-- .../fixtures/CodeInsightTestFixture.java | 4 +-- .../impl/CodeInsightTestFixtureImpl.java | 19 ++++++------ .../source/xml/SchemaPrefixReference.java | 29 ++++++++----------- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java index b15bbcc6829a..f6aac4d73e26 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java @@ -22,6 +22,7 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFileWithId; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; @@ -34,7 +35,6 @@ import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.ParameterizedCachedValue; import com.intellij.psi.util.ParameterizedCachedValueProvider; -import com.intellij.util.ArrayUtil; import com.intellij.util.Processor; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.MultiMap; @@ -222,7 +222,11 @@ public class FileIncludeManagerImpl extends FileIncludeManager { public CachedValueProvider.Result compute(PsiFile param) { VirtualFile[] value = computeFiles(param, myRuntimeOnly); // todo: we need "url modification tracker" for VirtualFile - return CachedValueProvider.Result.create(value, ArrayUtil.append(value, param.getVirtualFile())); + Object[] deps = new Object[value.length + 2]; + deps[deps.length - 2] = param.getVirtualFile(); + deps[deps.length - 1] = VirtualFileManager.getInstance(); + + return CachedValueProvider.Result.create(value, deps); } } } diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java index 915da014fdea..b329ec8ace4d 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java @@ -207,7 +207,7 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture { */ void launchAction(@NotNull IntentionAction action); - void configureByFile(@TestDataFile @NonNls String file); + PsiFile configureByFile(@TestDataFile @NonNls String file); void configureByFiles(@NonNls String... files); @@ -305,7 +305,7 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture { void performEditorAction(String actionId); - int configureFromTempProjectFile(String filePath); + PsiFile configureFromTempProjectFile(String filePath); void configureFromExistingVirtualFile(VirtualFile f); diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index 51826773cf31..9ae07411d9fd 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -661,7 +661,8 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig new WriteCommandAction.Simple(project) { protected void run() throws Exception { - final int offset = configureByFilesInner(filePath); + configureByFilesInner(filePath); + int offset = myEditor.getCaretModel().getOffset(); final Collection infos = doHighlighting(); for (HighlightInfo info :infos) { @@ -945,7 +946,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig super.tearDown(); } - private int configureByFilesInner(@NonNls String... filePaths) throws IOException { + private PsiFile configureByFilesInner(@NonNls String... filePaths) throws IOException { assertInitialized(); myFile = null; myEditor = null; @@ -955,13 +956,14 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig return configureByFileInner(filePaths[0]); } - public void configureByFile(final String file) { + public PsiFile configureByFile(final String file) { assertInitialized(); new WriteCommandAction.Simple(getProject()) { protected void run() throws Exception { configureByFilesInner(file); } }.execute(); + return myFile; } public void configureByFiles(@NonNls final String... files) { @@ -1026,16 +1028,15 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig /** * * @param filePath - * @return caret offset or -1 if caret marker does not present * @throws IOException */ - private int configureByFileInner(@NonNls String filePath) { + private PsiFile configureByFileInner(@NonNls String filePath) { assertInitialized(); final VirtualFile file = copyFileToProject(filePath); return configureByFileInner(file); } - public int configureFromTempProjectFile(final String filePath) { + public PsiFile configureFromTempProjectFile(final String filePath) { return configureByFileInner(findFileInTempDir(filePath)); } @@ -1043,11 +1044,11 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig configureByFileInner(f); } - private int configureByFileInner(final VirtualFile copy) { + private PsiFile configureByFileInner(final VirtualFile copy) { return configureInner(copy, SelectionAndCaretMarkupLoader.fromFile(copy, getProject())); } - private int configureInner(@NotNull final VirtualFile copy, final SelectionAndCaretMarkupLoader loader) { + private PsiFile configureInner(@NotNull final VirtualFile copy, final SelectionAndCaretMarkupLoader loader) { assertInitialized(); try { final OutputStream outputStream = copy.getOutputStream(null, 0, 0); @@ -1077,7 +1078,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig } } - return offset; + return myFile; } private static void setContext(final PsiFile file, final PsiElement context) { diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/SchemaPrefixReference.java b/xml/impl/src/com/intellij/psi/impl/source/xml/SchemaPrefixReference.java index 8ef432759162..3148d68d2817 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/xml/SchemaPrefixReference.java +++ b/xml/impl/src/com/intellij/psi/impl/source/xml/SchemaPrefixReference.java @@ -16,7 +16,6 @@ package com.intellij.psi.impl.source.xml; import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.openapi.util.NullableLazyValue; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReferenceBase; @@ -36,21 +35,7 @@ import org.jetbrains.annotations.Nullable; */ public class SchemaPrefixReference extends PsiReferenceBase implements PossiblePrefixReference { - private final NullableLazyValue myPrefix = new NullableLazyValue() { - @Override - protected SchemaPrefix compute() { - if (myElement instanceof XmlAttribute && (((XmlAttribute)myElement).isNamespaceDeclaration())) { - return new SchemaPrefix((XmlAttribute)myElement, getRangeInElement(), myName); - } - else if (myElement instanceof XmlAttributeValue && - ((XmlAttribute)((XmlAttributeValue)myElement).getParent()).getLocalName().equals("prefix")) { - return SchemaPrefix.createJspPrefix((XmlAttributeValue)SchemaPrefixReference.this.myElement, myName); - } - else { - return resolvePrefix(myElement, myName); - } - } - }; + private final SchemaPrefix myPrefix; private final String myName; @Nullable @@ -67,6 +52,16 @@ public class SchemaPrefixReference extends PsiReferenceBase implemen super(element, range, true); myName = name; myTagNameReference = tagNameReference; + if (myElement instanceof XmlAttribute && (((XmlAttribute)myElement).isNamespaceDeclaration())) { + myPrefix = new SchemaPrefix((XmlAttribute)myElement, getRangeInElement(), myName); + } + else if (myElement instanceof XmlAttributeValue && + ((XmlAttribute)((XmlAttributeValue)myElement).getParent()).getLocalName().equals("prefix")) { + myPrefix = SchemaPrefix.createJspPrefix((XmlAttributeValue)myElement, myName); + } + else { + myPrefix = null; + } } public String getNamespacePrefix() { @@ -74,7 +69,7 @@ public class SchemaPrefixReference extends PsiReferenceBase implemen } public SchemaPrefix resolve() { - return myPrefix.getValue(); + return myPrefix == null ? resolvePrefix(myElement, myName) : myPrefix; } @NotNull From 777824a3e5e36e0fb89d8e422db2f9075df26a1d Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 11 Aug 2010 21:05:02 +0400 Subject: [PATCH 32/36] VCS: support renames in show diff for annotation - for SVN only for now --- .../openapi/vcs/CommittedChangesProvider.java | 6 +- .../vcs/actions/AnnotateToggleAction.java | 12 ++- .../CompositeCommittedChangesProvider.java | 3 +- .../CvsCommittedChangesProvider.java | 9 +- .../GitCommittedChangeListProvider.java | 9 +- .../HgCachingCommitedChangesProvider.java | 10 +- .../history/SvnCommittedChangesProvider.java | 93 ++++++++++++++++--- 7 files changed, 114 insertions(+), 28 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/CommittedChangesProvider.java b/platform/vcs-api/src/com/intellij/openapi/vcs/CommittedChangesProvider.java index 9aa5d7f829c8..4a035ad82c81 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/CommittedChangesProvider.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/CommittedChangesProvider.java @@ -16,6 +16,7 @@ package com.intellij.openapi.vcs; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.changes.committed.DecoratorManager; import com.intellij.openapi.vcs.changes.committed.VcsCommittedListsZipper; import com.intellij.openapi.vcs.changes.committed.VcsCommittedViewAuxiliary; @@ -58,6 +59,9 @@ public interface CommittedChangesProvider getOneList(final VirtualFile file, final VcsRevisionNumber number) throws VcsException; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java index c7cfd812ee67..1b4b3afb7d75 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java @@ -38,6 +38,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; @@ -526,13 +527,16 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware { if (revisionNumber != null) { final VcsException[] exc = new VcsException[1]; final List changes = new LinkedList(); + final FilePath[] targetPath = new FilePath[1]; ProgressManager.getInstance().run(new Task.Backgroundable(myVcs.getProject(), "Loading revision " + revisionNumber.asString() + " contents", true, BackgroundFromStartOption.getInstance()) { @Override public void run(@NotNull ProgressIndicator indicator) { final CommittedChangesProvider provider = myVcs.getCommittedChangesProvider(); try { - final CommittedChangeList cl = provider.getOneList(myFile, revisionNumber); + final Pair pair = provider.getOneList(myFile, revisionNumber); + targetPath[0] = pair.getSecond() == null ? new FilePathImpl(myFile) : pair.getSecond(); + final CommittedChangeList cl = pair.getFirst(); if (cl == null) { ChangesViewBalloonProblemNotifier.showMe(myVcs.getProject(), "Can not load data for show diff", MessageType.ERROR); return; @@ -550,7 +554,7 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware { if (exc[0] != null) { ChangesViewBalloonProblemNotifier.showMe(myVcs.getProject(), "Can not show diff: " + exc[0].getMessage(), MessageType.ERROR); } else if (! changes.isEmpty()) { - int idx = findSelfInList(changes); + int idx = findSelfInList(changes, targetPath[0]); final ShowDiffUIContext context = new ShowDiffUIContext(true); context.setDiffNavigationContext(createDiffNavigationContext(actualNumber)); ShowDiffAction.showDiffForChange(changes.toArray(new Change[changes.size()]), idx, myVcs.getProject(), context); @@ -560,9 +564,9 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware { } } - private int findSelfInList(List changes) { + private int findSelfInList(List changes, final FilePath filePath) { int idx = -1; - final File ioFile = new File(myFile.getPath()); + final File ioFile = filePath.getIOFile(); for (int i = 0; i < changes.size(); i++) { final Change change = changes.get(i); if ((change.getAfterRevision() != null) && (change.getAfterRevision().getFile().getIOFile().equals(ioFile))) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CompositeCommittedChangesProvider.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CompositeCommittedChangesProvider.java index 8b4c287f54f9..e5ef4df4c142 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CompositeCommittedChangesProvider.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CompositeCommittedChangesProvider.java @@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.changes.committed; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; @@ -154,7 +155,7 @@ public class CompositeCommittedChangesProvider implements CommittedChangesProvid } @Override - public CommittedChangeList getOneList(VirtualFile file, VcsRevisionNumber number) { + public Pair getOneList(VirtualFile file, VcsRevisionNumber number) { throw new UnsupportedOperationException(); } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java index 17ce14d514ef..a760cc3ec588 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java @@ -30,6 +30,7 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.ChangesUtil; import com.intellij.openapi.vcs.changes.committed.*; @@ -132,8 +133,10 @@ public class CvsCommittedChangesProvider implements CachingCommittedChangesProvi @Nullable @Override - public CvsChangeList getOneList(VirtualFile file, final VcsRevisionNumber number) throws VcsException { - CvsRepositoryLocation cvsLocation = (CvsRepositoryLocation) getLocationFor(new FilePathImpl(file)); + public Pair getOneList(VirtualFile file, final VcsRevisionNumber number) throws VcsException { + // todo implement in proper way + final FilePathImpl filePath = new FilePathImpl(file); + CvsRepositoryLocation cvsLocation = (CvsRepositoryLocation) getLocationFor(filePath); final String module = cvsLocation.getModuleName(); final CvsEnvironment connectionSettings = cvsLocation.getEnvironment(); if (connectionSettings.isOffline()) { @@ -162,7 +165,7 @@ public class CvsCommittedChangesProvider implements CachingCommittedChangesProvi else if (! executionResult.hasNoErrors()) { throw executionResult.composeError(); } - return result[0]; + return new Pair(result[0], filePath); } public List getCommittedChanges(ChangeBrowserSettings settings, RepositoryLocation location, final int maxCount) throws VcsException { diff --git a/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java b/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java index 0b15782eb351..3faed6261dc7 100644 --- a/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java +++ b/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java @@ -17,6 +17,7 @@ package git4idea.changes; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.committed.DecoratorManager; @@ -225,8 +226,10 @@ public class GitCommittedChangeListProvider implements CommittedChangesProvider< } @Override - public CommittedChangeList getOneList(VirtualFile file, final VcsRevisionNumber number) throws VcsException { - final GitRepositoryLocation l = (GitRepositoryLocation) getLocationFor(new FilePathImpl(file)); + public Pair getOneList(VirtualFile file, final VcsRevisionNumber number) throws VcsException { + // todo implement in proper way + final FilePathImpl filePath = new FilePathImpl(file); + final GitRepositoryLocation l = (GitRepositoryLocation) getLocationFor(filePath); VirtualFile root = LocalFileSystem.getInstance().findFileByIoFile(l.getRoot()); if (root == null) { throw new VcsException("The repository does not exists anymore: " + l.getRoot()); @@ -244,7 +247,7 @@ public class GitCommittedChangeListProvider implements CommittedChangesProvider< result[0] = committedChangeList; } }, false); - return result[0]; + return new Pair(result[0], filePath); } public int getFormatVersion() { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java index 156acceb9274..2356f8afd93f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java @@ -13,6 +13,7 @@ package org.zmlx.hg4idea.provider; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.actions.VcsContextFactory; import com.intellij.openapi.vcs.changes.Change; @@ -271,16 +272,17 @@ public class HgCachingCommitedChangesProvider } @Override - public CommittedChangeList getOneList(VirtualFile file, VcsRevisionNumber number) throws VcsException { + public Pair getOneList(VirtualFile file, VcsRevisionNumber number) throws VcsException { final ChangeBrowserSettings settings = createDefaultSettings(); settings.USE_CHANGE_AFTER_FILTER = true; settings.USE_CHANGE_BEFORE_FILTER = true; settings.CHANGE_AFTER = number.asString(); settings.CHANGE_BEFORE = number.asString(); - final List list = getCommittedChanges(settings, getLocationFor( - VcsContextFactory.SERVICE.getInstance().createFilePathOn(file)), 1); + // todo implement in proper way + final FilePath filePath = VcsContextFactory.SERVICE.getInstance().createFilePathOn(file); + final List list = getCommittedChanges(settings, getLocationFor(filePath), 1); if (list.size() == 1) { - return list.get(0); + return new Pair(list.get(0), filePath); } return null; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java index 84f9d8b7530e..71d287c954fa 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java @@ -26,6 +26,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ContentRevision; import com.intellij.openapi.vcs.changes.committed.*; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; @@ -39,12 +41,10 @@ import com.intellij.util.ThrowableConsumer; import com.intellij.util.containers.MultiMap; import com.intellij.util.messages.MessageBusConnection; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.SvnAuthenticationNotifier; -import org.jetbrains.idea.svn.SvnBundle; -import org.jetbrains.idea.svn.SvnUtil; -import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.*; import org.jetbrains.idea.svn.actions.ConfigureBranchesAction; import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.wc.SVNInfo; import org.tmatesoft.svn.core.wc.SVNLogClient; @@ -53,6 +53,7 @@ import org.tmatesoft.svn.core.wc.SVNWCClient; import java.io.DataInput; import java.io.DataOutput; +import java.io.File; import java.io.IOException; import java.util.*; @@ -491,7 +492,7 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi } @Override - public SvnChangeList getOneList(final VirtualFile file, VcsRevisionNumber number) throws VcsException { + public Pair getOneList(final VirtualFile file, VcsRevisionNumber number) throws VcsException { final VirtualFile root = ProjectLevelVcsManager.getInstance(myProject).getVcsRootFor(file); final SvnRepositoryLocation svnRootLocation = (SvnRepositoryLocation)getLocationFor(new FilePathImpl(root)); if (svnRootLocation == null) return null; @@ -508,13 +509,15 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi final SVNRevision revisionBefore; final SVNURL repositoryUrl; final SVNURL svnurl; + final SVNInfo targetInfo; try { logger = myVcs.createLogClient(); revisionBefore = SVNRevision.create(revision); svnurl = SVNURL.parseURIEncoded(url); final SVNWCClient client = myVcs.createWCClient(); - SVNInfo info = client.doInfo(svnurl, SVNRevision.UNDEFINED, SVNRevision.HEAD); + final SVNInfo info = client.doInfo(svnurl, SVNRevision.UNDEFINED, SVNRevision.HEAD); + targetInfo = client.doInfo(new File(file.getPath()), SVNRevision.WORKING); if (info == null) { throw new VcsException("Can not get repository URL"); } @@ -528,10 +531,71 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi if (result[0] == null) { tryByRoot(result, logger, revisionBefore, repositoryUrl); if (result[0] == null) { - tryStepByStep(svnRootLocation, result, logger, revisionBefore, repositoryUrl, svnurl); + FilePath path = tryStepByStep(svnRootLocation, result, logger, revisionBefore, targetInfo, svnurl); + path = path == null ? new FilePathImpl(file) : path; + // and pass & take rename context there + return new Pair(result[0], path); } } - return result[0]; + if (result[0].getChanges().size() == 1) { + final Collection changes = result[0].getChanges(); + final Change change = changes.iterator().next(); + final ContentRevision afterRevision = change.getAfterRevision(); + if (afterRevision != null) { + return new Pair(result[0], afterRevision.getFile()); + } else { + return new Pair(result[0], new FilePathImpl(file)); + } + } + String relativePath = SVNPathUtil.getRelativePath(targetInfo.getRepositoryRootURL().toString(), targetInfo.getURL().toString()); + relativePath = relativePath.startsWith("/") ? relativePath : "/" + relativePath; + final Change targetChange = result[0].getByPath(relativePath); + if (targetChange == null) { + FilePath path = tryStepByStep(svnRootLocation, result, logger, revisionBefore, targetInfo, svnurl); + path = path == null ? new FilePathImpl(file) : path; + // and pass & take rename context there + return new Pair(result[0], path); + } + return new Pair(result[0], new FilePathImpl(file)); + } + + private static class RenameContext { + private String myCurrentPath; + private String myRepositoryRoot; + private boolean myHadChanged; + + private RenameContext(final SVNInfo info) { + myRepositoryRoot = info.getRepositoryRootURL().toString(); + myCurrentPath = SVNPathUtil.getRelativePath(myRepositoryRoot, info.getURL().toString()); + myCurrentPath = myCurrentPath.startsWith("/") ? myCurrentPath : ("/" + myCurrentPath); + } + + public void accept(final SVNLogEntry entry) { + final Map changedPaths = entry.getChangedPaths(); + + for (Object o : changedPaths.values()) { + final SVNLogEntryPath entryPath = (SVNLogEntryPath) o; + if ('A' == entryPath.getType()) { + if (myCurrentPath.equals(entryPath.getPath())) { + myHadChanged = true; + myCurrentPath = entryPath.getCopyPath(); + } + } + } + } + + @Nullable + public FilePath getFilePath(final SvnVcs vcs) { + if (! myHadChanged) return null; + final SvnFileUrlMapping svnFileUrlMapping = vcs.getSvnFileUrlMapping(); + final String absolutePath = SVNPathUtil.append(myRepositoryRoot, myCurrentPath); + final String localPath = svnFileUrlMapping.getLocalPath(absolutePath); + if (localPath == null) { + LOG.info("Cannot find local path for url: " + absolutePath); + return null; + } + return new FilePathImpl(new File(localPath), false); + } } private void tryByRoot(SvnChangeList[] result, SVNLogClient logger, SVNRevision revisionBefore, SVNURL repositoryUrl) throws VcsException { @@ -540,13 +604,16 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi tryExactHit(new SvnRepositoryLocation(repositoryUrl.toString()), result, logger, revisionBefore, repositoryUrl, repositoryUrl); } - private void tryStepByStep(final SvnRepositoryLocation svnRepositoryLocation, + // return changed path, if any + private FilePath tryStepByStep(final SvnRepositoryLocation svnRepositoryLocation, final SvnChangeList[] result, SVNLogClient logger, - final SVNRevision revisionBefore, final SVNURL repositoryUrl, SVNURL svnurl) throws VcsException { + final SVNRevision revisionBefore, final SVNInfo info, SVNURL svnurl) throws VcsException { + final String repositoryRoot = info.getRepositoryRootURL().toString(); try { + final RenameContext renameContext = new RenameContext(info); logger.doLog(svnurl, null, SVNRevision.UNDEFINED, SVNRevision.HEAD, revisionBefore, - false, true, true, 0, null, + false, true, false, 0, null, new ISVNLogEntryHandler() { public void handleLogEntry(SVNLogEntry logEntry) { if (myProject.isDisposed()) throw new ProcessCanceledException(); @@ -554,11 +621,13 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi // do not add lists without info - this situation is possible for lists where there are paths that user has no rights to observe return; } + renameContext.accept(logEntry); if (logEntry.getRevision() == revisionBefore.getNumber()) { - result[0] = new SvnChangeList(myVcs, svnRepositoryLocation, logEntry, repositoryUrl.toString()); + result[0] = new SvnChangeList(myVcs, svnRepositoryLocation, logEntry, repositoryRoot); } } }); + return renameContext.getFilePath(myVcs); } catch (SVNException e) { throw new VcsException(e); From 663fe159ce5234225cb2313c888d7cc059103ee1 Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 11 Aug 2010 21:16:03 +0400 Subject: [PATCH 33/36] SVN: misleading "discovering location" due to not updated progress --- plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java index 4dc1cd824f24..331146cf3eae 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java @@ -317,7 +317,9 @@ public class SvnUtil { public Collection handleWorkingCopyRoot(File root, ProgressIndicator progress) { final Collection result = new HashSet(); + String oldText = null; if (progress != null) { + oldText = progress.getText(); progress.setText(SvnBundle.message("progress.text.discovering.location", root.getAbsolutePath())); } try { @@ -330,6 +332,9 @@ public class SvnUtil { catch (SVNException e) { // } + if (progress != null) { + progress.setText(oldText); + } return result; } } From f6a81850230d0c3468c30f645d89d502c1c52e83 Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Wed, 11 Aug 2010 23:50:16 +0400 Subject: [PATCH 34/36] table editor: incons & speedsearch fixes --- .../com/intellij/ui/table/TableHeaderRenderer.java | 5 ++++- .../src/com/intellij/ui/table/TableView.java | 11 +++++++++-- .../util/src/com/intellij/util/ui/ColumnInfo.java | 5 +++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/table/TableHeaderRenderer.java b/platform/platform-api/src/com/intellij/ui/table/TableHeaderRenderer.java index b631be29833d..c55057995798 100644 --- a/platform/platform-api/src/com/intellij/ui/table/TableHeaderRenderer.java +++ b/platform/platform-api/src/com/intellij/ui/table/TableHeaderRenderer.java @@ -22,6 +22,7 @@ import com.intellij.util.ui.UIUtil; import javax.swing.*; import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; import javax.swing.table.JTableHeader; import javax.swing.table.TableCellRenderer; import java.awt.*; @@ -81,7 +82,9 @@ public class TableHeaderRenderer extends JPanel implements TableCellRenderer{ icon = IconLoader.getIcon("/actions/sortDesc.png"); } } - + final Icon columnIcon = columnInfo.getIcon(); + myLabel.setIcon(columnIcon); + myLabel.setIconTextGap(10); setText(labelString); setIcon(icon); setToolTipText(columnInfo.getTooltipText()); diff --git a/platform/platform-api/src/com/intellij/ui/table/TableView.java b/platform/platform-api/src/com/intellij/ui/table/TableView.java index 3fcfd98ad7f3..30973f38dc3e 100644 --- a/platform/platform-api/src/com/intellij/ui/table/TableView.java +++ b/platform/platform-api/src/com/intellij/ui/table/TableView.java @@ -26,9 +26,11 @@ import javax.swing.*; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.*; +import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.*; +import java.util.List; public class TableView extends BaseTableView implements ItemsProvider, SelectionProvider { public TableView() { @@ -115,8 +117,11 @@ public class TableView extends BaseTableView implements ItemsProvider, Sel public void updateColumnSizes() { ColumnInfo[] columns = getListTableModel().getColumnInfos(); for (int i = 0; i < columns.length; i++) { - ColumnInfo columnInfo = columns[i]; - TableColumn column = getColumnModel().getColumn(i); + final ColumnInfo columnInfo = columns[i]; + final TableColumn column = getColumnModel().getColumn(i); + final Component headerComponent = + getTableHeader().getDefaultRenderer().getTableCellRendererComponent(this, column.getHeaderValue(), false, false, 0, 0); + final Dimension headerSize = headerComponent.getPreferredSize(); final String maxStringValue; final String preferredValue; if (columnInfo.getWidth(this) > 0) { @@ -126,11 +131,13 @@ public class TableView extends BaseTableView implements ItemsProvider, Sel } else if ((maxStringValue = columnInfo.getMaxStringValue()) != null) { int width = getFontMetrics(getFont()).stringWidth(maxStringValue) + columnInfo.getAdditionalWidth(); + width = Math.max(width, headerSize.width); column.setPreferredWidth(width); column.setMaxWidth(width); } else if ((preferredValue = columnInfo.getPreferredStringValue()) != null) { int width = getFontMetrics(getFont()).stringWidth(preferredValue) + columnInfo.getAdditionalWidth(); + width = Math.max(width, headerSize.width); column.setPreferredWidth(width); } } diff --git a/platform/util/src/com/intellij/util/ui/ColumnInfo.java b/platform/util/src/com/intellij/util/ui/ColumnInfo.java index 9dcabc090d4b..3945f6d076c5 100644 --- a/platform/util/src/com/intellij/util/ui/ColumnInfo.java +++ b/platform/util/src/com/intellij/util/ui/ColumnInfo.java @@ -44,6 +44,11 @@ public abstract class ColumnInfo { myName = name; } + @Nullable + public Icon getIcon() { + return null; + } + public String toString() { return getName(); } From 4391629d5bd06fe6262417f166dc10ee7e774e83 Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 11 Aug 2010 14:20:56 +0400 Subject: [PATCH 35/36] ant generation for artifacts: 'zip' task generated for non-jar archives --- .../impl/elements/ArchivePackagingElement.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ArchivePackagingElement.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ArchivePackagingElement.java index 0d5aa8214d72..c633f9448058 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ArchivePackagingElement.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ArchivePackagingElement.java @@ -17,17 +17,19 @@ package com.intellij.packaging.impl.elements; import com.intellij.compiler.ant.BuildProperties; import com.intellij.compiler.ant.Generator; +import com.intellij.compiler.ant.Tag; import com.intellij.compiler.ant.artifacts.ArchiveAntCopyInstructionCreator; import com.intellij.compiler.ant.taskdefs.Jar; +import com.intellij.compiler.ant.taskdefs.Zip; import com.intellij.packaging.artifacts.ArtifactType; import com.intellij.packaging.elements.*; import com.intellij.packaging.impl.ui.ArchiveElementPresentation; -import com.intellij.packaging.ui.PackagingElementPresentation; import com.intellij.packaging.ui.ArtifactEditorContext; -import com.intellij.util.xmlb.annotations.Attribute; +import com.intellij.packaging.ui.PackagingElementPresentation; import com.intellij.util.xmlb.XmlSerializerUtil; -import org.jetbrains.annotations.NotNull; +import com.intellij.util.xmlb.annotations.Attribute; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import java.util.Collections; import java.util.List; @@ -58,7 +60,13 @@ public class ArchivePackagingElement extends CompositeElementWithManifest Date: Thu, 12 Aug 2010 10:39:58 +0400 Subject: [PATCH 36/36] WI-2195: PHP debug: Watches view: commands to add and remove a watch could be added to context menu --- platform/platform-resources/src/idea/LangActions.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 1e24656bd38f..6b8802cf6fbd 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -671,6 +671,8 @@ + +