Merge remote-tracking branch 'origin/master' phpstorm/134.1377
authorVladimir Orlov <vladimir.orlov@jetbrains.com>
Sat, 1 Mar 2014 08:57:18 +0000 (12:57 +0400)
committerVladimir Orlov <vladimir.orlov@jetbrains.com>
Sat, 1 Mar 2014 08:57:18 +0000 (12:57 +0400)
196 files changed:
.idea/libraries/Netty.xml
java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java
java/debugger/impl/src/com/intellij/debugger/engine/evaluation/TextWithImportsImpl.java
java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java
java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java
java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaFieldBreakpointType.java
java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaLineBreakpointTypeBase.java
java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaMethodBreakpointType.java
java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeTypeArgumentsFix.java
java/java-analysis-impl/src/com/intellij/codeInsight/intention/AddAnnotationPsiFix.java
java/java-analysis-impl/src/com/intellij/codeInsight/intention/impl/AddNullableNotNullAnnotationFix.java
java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToCatchFix.java
java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java
java/java-impl/src/com/intellij/codeInsight/intention/impl/AddAnnotationIntention.java
java/java-impl/src/com/intellij/codeInspection/dataFlow/EditContractIntention.java
java/java-impl/src/com/intellij/refactoring/changeClassSignature/ChangeClassSignatureProcessor.java
java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassProcessor.java
java/java-impl/src/com/intellij/refactoring/inlineSuperClass/usageInfo/ReplaceWithSubtypeUsageInfo.java
java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java
java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeElementImpl.java
java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java
java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSharedImplUtil.java
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnsupportedFeatures7.java
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/typeAnnotations.java
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/Variance.java
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/LiftedCaptureToOuterCall.java [new file with mode: 0644]
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/LambdaFormalParamTypesParametrization.java [new file with mode: 0644]
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/NonWildcardParametrization.java [new file with mode: 0644]
java/java-tests/testSrc/com/intellij/codeInsight/AddAnnotationFixTest.java
java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java
java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalTypeWildcardParameterizationTest.java [new file with mode: 0644]
java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java
java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
jps/jps-builders/src/org/jetbrains/jps/ModuleChunk.java
jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java
jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CompilerMessage.java
lib/netty-all-5.0.0.Alpha2.jar [moved from lib/netty-all-5.0.0.Alpha1.jar with 62% similarity]
lib/required_for_dist.txt
lib/src/netty-all-5.0.0.Alpha2-sources.jar [moved from lib/src/netty-all-5.0.0.Alpha1-sources.jar with 68% similarity]
platform/core-api/src/com/intellij/openapi/editor/colors/CodeInsightColors.java
platform/core-api/src/com/intellij/openapi/vfs/encoding/EncodingRegistry.java
platform/core-api/src/com/intellij/util/PlatformUtilsCore.java
platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java
platform/editor-ui-ex/src/com/intellij/injected/editor/MarkupModelWindow.java
platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/MarkupModelEx.java
platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/EmptyMarkupModel.java
platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java
platform/lang-impl/src/com/intellij/execution/actions/StopProcessAction.java
platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java [new file with mode: 0644]
platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java
platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java
platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java [moved from platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectLastOccurrenceAction.java with 93% similarity]
platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeFactory.java
platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java
platform/lang-impl/src/com/intellij/openapi/file/exclude/PersistentFileSetManager.java
platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandlerWorker.java
platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java
platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java
platform/platform-api/src/com/intellij/openapi/diff/SimpleContent.java
platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonUI.java
platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaToggleButtonUI.java [new file with mode: 0644]
platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties
platform/platform-impl/src/com/intellij/openapi/diff/actions/DiffPanelComboBoxAction.java [new file with mode: 0644]
platform/platform-impl/src/com/intellij/openapi/diff/actions/HighlightModeAction.java
platform/platform-impl/src/com/intellij/openapi/diff/actions/IgnoreWhiteSpacesAction.java
platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffUtil.java
platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/FragmentedDiffPanelState.java
platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/PresetBlocksDiffPolicy.java
platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java
platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeList.java
platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java
platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/PreferWholeLines.java
platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/TextCompareProcessor.java
platform/platform-impl/src/com/intellij/openapi/diff/impl/splitter/DividerPolygon.java
platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java
platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentialsHolder.java
platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkCredentials.java
platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkCredentialsHolder.java
platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkProperties.java
platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkPropertiesHolder.java
platform/platform-impl/src/com/intellij/remotesdk2/RemoteConnectionCredentialsWrapper.java [new file with mode: 0644]
platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkAdditionalData2.java
platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
platform/platform-impl/src/com/intellij/remotesdk2/VagrantBasedCredentialsHolder.java [new file with mode: 0644]
platform/platform-impl/src/com/intellij/remotesdk2/WebDeploymentCredentialsHolder.java [new file with mode: 0644]
platform/platform-impl/src/org/jetbrains/ide/BuiltInServerManagerImpl.java
platform/platform-resources-en/src/messages/ActionsBundle.properties
platform/platform-resources-en/src/messages/DiffBundle.properties
platform/platform-resources/src/DefaultColorSchemesManager.xml
platform/platform-resources/src/idea/Keymap_Default.xml
platform/platform-resources/src/idea/Keymap_Eclipse.xml
platform/platform-resources/src/idea/Keymap_Mac.xml
platform/platform-resources/src/idea/Keymap_MacClassic.xml
platform/platform-resources/src/idea/PlatformActions.xml
platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/IgnoreWhiteSpaceTest.java
platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/highlighting/UtilTest.java
platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/processing/LineBlocksDiffPolicyTest.java
platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/processing/TextCompareProcessorTest.java
platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/SelectUnselectOccurrenceActionsTest.java
platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/EnforcedPlaintTextFileTypeManagerTest.java [new file with mode: 0644]
platform/util/src/com/intellij/openapi/diff/LineTokenizer.java
platform/util/src/com/intellij/openapi/diff/LineTokenizerBase.java [new file with mode: 0644]
platform/util/src/com/intellij/openapi/diff/ex/DiffFragment.java
platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java
platform/util/src/com/intellij/openapi/diff/impl/DiffFragmentBuilder.java
platform/util/src/com/intellij/openapi/diff/impl/fragments/LineFragment.java
platform/util/src/com/intellij/openapi/diff/impl/highlighting/FragmentSide.java
platform/util/src/com/intellij/openapi/diff/impl/highlighting/Util.java
platform/util/src/com/intellij/openapi/diff/impl/processing/ByWord.java
platform/util/src/com/intellij/openapi/diff/impl/processing/DiffCorrection.java
platform/util/src/com/intellij/openapi/diff/impl/processing/DiffPolicy.java
platform/util/src/com/intellij/openapi/diff/impl/processing/Formatting.java
platform/util/src/com/intellij/openapi/diff/impl/processing/LineFragmentsCollector.java
platform/util/src/com/intellij/openapi/diff/impl/processing/UniteSameType.java
platform/util/src/com/intellij/openapi/diff/impl/processing/Word.java
platform/util/src/com/intellij/openapi/diff/impl/string/DiffString.java [new file with mode: 0644]
platform/util/src/com/intellij/openapi/diff/impl/string/DiffStringBuilder.java [new file with mode: 0644]
platform/util/src/com/intellij/openapi/util/JDOMExternalizer.java
platform/util/src/com/intellij/util/diff/PatienceIntLCS.java
platform/util/src/com/intellij/util/xmlb/TextBinding.java
platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java
platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/TextPatchBuilder.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java
plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpectedTypeUtils.java
plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SharedThreadLocalRandomInspection.java [new file with mode: 0644]
plugins/InspectionGadgets/src/inspectionDescriptions/SharedThreadLocalRandom.html [new file with mode: 0644]
plugins/InspectionGadgets/src/inspectionDescriptions/ThreadLocalNotStaticFinal.html
plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_unboxing/AutoUnboxing.java
plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_unboxing/expected.xml
plugins/InspectionGadgets/test/com/siyeh/igtest/naming/method_names_differ_only_by_case/expected.xml
plugins/InspectionGadgets/testsrc/com/siyeh/ig/threading/SharedThreadLocalRandomInspectionTest.java [new file with mode: 0644]
plugins/IntelliLang/src/META-INF/plugin.xml
plugins/devkit/src/references/IconsReferencesContributor.java
plugins/eclipse/resources/META-INF/plugin.xml
plugins/github/src/META-INF/plugin.xml
plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java
plugins/github/src/org/jetbrains/plugins/github/GithubCreatePullRequestWorker.java
plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java
plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java
plugins/github/src/org/jetbrains/plugins/github/extensions/GithubHttpAuthDataProvider.java
plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
plugins/github/src/org/jetbrains/plugins/github/ui/GithubBasicLoginDialog.java
plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginDialog.java
plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java
plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthDataHolder.java [new file with mode: 0644]
plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java
plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java
plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTest.java
plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java
plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovycOSProcessHandler.java
plugins/groovy/test/org/jetbrains/plugins/groovy/FastGroovyTestSuite.java
plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GppCompilerTest.groovy [deleted file]
plugins/javaFX/javaFX-CE/src/META-INF/plugin.xml
plugins/junit/src/META-INF/plugin.xml
plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/RemoveManagedFilesAction.java
plugins/maven/src/main/resources/META-INF/plugin.xml
plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesFileType.java
plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsInstrumenter.java
python/ide/src/com/jetbrains/python/configuration/PythonContentEntriesConfigurable.java
python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java
python/psi-api/src/com/jetbrains/python/PythonFileType.java
python/resources/icons/com/jetbrains/python/skeleton.png [deleted file]
python/resources/icons/com/jetbrains/python/skeleton@2x.png [deleted file]
python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java
python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
python/src/com/jetbrains/python/inspections/PyByteLiteralInspection.java
python/src/com/jetbrains/python/inspections/PyMandatoryEncodingInspection.java
python/src/com/jetbrains/python/inspections/PyNonAsciiCharInspection.java
python/src/com/jetbrains/python/inspections/PyPep8NamingInspection.java
python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java
python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java
python/src/com/jetbrains/python/sdk/PythonSdkAdditionalData.java
python/src/icons/PythonIcons.java
python/testSrc/com/jetbrains/python/PyEncodingTest.java
xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java

index 8037545021dc9c1f4fdd321264a0ec988755b053..bc6600b3242d0ba1fb40aafbd2c2e617ba23f8ea 100644 (file)
@@ -1,11 +1,11 @@
 <component name="libraryTable">
   <library name="Netty">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/lib/netty-all-5.0.0.Alpha1.jar!/" />
+      <root url="jar://$PROJECT_DIR$/lib/netty-all-5.0.0.Alpha2.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="jar://$PROJECT_DIR$/lib/src/netty-all-5.0.0.Alpha1-sources.jar!/" />
+      <root url="jar://$PROJECT_DIR$/lib/src/netty-all-5.0.0.Alpha2-sources.jar!/" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
index 9e89f13c79c0d134d2b0b80076a4477270f1bbe8..5b208a6d165eb16f77f897fa37e3e925e6fcd4bf 100644 (file)
@@ -197,6 +197,9 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
       }
       FileUtil.createIfDoesntExist(CompilerPaths.getRebuildMarkerFile(project));
       --myWatchedProjectsCount;
+      if (ourDebugMode) {
+        System.out.println("After suspend for project:"+projectId + "," + myWatchedProjectsCount);
+      }
       // cleanup internal structures to free memory
       mySourcesToRecompile.remove(projectId);
       myOutputsToDelete.remove(projectId);
@@ -217,8 +220,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
 
   public void watchProject(Project project) {
     synchronized (myDataLock) {
-      mySuspendedProjects.remove(getProjectId(project));
+      int projectId = getProjectId(project);
+      mySuspendedProjects.remove(projectId);
       ++myWatchedProjectsCount;
+      if (ourDebugMode) {
+        System.out.println("After watch for project:"+projectId + "," + myWatchedProjectsCount);
+      }
     }
   }
 
index f52100aec91ba0e82e398721ea73bf38c2fb1aba..4eda8984e285fd1310fde5e35c42996b6d29f598 100644 (file)
@@ -69,10 +69,7 @@ public final class TextWithImportsImpl implements TextWithImports{
   }
 
   private static Trinity<String, String, FileType> parseExternalForm(String s) {
-    // when serialized into a tag special symbols are now kept as is
-    // so our separator \r may be converted to \n or \r\n
-    s = StringUtil.convertLineSeparators(s);
-    String[] split = s.split("\n");
+    String[] split = s.split(String.valueOf(DebuggerEditorImpl.SEPARATOR));
     return Trinity.create(split[0], split.length > 1 ? split[1] : "", split.length > 2 ? FileTypeManager.getInstance().getStdFileType(split[2]) : null);
   }
 
index 5fadb64b8f9a8ccf7fb9982be26eee1e85779ce7..c682325b2366e6b50ecf22f1e8a85b5c2ef8d488 100644 (file)
@@ -587,6 +587,9 @@ public class BreakpointManager {
     breakpoint.updateUI();
     RequestManagerImpl.createRequests(breakpoint);
     myDispatcher.getMulticaster().breakpointsChanged();
+    if (breakpoint instanceof MethodBreakpoint || breakpoint instanceof WildcardMethodBreakpoint) {
+      XDebugSessionImpl.NOTIFICATION_GROUP.createNotification("Method breakpoints may dramatically slow down debugging", MessageType.WARNING).notify(myProject);
+    }
   }
 
   private synchronized void onBreakpointAdded(XBreakpoint xBreakpoint) {
@@ -917,6 +920,7 @@ public class BreakpointManager {
   private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
   public void fireBreakpointChanged(Breakpoint breakpoint) {
     breakpoint.reload();
+    breakpoint.updateUI();
     RequestManagerImpl.updateRequests(breakpoint);
     if (myAllowMulticasting) {
       // can be invoked from non-AWT thread
index a1c2df838e65e8c97b9ea10b88ce4ba958817faa..16d031a7d3090f628f314357cd8ef954db017fb7 100644 (file)
@@ -383,7 +383,7 @@ public abstract class BreakpointWithHighlighter<P extends JavaBreakpointProperti
     if (myVisible) {
       if (isValid()) {
         final XBreakpointManager breakpointManager = XDebuggerManager.getInstance(myProject).getBreakpointManager();
-        breakpointManager.updateBreakpointPresentation((XLineBreakpoint)myXBreakpoint, getIcon(), getDescription());
+        breakpointManager.updateBreakpointPresentation((XLineBreakpoint)myXBreakpoint, getIcon(), null);
       }
       //RangeHighlighter highlighter = myHighlighter;
       //if (highlighter != null && highlighter.isValid() && isValid()) {
index 66b8284ae4cb3e1ab9429457eb9beedf82b28512..74a6f2df61ccf4eed084b9dbcdebe432987f269a 100644 (file)
@@ -70,11 +70,10 @@ public class JavaFieldBreakpointType extends JavaLineBreakpointTypeBase<JavaFiel
 
   @Override
   public String getShortText(XLineBreakpoint<JavaFieldBreakpointProperties> breakpoint) {
-    return getDisplayText(breakpoint);
+    return getText(breakpoint);
   }
 
-  @Override
-  public String getDisplayText(XLineBreakpoint<JavaFieldBreakpointProperties> breakpoint) {
+  public String getText(XLineBreakpoint<JavaFieldBreakpointProperties> breakpoint) {
     //if(!isValid()) {
     //  return DebuggerBundle.message("status.breakpoint.invalid");
     //}
index b9d68e3b56a819e7672e217db632c743b7ad15b0..14d7bf4bcd22b07763f7d2e1536c7ec169c1d7a5 100644 (file)
@@ -15,7 +15,9 @@
  */
 package com.intellij.debugger.ui.breakpoints;
 
+import com.intellij.debugger.DebuggerManagerEx;
 import com.intellij.debugger.engine.DebuggerUtils;
+import com.intellij.debugger.ui.JavaDebuggerSupport;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.fileTypes.FileType;
@@ -70,6 +72,18 @@ public abstract class JavaLineBreakpointTypeBase<P extends JavaBreakpointPropert
     return new JavaDebuggerEditorsProvider();
   }
 
+  @Override
+  public String getDisplayText(XLineBreakpoint<P> breakpoint) {
+    BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(JavaDebuggerSupport.getCurrentProject()).getBreakpointManager();
+      BreakpointWithHighlighter javaBreakpoint = (BreakpointWithHighlighter)breakpointManager.findBreakpoint(breakpoint);
+      if (javaBreakpoint != null) {
+        return javaBreakpoint.getDescription();
+      }
+      else {
+        return super.getDisplayText(breakpoint);
+      }
+  }
+
   @Override
   public final boolean canPutAt(@NotNull VirtualFile file, final int line, @NotNull Project project) {
     PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
index 3e4afd7ac5cb0aec71b6a84e8078e2f92998d6a2..94c3c77d80ce9db1a3cc2acfb415d1323096b50e 100644 (file)
@@ -68,11 +68,6 @@ public class JavaMethodBreakpointType extends JavaLineBreakpointTypeBase<JavaMet
 
   @Override
   public String getShortText(XLineBreakpoint<JavaMethodBreakpointProperties> breakpoint) {
-    return getDisplayText(breakpoint);
-  }
-
-  @Override
-  public String getDisplayText(XLineBreakpoint<JavaMethodBreakpointProperties> breakpoint) {
     return getText(breakpoint);
   }
 
index 4e9d79fecf57cab0a24c9a8224213c00057d85d6..352e74557eed4eee4d6bec70bd238be86e458724 100644 (file)
@@ -1324,8 +1324,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
     myHolder.add(GenericsHighlightUtil.checkParametersAllowed(list, myLanguageLevel,myFile));
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkParametersOnRaw(list));
     if (!myHolder.hasErrorResults()) {
-      for (PsiType type : list.getTypeArguments()) {
-        myHolder.add(HighlightUtil.checkDiamondFeature(type, list, myLanguageLevel,myFile));
+      for (PsiTypeElement typeElement : list.getTypeParameterElements()) {
+        myHolder.add(HighlightUtil.checkDiamondFeature(typeElement.getType(), list, myLanguageLevel,myFile));
       }
     }
   }
index 76580adaa5f4a3a3eb6056368599098436a094d4..b4a8d5b99d1752e8bfc8ece44716ec5deee1e434 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-/**
- * Created by IntelliJ IDEA.
- * User: cdr
- * Date: Nov 13, 2002
- * Time: 3:26:50 PM
- * To change this template use Options | File Templates.
- */
 package com.intellij.codeInsight.daemon.impl.quickfix;
 
 import com.intellij.codeInsight.FileModificationService;
@@ -32,6 +24,7 @@ import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.TypeConversionUtil;
@@ -39,11 +32,18 @@ import com.intellij.util.Function;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import static com.intellij.util.ObjectUtils.assertNotNull;
+
+/**
+ * @author cdr
+ * @since Nov 13, 2002
+ */
 public class ChangeTypeArgumentsFix implements IntentionAction, HighPriorityAction {
+  private static final Logger LOG = Logger.getInstance("#" + ChangeTypeArgumentsFix.class.getName());
+
   private final PsiMethod myTargetMethod;
   private final PsiClass myPsiClass;
   private final PsiExpression[] myExpressions;
-  private static final Logger LOG = Logger.getInstance("#" + ChangeTypeArgumentsFix.class.getName());
   private final PsiNewExpression myNewExpression;
 
   ChangeTypeArgumentsFix(@NotNull PsiMethod targetMethod,
@@ -116,11 +116,12 @@ public class ChangeTypeArgumentsFix implements IntentionAction, HighPriorityActi
     LOG.assertTrue(reference != null, myNewExpression);
     final PsiReferenceParameterList parameterList = reference.getParameterList();
     LOG.assertTrue(parameterList != null, myNewExpression);
+    PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
     PsiTypeElement[] elements = parameterList.getTypeParameterElements();
     for (int i = elements.length - 1; i >= 0; i--) {
-      PsiTypeElement typeElement = elements[i];
-      final PsiType typeArg = psiSubstitutor.substitute(typeParameters[i]);
-      typeElement.replace(JavaPsiFacade.getElementFactory(project).createTypeElement(typeArg));
+      PsiType typeArg = assertNotNull(psiSubstitutor.substitute(typeParameters[i]));
+      PsiElement replaced = elements[i].replace(factory.createTypeElement(typeArg));
+      JavaCodeStyleManager.getInstance(file.getProject()).shortenClassReferences(replaced);
     }
   }
 
index 987f02dc9c39807dbd3b3cdcb1c16bfa0feeb244..84f704f64dcd29f5bebc731f4fc5e2572cad8ed5 100644 (file)
@@ -64,15 +64,25 @@ public class AddAnnotationPsiFix extends LocalQuickFixOnPsiElement {
   }
 
   @Nullable
-  public static PsiModifierListOwner getContainer(final PsiElement element) {
-    PsiModifierListOwner listOwner = PsiTreeUtil.getParentOfType(element, PsiParameter.class, false);
-    if (listOwner == null) {
-      final PsiIdentifier psiIdentifier = PsiTreeUtil.getParentOfType(element, PsiIdentifier.class, false);
-      if (psiIdentifier != null && psiIdentifier.getParent() instanceof PsiModifierListOwner) {
-        listOwner = (PsiModifierListOwner)psiIdentifier.getParent();
+  public static PsiModifierListOwner getContainer(final PsiFile file, int offset) {
+    PsiReference reference = file.findReferenceAt(offset);
+    if (reference != null) {
+      PsiElement target = reference.resolve();
+      if (target instanceof PsiMember) {
+        return (PsiMember)target;
       }
     }
-    return listOwner;
+
+    PsiElement element = file.findElementAt(offset);
+
+    PsiModifierListOwner listOwner = PsiTreeUtil.getParentOfType(element, PsiParameter.class, false);
+    if (listOwner != null) return listOwner;
+
+    final PsiIdentifier psiIdentifier = PsiTreeUtil.getParentOfType(element, PsiIdentifier.class, false);
+    if (psiIdentifier != null && psiIdentifier.getParent() instanceof PsiModifierListOwner) {
+      return (PsiModifierListOwner)psiIdentifier.getParent();
+    }
+    return null;
   }
 
   @Override
index 6684613f0ab0f1200eb8fab46442b10571429964..272ce37708adcf214fc4c72f69d580f73f455fa5 100644 (file)
@@ -41,7 +41,7 @@ public class AddNullableNotNullAnnotationFix extends AddAnnotationPsiFix {
     if (!super.isAvailable(project, file, startElement, endElement)) {
       return false;
     }
-    PsiModifierListOwner owner = getContainer(startElement);
+    PsiModifierListOwner owner = getContainer(file, startElement.getTextRange().getStartOffset());
     if (owner == null || AnnotationUtil.isAnnotated(owner, getAnnotationsToRemove()[0], false, false)) {
       return false;
     }
index ccb1c3c369e409ce84b73115416a83eb7a0cf7e3..5d51949c1d6beb6d5b612913a3095d7a9158ea4b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -52,7 +52,9 @@ public class AddExceptionToCatchFix extends BaseIntentionAction {
     PsiDocumentManager.getInstance(project).commitAllDocuments();
 
     PsiElement element = findElement(file, offset);
-    PsiTryStatement tryStatement = (PsiTryStatement) element.getParent();
+    if (element == null) return;
+
+    PsiTryStatement tryStatement = (PsiTryStatement)element.getParent();
     List<PsiClassType> unhandledExceptions = new ArrayList<PsiClassType>(ExceptionUtil.collectUnhandledExceptions(element, null));
     ExceptionUtil.sortExceptionsByHierarchy(unhandledExceptions);
 
@@ -86,7 +88,9 @@ public class AddExceptionToCatchFix extends BaseIntentionAction {
     }
   }
 
-  private static PsiCodeBlock addCatchStatement(PsiTryStatement tryStatement, PsiClassType exceptionType, PsiFile file) throws IncorrectOperationException {
+  private static PsiCodeBlock addCatchStatement(PsiTryStatement tryStatement,
+                                                PsiClassType exceptionType,
+                                                PsiFile file) throws IncorrectOperationException {
     PsiElementFactory factory = JavaPsiFacade.getInstance(tryStatement.getProject()).getElementFactory();
 
     if (tryStatement.getTryBlock() == null) {
@@ -108,9 +112,12 @@ public class AddExceptionToCatchFix extends BaseIntentionAction {
     }
 
     PsiParameter[] parameters = tryStatement.getCatchBlockParameters();
-    parameters[parameters.length - 1].getTypeElement().replace(factory.createTypeElement(exceptionType));
-    PsiCodeBlock[] catchBlocks = tryStatement.getCatchBlocks();
+    PsiTypeElement typeElement = parameters[parameters.length - 1].getTypeElement();
+    if (typeElement != null) {
+      JavaCodeStyleManager.getInstance(file.getProject()).shortenClassReferences(typeElement);
+    }
 
+    PsiCodeBlock[] catchBlocks = tryStatement.getCatchBlocks();
     return catchBlocks[catchBlocks.length - 1];
   }
 
index 19a4639a0689c866a2ddffd447978c37829cdc3b..69800e5616f7a4907f969eef9d25361ee3bbefbc 100644 (file)
@@ -200,7 +200,7 @@ public class StaticImportMethodFix implements IntentionAction {
             //do not show methods from default package
             && !((PsiJavaFile)file).getPackageName().isEmpty()
             && PsiUtil.isAccessible(file.getProject(), method, element, containingClass)) {
-          if (method.isDeprecated()) {
+          if (isEffectivelyDeprecated(method)) {
             deprecated.put(containingClass, method);
             return processCondition();
           }
@@ -209,6 +209,20 @@ public class StaticImportMethodFix implements IntentionAction {
         return processCondition();
       }
 
+      private boolean isEffectivelyDeprecated(PsiMethod method) {
+        if (method.isDeprecated()) {
+          return true;
+        }
+        PsiClass aClass = method.getContainingClass();
+        while (aClass != null) {
+          if (aClass.isDeprecated()) {
+            return true;
+          }
+          aClass = aClass.getContainingClass();
+        }
+        return false;
+      }
+
       private boolean processCondition() {
         return (applicableList.isEmpty() ? list : applicableList).size() + deprecated.size() < 50;
       }
index 2b839b5dfcde318878e814cbb01b8275634ca63a..daf5aa5eac741cce8b8c9e78b784efe0eced54ce 100644 (file)
@@ -26,13 +26,11 @@ import com.intellij.codeInsight.AnnotationUtil;
 import com.intellij.codeInsight.CodeInsightBundle;
 import com.intellij.codeInsight.intention.AddAnnotationFix;
 import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
-import com.intellij.openapi.editor.CaretModel;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Pair;
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
-import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
 
@@ -49,22 +47,11 @@ public abstract class AddAnnotationIntention extends BaseIntentionAction {
   // include not in project files
   @Override
   public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
-    CaretModel caretModel = editor.getCaretModel();
-    int position = caretModel.getOffset();
-    PsiElement element = file.findElementAt(position);
-    return element != null && isAvailable(project, element);
-  }
-
-  public boolean isAvailable(@NotNull final Project project, @NotNull final PsiElement element) {
-    if (!element.isValid()) return false;
-    final PsiModifierListOwner owner;
-    if (!element.getManager().isInProject(element) || CodeStyleSettingsManager.getSettings(project).USE_EXTERNAL_ANNOTATIONS) {
-      owner = AddAnnotationPsiFix.getContainer(element);
-    }
-    else {
+    final PsiModifierListOwner owner = AddAnnotationPsiFix.getContainer(file, editor.getCaretModel().getOffset());
+    if (owner == null ||
+        owner.getManager().isInProject(owner) && !CodeStyleSettingsManager.getSettings(project).USE_EXTERNAL_ANNOTATIONS) {
       return false;
     }
-    if (owner == null) return false;
     Pair<String, String[]> annotations = getAnnotations(project);
     String toAdd = annotations.first;
     String[] toRemove = annotations.second;
@@ -82,11 +69,7 @@ public abstract class AddAnnotationIntention extends BaseIntentionAction {
 
   @Override
   public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
-    CaretModel caretModel = editor.getCaretModel();
-    int position = caretModel.getOffset();
-    PsiElement element = file.findElementAt(position);
-
-    PsiModifierListOwner owner = AddAnnotationPsiFix.getContainer(element);
+    PsiModifierListOwner owner = AddAnnotationPsiFix.getContainer(file, editor.getCaretModel().getOffset());
     if (owner == null || !owner.isValid()) return;
     Pair<String, String[]> annotations = getAnnotations(project);
     String toAdd = annotations.first;
index 7040347c4d0e728947a4de506bc65b28f63d5a4e..767077b3448e9d37eeb637966c38da21fd495090 100644 (file)
@@ -28,7 +28,6 @@ import com.intellij.openapi.ui.InputValidatorEx;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
-import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
@@ -48,22 +47,15 @@ public class EditContractIntention extends BaseIntentionAction {
 
   @Nullable
   private static PsiMethod getTargetMethod(@NotNull Project project, Editor editor, PsiFile file) {
-    PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
-    if (element == null) return null;
-    if (!element.getManager().isInProject(element) || CodeStyleSettingsManager.getSettings(project).USE_EXTERNAL_ANNOTATIONS) {
-      final PsiModifierListOwner owner = AddAnnotationPsiFix.getContainer(element);
-      if (owner instanceof PsiMethod) {
-        PsiElement original = owner.getOriginalElement();
-        if (original instanceof PsiMethod) {
-          return (PsiMethod)original;
-        }
-        return (PsiMethod)owner;
-      }
+    final PsiModifierListOwner owner =  AddAnnotationPsiFix.getContainer(file, editor.getCaretModel().getOffset());
+    if (owner instanceof PsiMethod &&
+        (!owner.getManager().isInProject(owner) || CodeStyleSettingsManager.getSettings(project).USE_EXTERNAL_ANNOTATIONS)) {
+      PsiElement original = owner.getOriginalElement();
+      return original instanceof PsiMethod ? (PsiMethod)original : (PsiMethod)owner;
     }
     return null;
   }
 
-
   @Override
   public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
     final PsiMethod method = getTargetMethod(project, editor, file);
index ee207fb89fc70b23527251d57f8eee909857fafb..a32dc464f7fa1f4048d4688e0e8a5b904112c0ca 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -21,6 +21,7 @@ import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Ref;
 import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.searches.ReferencesSearch;
 import com.intellij.psi.util.PsiUtil;
@@ -187,27 +188,28 @@ public class ChangeClassSignatureProcessor extends BaseRefactoringProcessor {
     ChangeSignatureUtil.synchronizeList(myClass.getTypeParameterList(), newTypeParameters, TypeParameterList.INSTANCE, toRemoveParms);
   }
 
-  private boolean[] detectRemovedParameters(final PsiTypeParameter[] originaltypeParameters) {
-    final boolean[] toRemoveParms = new boolean[originaltypeParameters.length];
-    Arrays.fill(toRemoveParms, true);
+  private boolean[] detectRemovedParameters(final PsiTypeParameter[] original) {
+    final boolean[] toRemove = new boolean[original.length];
+    Arrays.fill(toRemove, true);
     for (final TypeParameterInfo info : myNewSignature) {
       int oldParameterIndex = info.getOldParameterIndex();
       if (oldParameterIndex >= 0) {
-        toRemoveParms[oldParameterIndex] = false;
+        toRemove[oldParameterIndex] = false;
       }
     }
-    return toRemoveParms;
+    return toRemove;
   }
 
-  private void processUsage(final UsageInfo usage, final PsiTypeParameter[] originalTypeParameters, final boolean[] toRemoveParms)
-    throws IncorrectOperationException {
+  private void processUsage(UsageInfo usage, PsiTypeParameter[] original, boolean[] toRemove) throws IncorrectOperationException {
     PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory();
     PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement)usage.getElement();
+    assert referenceElement != null : usage;
     PsiSubstitutor usageSubstitutor = determineUsageSubstitutor(referenceElement);
 
     PsiReferenceParameterList referenceParameterList = referenceElement.getParameterList();
+    assert referenceParameterList != null : referenceElement;
     PsiTypeElement[] oldValues = referenceParameterList.getTypeParameterElements();
-    if (oldValues.length != originalTypeParameters.length) return;
+    if (oldValues.length != original.length) return;
     List<PsiTypeElement> newValues = new ArrayList<PsiTypeElement>();
     for (final TypeParameterInfo info : myNewSignature) {
       int oldIndex = info.getOldParameterIndex();
@@ -221,7 +223,9 @@ public class ChangeClassSignatureProcessor extends BaseRefactoringProcessor {
         newValues.add(newValue);
       }
     }
-    ChangeSignatureUtil.synchronizeList(referenceParameterList, newValues, ReferenceParameterList.INSTANCE, toRemoveParms);
+
+    ChangeSignatureUtil.synchronizeList(referenceParameterList, newValues, ReferenceParameterList.INSTANCE, toRemove);
+    JavaCodeStyleManager.getInstance(myProject).shortenClassReferences(referenceParameterList);
   }
 
   private PsiSubstitutor determineUsageSubstitutor(PsiJavaCodeReferenceElement referenceElement) {
index 25a9481259d805070299b2b9ec796edde27d560c..2b483ddb676c8aa04836ddc9f07af988390f67a8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.wm.WindowManager;
 import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.searches.ReferencesSearch;
 import com.intellij.psi.util.PsiTreeUtil;
@@ -259,9 +260,13 @@ public class InlineToAnonymousClassProcessor extends BaseRefactoringProcessor {
         new InlineToAnonymousConstructorProcessor(myClass, psiNewExpression, superType).run();
       }
       else {
-        PsiJavaCodeReferenceElement element =
-          JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory().createClassReferenceElement(superType.resolve());
-        psiNewExpression.getClassReference().replace(element);        
+        PsiClass target = superType.resolve();
+        assert target != null : superType;
+        PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory();
+        PsiJavaCodeReferenceElement element = factory.createClassReferenceElement(target);
+        PsiJavaCodeReferenceElement reference = psiNewExpression.getClassReference();
+        assert reference != null : psiNewExpression;
+        reference.replace(element);
       }
     }
     catch (IncorrectOperationException e) {
@@ -276,7 +281,8 @@ public class InlineToAnonymousClassProcessor extends BaseRefactoringProcessor {
     PsiType substType = classResolveResult.getSubstitutor().substitute(superType);
     assert classResolveResult.getElement() == myClass;
     try {
-      typeElement.replace(factory.createTypeElement(substType));
+      PsiElement replaced = typeElement.replace(factory.createTypeElement(substType));
+      JavaCodeStyleManager.getInstance(myProject).shortenClassReferences(replaced);
     }
     catch(IncorrectOperationException e) {
       LOG.error(e);
index f2a6a2e647a2016ee7b131605eb6d20d58bc65e0..ec1e10df935bd861816cc76fa0578079b99c2fe2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-/*
- * User: anna
- * Date: 27-Aug-2008
- */
 package com.intellij.refactoring.inlineSuperClass.usageInfo;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.util.TypeConversionUtil;
 import com.intellij.refactoring.util.FixableUsageInfo;
 import com.intellij.util.Function;
 import com.intellij.util.IncorrectOperationException;
 
+/**
+ * @author anna
+ * @since 27-Aug-2008
+ */
 public class ReplaceWithSubtypeUsageInfo extends FixableUsageInfo {
   public static final Logger LOG = Logger.getInstance("#" + ReplaceWithSubtypeUsageInfo.class.getName());
   private final PsiTypeElement myTypeElement;
@@ -51,8 +52,10 @@ public class ReplaceWithSubtypeUsageInfo extends FixableUsageInfo {
 
   public void fixUsage() throws IncorrectOperationException {
     if (myTypeElement.isValid()) {
-      final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(myTypeElement.getProject()).getElementFactory();
-      myTypeElement.replace(elementFactory.createTypeElement(myTargetClassType));
+      Project project = myTypeElement.getProject();
+      PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory();
+      PsiElement replaced = myTypeElement.replace(elementFactory.createTypeElement(myTargetClassType));
+      JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced);
     }
   }
 
index 8c36cfae1b889f87a4c6bc66870b13ddf5fe8920..577d38a30a15a7195a286955c7d75df96cb7959c 100644 (file)
@@ -519,6 +519,14 @@ public class GenericsUtil {
     else if (type instanceof PsiArrayType) {
       return checkNotAssignable(bound, type, true);
     }
+    else if (type instanceof PsiIntersectionType) {
+      for (PsiType psiType : ((PsiIntersectionType)type).getConjuncts()) {
+        if (!checkNotInBounds(psiType, bound, uncheckedConversionByDefault)) {
+          return false; 
+        }
+      }
+      return true;
+    }
     return false;
   }
 
index 215bb86b2b81a465abb6d79fc8e5aef1e5fdd457..5f5d6d7ef8dc72efc23af075910ae9c1ae196216 100644 (file)
@@ -78,7 +78,8 @@ public class PsiIntersectionType extends PsiType {
         for (PsiType existing : array) {
           if (type != existing) {
             final boolean allowUncheckedConversion = type instanceof PsiClassType && ((PsiClassType)type).isRaw();
-            if (TypeConversionUtil.isAssignable(type, existing, allowUncheckedConversion)) {
+            if (TypeConversionUtil.isAssignable(GenericsUtil.eliminateWildcards(type), 
+                                                GenericsUtil.eliminateWildcards(existing), allowUncheckedConversion)) {
               iterator.remove();
               break;
             }
index 0de45be17786f133b9f2b057c7b0faa83fa0a9a5..77fd0081d161326184a26a426e564227819fa09d 100644 (file)
@@ -493,6 +493,13 @@ public class PsiImplUtil {
       return PsiUtil.captureToplevelWildcards(type, expression);
     }
 
+    final PsiElement parent = toplevel.getParent();
+    if (parent instanceof PsiExpressionList &&
+        PsiUtil.isLanguageLevel8OrHigher(parent) &&
+        parent.getParent() instanceof PsiCallExpression) {
+      return PsiUtil.captureToplevelWildcards(type, expression);
+    }
+
     final PsiType normalized = doNormalizeWildcardByPosition(type, expression, toplevel);
     LOG.assertTrue(normalized.isValid(), type);
     if (normalized instanceof PsiClassType && !PsiUtil.isAccessedForWriting(toplevel)) {
index 599f756adbc1d5e8ecb32c897997cd66a615bdcb..16d9712386843b4fc5da546d6e14d36351ec4bf6 100644 (file)
@@ -17,8 +17,7 @@ package com.intellij.psi.impl.compiled;
 
 import com.intellij.openapi.util.AtomicNotNullLazyValue;
 import com.intellij.openapi.util.NotNullLazyValue;
-import com.intellij.openapi.util.NullableLazyValue;
-import com.intellij.openapi.util.VolatileNullableLazyValue;
+import com.intellij.openapi.util.Ref;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.PsiImplUtil;
 import com.intellij.psi.impl.PsiJavaParserFacadeImpl;
@@ -28,7 +27,6 @@ import com.intellij.psi.impl.source.tree.JavaElementType;
 import com.intellij.psi.impl.source.tree.TreeElement;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement {
   @NonNls static final char VARIANCE_NONE = '\0';
@@ -41,18 +39,18 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement
   private final PsiElement myParent;
   private final String myTypeText;
   private final char myVariance;
-  private final NullableLazyValue<ClsElementImpl> myChild;
+  private final NotNullLazyValue<Ref<ClsElementImpl>> myChild;
   private final NotNullLazyValue<PsiType> myCachedType;
 
   public ClsTypeElementImpl(@NotNull PsiElement parent, @NotNull String typeText, char variance) {
     myParent = parent;
     myTypeText = TypeInfo.internFrequentType(typeText);
     myVariance = variance;
-    myChild = new VolatileNullableLazyValue<ClsElementImpl>() {
-      @Nullable
+    myChild = new AtomicNotNullLazyValue<Ref<ClsElementImpl>>() {
+      @NotNull
       @Override
-      protected ClsElementImpl compute() {
-        return calculateChild();
+      protected Ref<ClsElementImpl> compute() {
+        return Ref.create(calculateChild());
       }
     };
     myCachedType = new AtomicNotNullLazyValue<PsiType>() {
@@ -67,7 +65,7 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement
   @Override
   @NotNull
   public PsiElement[] getChildren() {
-    ClsElementImpl child = myChild.getValue();
+    ClsElementImpl child = myChild.getValue().get();
     return child != null ? new PsiElement[]{child} : PsiElement.EMPTY_ARRAY;
   }
 
@@ -111,7 +109,7 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement
   public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException {
     setMirrorCheckingType(element, JavaElementType.TYPE);
 
-    ClsElementImpl child = myChild.getValue();
+    ClsElementImpl child = myChild.getValue().get();
     if (child != null) {
       child.setMirror(element.getFirstChildNode());
     }
@@ -157,7 +155,7 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement
     PsiType result = PsiJavaParserFacadeImpl.getPrimitiveType(myTypeText);
     if (result != null) return result;
 
-    ClsElementImpl childElement = myChild.getValue();
+    ClsElementImpl childElement = myChild.getValue().get();
     if (childElement instanceof ClsTypeElementImpl) {
       if (isArray()) {
         switch (myVariance) {
index a52ea73a18d5ea1b17f7ca80d2baa73b2c3b5a92..f1439e6a219df5bcee515d2796bdd6811ee6348f 100644 (file)
@@ -18,7 +18,6 @@ package com.intellij.psi.impl.source.resolve.graphInference;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.source.resolve.graphInference.constraints.TypeEqualityConstraint;
-import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.util.TypeConversionUtil;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.Nullable;
@@ -119,14 +118,10 @@ public class FunctionalInterfaceParameterizationUtil {
         return null;
       }
 
-      if (!TypeConversionUtil.containsWildcards(parameterization)) {
+      if (!TypeConversionUtil.containsWildcards(parameterization) && psiClassType.isAssignableFrom(parameterization)) {
         return parameterization;
       }
 
-      if (!psiClassType.isAssignableFrom(parameterization)) {
-        return null;
-      }
-
       return getNonWildcardParameterization((PsiClassType)psiClassType);
     }
     return null;
@@ -169,27 +164,32 @@ public class FunctionalInterfaceParameterizationUtil {
       for (int i = 0; i < parameters.length; i++) {
         PsiType paramType = parameters[i];
         if (paramType instanceof PsiWildcardType) {
-          final PsiClassType[] extendsListTypes = typeParameters[i].getExtendsListTypes();
-          final PsiClassType Bi = extendsListTypes.length > 0 ? extendsListTypes[0]
-                                                              : PsiType.getJavaLangObject(psiClass.getManager(),
-                                                                                          GlobalSearchScope.allScope(psiClass.getProject()));
-          if (PsiPolyExpressionUtil.mentionsTypeParameters(Bi, typeParametersSet)) {
-            return null;
+          final PsiType bound = GenericsUtil.eliminateWildcards(((PsiWildcardType)paramType).getBound(), false);
+          if (((PsiWildcardType)paramType).isSuper()) {
+            newParameters[i] = bound;
           }
-
-          final PsiType bound = ((PsiWildcardType)paramType).getBound();
-          if (bound == null) {
-            newParameters[i] = Bi;
-          } else if (((PsiWildcardType)paramType).isExtends()){
-            newParameters[i] = GenericsUtil.getGreatestLowerBound(Bi, GenericsUtil.eliminateWildcards(bound, false));
-          } else {
-            newParameters[i] = GenericsUtil.eliminateWildcards(bound, false);
+          else {
+            newParameters[i] = bound != null ? bound : PsiType.getJavaLangObject(psiClass.getManager(), psiClassType.getResolveScope());
+            for (PsiClassType paramBound : typeParameters[i].getExtendsListTypes()) {
+              if (!PsiPolyExpressionUtil.mentionsTypeParameters(paramBound, typeParametersSet)) {
+                newParameters[i] = GenericsUtil.getGreatestLowerBound(paramBound, newParameters[i]);
+              }
+            }
           }
         } else {
           newParameters[i] = paramType;
         }
       }
-      return JavaPsiFacade.getElementFactory(psiClass.getProject()).createType(psiClass, newParameters);
+
+      if (!isWellFormed(psiClass, typeParameters, newParameters)) {
+        return null;
+      }
+
+      final PsiClassType parameterization = JavaPsiFacade.getElementFactory(psiClass.getProject()).createType(psiClass, newParameters);
+      if (!psiClassType.isAssignableFrom(parameterization)) {
+        return null;
+      }
+      return parameterization;
     }
     return null;
   }
index d46d56d7d96c03a31ee7edc683bd61025206dfcd..727352e5e972e2357b929334c29fd39d4e831e01 100644 (file)
@@ -20,7 +20,6 @@ import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.Pair;
 import com.intellij.psi.*;
-import com.intellij.psi.impl.PsiImplUtil;
 import com.intellij.psi.impl.source.resolve.graphInference.constraints.*;
 import com.intellij.psi.infos.MethodCandidateInfo;
 import com.intellij.psi.search.GlobalSearchScope;
@@ -360,16 +359,11 @@ public class InferenceSession {
     }
     return sameMethodCall;
   }
-  
-  public void addCapturedVariable(PsiTypeParameter param) {
-    initBounds(param);
-  }
 
   private void initReturnTypeConstraint(PsiMethod method, final PsiCallExpression context) {
     if (PsiPolyExpressionUtil.isMethodCallPolyExpression(context, method)) {
       PsiType returnType = method.getReturnType();
       if (!PsiType.VOID.equals(returnType) && returnType != null) {
-        returnType = PsiImplUtil.normalizeWildcardTypeByPosition(returnType, context);
         PsiType targetType = PsiTypesUtil.getExpectedTypeByParent(context);
         if (targetType == null) {
           targetType = getTargetType(context);
index dcfd45104a2511d9f4af0c3c29164bd5156966e3..8db944aaf90488fdcccfe3d285f4fe0273549c69 100644 (file)
@@ -129,7 +129,11 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
             final PsiParameter[] parameters = method.getParameterList().getParameters();
             callSession.initExpressionConstraints(parameters, args, myExpression, method);
           }
-          callSession.registerConstraints(returnType, myT);
+          final boolean accepted = callSession.repeatInferencePhases(true);
+          if (!accepted) {
+            //todo return false;
+          }
+          callSession.registerConstraints(returnType, substitutor.substitute(returnType));
           if (callSession.repeatInferencePhases(true)) {
             final Collection<InferenceVariable> inferenceVariables = callSession.getInferenceVariables();
             if (sameMethodCall) {
index 58c29706c1a318794b5880cfcfc3aacc39729b0a..18ff2d110ad92eabb9251e144b22395ff8506745 100644 (file)
@@ -25,7 +25,6 @@ import com.intellij.psi.tree.TokenSet;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.CharTable;
 import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.SmartList;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -55,18 +54,19 @@ public class JavaSharedImplUtil {
     return type;
   }
 
+  // collects annotations bound to C-style arrays
   private static List<PsiAnnotation[]> collectAnnotations(PsiElement anchor, PsiAnnotation stopAt) {
-    List<PsiAnnotation[]> annotations = new SmartList<PsiAnnotation[]>();
+    List<PsiAnnotation[]> annotations = ContainerUtil.newSmartList();
 
     List<PsiAnnotation> current = null;
-    boolean stop = false;
+    boolean found = (stopAt == null), stop = false;
     for (PsiElement child = anchor.getNextSibling(); child != null; child = child.getNextSibling()) {
       if (child instanceof PsiComment || child instanceof PsiWhiteSpace) continue;
 
       if (child instanceof PsiAnnotation) {
-        if (current == null) current = new SmartList<PsiAnnotation>();
+        if (current == null) current = ContainerUtil.newSmartList();
         current.add((PsiAnnotation)child);
-        if (child == stopAt) stop = true;
+        if (child == stopAt) found = stop = true;
         continue;
       }
 
@@ -80,8 +80,8 @@ public class JavaSharedImplUtil {
       }
     }
 
-    // stop == true means annotation is misplaced
-    return stop ? null : annotations;
+    // annotation is misplaced (either located before the anchor or has no following brackets)
+    return !found || stop ? null : annotations;
   }
 
   public static void normalizeBrackets(@NotNull PsiVariable variable) {
index 506accd112c312f0aa1fd3530cd0deb6ecd6a9ab..d0d4dbc5324afeb6d4d4d91012f601990e950380 100644 (file)
@@ -27,7 +27,7 @@ class UnsupportedFeatures {
     for (String s : args) { System.out.println(s); }
 
     List<String> list =
-      new ArrayList<>();
+      new ArrayList<error descr="Diamond types are not supported at this language level"><></error>();
 
     for (String s : list) {}
     Arrays.asList("");
index 400a678da1ed873ffea0346b6fbe183a19f54042..28035c8c16985da088745cb8e341939afc0a6039 100644 (file)
@@ -111,6 +111,7 @@ class Outer {
     int @TA [] a @TA [] <error descr="Annotations are not allowed here">@TA</error> = (p != null ? p : mixedArrays);
     return a;
   }
+  void <error descr="Annotations are not allowed here">@TA</error> misplaced() { }
 
   @TA Outer() { }
 
index 7556292ef5388f3cfded4cf92e0a3c0b4d4f358e..298a33dcbdf6c4a9e7c263a4fb6197dc92be9443 100644 (file)
@@ -142,7 +142,7 @@ class S1 {
     }
 
     void bar(List<? extends S1> k) {
-        f<error descr="'f(java.util.List<capture<? extends S1>>, capture<? extends S1>)' in 'S1' cannot be applied to '(java.util.List<capture<? extends S1>>, S1)'">(k,  k.get(0))</error>;
+        f<error descr="'f(java.util.List<capture<? extends S1>>, capture<? extends S1>)' in 'S1' cannot be applied to '(java.util.List<capture<? extends S1>>, capture<? extends S1>)'">(k,  k.get(0))</error>;
     }
 }
 
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/LiftedCaptureToOuterCall.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/LiftedCaptureToOuterCall.java
new file mode 100644 (file)
index 0000000..75d3b8a
--- /dev/null
@@ -0,0 +1,16 @@
+class Test {
+
+  class Foo<K> {}
+
+  void test(Foo<? extends String> p) {
+    foo(bar(p)) ;
+  }
+
+  <T> T bar(Foo<T> p) {
+    return null;
+  }
+
+  <K> K foo(K p) {
+    return null;
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/LambdaFormalParamTypesParametrization.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/LambdaFormalParamTypesParametrization.java
new file mode 100644 (file)
index 0000000..0dbcc3e
--- /dev/null
@@ -0,0 +1,10 @@
+import java.util.function.Function;
+
+class Test {
+
+  <U, V> void foo(Function<U, ? extends V> m) {}
+
+  {
+    foo((String e) -> e.length());
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/NonWildcardParametrization.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/NonWildcardParametrization.java
new file mode 100644 (file)
index 0000000..fa9df55
--- /dev/null
@@ -0,0 +1,108 @@
+import java.util.List;
+
+class SimpleDependency  {
+
+  interface I<R extends U, U> {
+    R m();
+  }
+
+  {
+    I<? extends String, ? extends  String> k = () -> null;
+    I<? extends String, String> k1 = () -> null;
+    I<? extends List<String>, List<String>> k2 = () -> null;
+    I<? extends List<String>, ? extends List<String>> k3 = () -> null;
+    I<? extends List<? extends String>, ? extends List<String>> k4 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends List<? extends String>, List<? extends String>> k5 = () -> null;
+    I<? extends List<? extends String>, ? extends List<? extends String>> k6 = () -> null;
+
+    I<? super String, String> s = () -> null;
+    I<? super List<String>, List<? extends String>> s1 = () -> null;
+  }
+}
+
+class NoDependency {
+  interface I<T, U> {
+    T m();
+  }
+
+  {
+    I<? extends String, ? extends String> k = () -> null;
+  }
+}
+
+class ExtendsList {
+  interface I<R extends List<T>, T> {
+    R m();
+  }
+
+  {
+    I<?, ? extends String> n = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<?, ?> n1 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<?, String> n2 = <error descr="Cannot infer functional interface type">() -> null</error>;
+
+
+    I<? extends List<?>, String> e1 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends List<?>, ?> e2 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends List<String>, ? extends String> e3 = () -> null;
+    I<? extends List<? extends String>, ? extends String> e4 = <error descr="Cannot infer functional interface type">() -> null</error>;
+
+    I<? super List<String>, ? extends String> s1 = () -> null;
+    I<? super List<String>, String> s2 = () -> null;
+  }
+}
+
+class MultipleBounds {
+  interface I<R extends List<T> & Comparable<T>, T> {
+    R m();
+  }
+
+  interface LC<K> extends List<K>, Comparable<K> {}
+
+  {
+    I<?, String> n = <error descr="Cannot infer functional interface type">() -> null</error>;
+
+    I<? extends List<String>, ? extends String> e1 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends Comparable<String>, ? extends String> e2 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends LC<String>, ? extends String> e3 = () -> null;
+    I<? extends LC<String>, String> e4 = () -> null;
+    I<? extends LC<? extends String>, String> e5 = <error descr="Cannot infer functional interface type">() -> null</error>;
+  }
+}
+
+class FirstIndependentBound {
+  interface I<R extends List<String> & Comparable<T>, T> {
+    R m();
+  }
+
+  interface LC<K> extends List<String>, Comparable<K> {}
+
+  {
+    I<?, String> n = <error descr="Cannot infer functional interface type">() -> null</error>;
+
+    I<? extends List<String>, ? extends String> e1 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends Comparable<String>, ? extends String> e2 = () -> null;
+    I<? extends LC<String>, ? extends String> e3 = () -> null;
+    I<? extends LC<String>, String> e4 = () -> null;
+    I<? extends LC<? extends String>, String> e5 = <error descr="Cannot infer functional interface type">() -> null</error>;
+  }
+}
+
+
+class SecondIndependentBound {
+  interface I<R extends List<T> & Comparable<String>, T> {
+    R m();
+  }
+
+  interface LC<K> extends List<String>, Comparable<K> {}
+
+  {
+    I<?, String> n = <error descr="Cannot infer functional interface type">() -> null</error>;
+
+    I<? extends List<String>, ? extends String> e1 = () -> null;
+    I<? extends Comparable<String>, ? extends String> e2 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends LC<String>, ? extends String> e3 = () -> null;
+    I<? extends LC<String>, String> e4 = () -> null;
+    I<? extends LC<? extends String>, String> e5 = <error descr="Cannot infer functional interface type">()  -> null</error>;
+    I<? extends LC<? extends String>, ? extends String> e6 = <error descr="Cannot infer functional interface type">()  -> null</error>;
+  }
+}
\ No newline at end of file
index 231a0cd45c0a8e24b6a6bf63eefb9ae5c413bb8f..ec8b8dd492840e4321282316c0ed10b9a81cf352 100644 (file)
@@ -27,7 +27,6 @@ import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.Result;
 import com.intellij.openapi.application.ex.PathManagerEx;
 import com.intellij.openapi.command.WriteCommandAction;
-import com.intellij.openapi.editor.CaretModel;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.module.Module;
@@ -51,6 +50,7 @@ import com.intellij.testFramework.PsiTestUtil;
 import com.intellij.testFramework.UsefulTestCase;
 import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
 import com.intellij.testFramework.fixtures.*;
+import com.intellij.util.ObjectUtils;
 import com.intellij.util.messages.MessageBusConnection;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -122,13 +122,7 @@ public class AddAnnotationFixTest extends UsefulTestCase {
 
   @NotNull
   private PsiModifierListOwner getOwner() {
-    CaretModel caretModel = myFixture.getEditor().getCaretModel();
-    int position = caretModel.getOffset();
-    PsiElement element = myFixture.getFile().findElementAt(position);
-    assert element != null;
-    PsiModifierListOwner container = AddAnnotationPsiFix.getContainer(element);
-    assert container != null;
-    return container;
+    return ObjectUtils.assertNotNull(AddAnnotationPsiFix.getContainer(myFixture.getFile(), myFixture.getCaretOffset()));
   }
 
   private void startListening(@NotNull final List<Trinity<PsiModifierListOwner, String, Boolean>> expectedSequence) {
index 1868d2196d7c271a8a5c8b2ce1143b2a3a90fc42..964566fcf5ffa6c42d33afdd81efd12cb535accb 100644 (file)
@@ -39,6 +39,8 @@ public class AnnotationsHighlightingTest extends LightDaemonAnalyzerTestCase {
   public void testInapplicable() { doTest(false); }
   public void testDuplicateAttribute() { doTest(false); }
   public void testDuplicateTarget() { doTest(false); }
+  public void testPingPongAnnotationTypesDependencies() { doTest(false);}
+  public void testClashMethods() { doTest(false);}
 
   public void testInvalidPackageAnnotationTarget() { doTest(BASE_PATH + "/" + getTestName(true) + "/package-info.java", false, false); }
   public void testPackageAnnotationNotInPackageInfo() { doTest(BASE_PATH + "/" + getTestName(true) + "/notPackageInfo.java", false, false); }
@@ -46,9 +48,6 @@ public class AnnotationsHighlightingTest extends LightDaemonAnalyzerTestCase {
   public void testTypeAnnotations() { doTest8(false); }
   public void testRepeatable() { doTest8(false); }
 
-  public void testPingPongAnnotationTypesDependencies() { doTest(false);}
-  public void testClashMethods() { doTest(false);}
-
   private void doTest(boolean checkWarnings) {
     setLanguageLevel(LanguageLevel.JDK_1_7);
     doTest(BASE_PATH + "/" + getTestName(true) + ".java", checkWarnings, false);
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalTypeWildcardParameterizationTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalTypeWildcardParameterizationTest.java
new file mode 100644 (file)
index 0000000..2e32026
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2014 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.codeInsight.daemon.lambda;
+
+import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
+import com.intellij.openapi.projectRoots.JavaSdkVersion;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.testFramework.IdeaTestUtil;
+import org.jetbrains.annotations.NonNls;
+
+public class FunctionalTypeWildcardParameterizationTest extends LightDaemonAnalyzerTestCase {
+  @NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization";
+
+  public void testNonWildcardParametrization() throws Exception {
+    doTest();
+  }
+
+  public void testLambdaFormalParamTypesParametrization() throws Exception {
+    doTest();
+  }
+
+  private void doTest() {
+    IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_8, getModule(), getTestRootDisposable());
+    doTestNewInference(BASE_PATH + "/" + getTestName(false) + ".java", false, false);
+  }
+
+  @Override
+  protected Sdk getProjectJDK() {
+    return IdeaTestUtil.getMockJdk18();
+  }
+}
index 0182af2a868914a8f2bfe3e353704d60206eb2ba..7cac6170b12e61691bfb5e279886b53fd00e4a24 100644 (file)
@@ -160,6 +160,10 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
     doTest();
   }
 
+  public void testLiftedCaptureToOuterCall() throws Exception {
+    doTest();
+  }
+
   private void doTest() throws Exception {
     doTest(false);
   }
index c2cef13e6ea87a50b5a96f144adde8ce28501982..bfd1de796f90f89108568361135cbc76f971f572 100644 (file)
@@ -194,7 +194,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase {
     PsiDirectory psiDirectory = FindInProjectUtil.getPsiDirectory(findModel, myProject);
     List<UsageInfo> result = new ArrayList<UsageInfo>();
     final CommonProcessors.CollectProcessor<UsageInfo> collector = new CommonProcessors.CollectProcessor<UsageInfo>(result);
-    FindInProjectUtil.findUsages(findModel, psiDirectory, myProject, true, collector, new FindUsagesProcessPresentation(FindInProjectUtil.setupViewPresentation(true, findModel)));
+    FindInProjectUtil.findUsages(findModel, psiDirectory, myProject, collector, new FindUsagesProcessPresentation(FindInProjectUtil.setupViewPresentation(true, findModel)));
     return result;
   }
 
index 683a8b02abb0d619379113390c4a753880e8e2ec..5f74fa20db0df7919097e1507abfb5fac1f517a2 100644 (file)
@@ -50,6 +50,21 @@ public class ModuleChunk {
     myContainsTests = containsTests;
   }
 
+  public String getPresentableShortName() {
+    String name = myModules.iterator().next().getName();
+    if (myModules.size() > 1) {
+      name += " and " + (myModules.size() - 1) + " more";
+      String fullName = getName();
+      if (fullName.length() < name.length()) {
+        name = fullName;
+      }
+    }
+    if (containsTests()) {
+      name = "tests of " + name;
+    }
+    return name;
+  }
+
   public String getName() {
     if (myModules.size() == 1) return myModules.iterator().next().getName();
     return StringUtil.join(myModules, GET_NAME, ",");
index 35de6680ca8714fec183ba6a9d10d4b7e06e2718..1f4bcfc09f8f260a7bd25114d4816ea9a71317a9 100644 (file)
@@ -79,7 +79,7 @@ public class JavaBuilderUtil {
       final boolean errorsDetected = Utils.errorsDetected(context);
       if (!isForcedRecompilationAllJavaModules(context)) {
         if (context.shouldDifferentiate(chunk)) {
-          context.processMessage(new ProgressMessage("Checking dependencies... [" + chunk.getName() + "]"));
+          context.processMessage(new ProgressMessage("Checking dependencies... [" + chunk.getPresentableShortName() + "]"));
           final Set<File> allCompiledFiles = getAllCompiledFilesContainer(context);
           final Set<File> allAffectedFiles = getAllAffectedFilesContainer(context);
 
@@ -144,7 +144,7 @@ public class JavaBuilderUtil {
             }
           }
           else {
-            final String messageText = "Marking " + chunk.getName() + " and direct dependants for recompilation";
+            final String messageText = "Marking " + chunk.getPresentableShortName() + " and direct dependants for recompilation";
             LOG.info("Non-incremental mode: " + messageText);
             context.processMessage(new ProgressMessage(messageText));
 
@@ -172,7 +172,7 @@ public class JavaBuilderUtil {
         return false;
       }
 
-      context.processMessage(new ProgressMessage("Updating dependency information... [" + chunk.getName() + "]"));
+      context.processMessage(new ProgressMessage("Updating dependency information... [" + chunk.getPresentableShortName() + "]"));
 
       globalMappings.integrate(delta);
 
index 092b002f2384d3a6a76e97fb4662cfdb559743f0..af1c974b84a2b068d1105761153873f3d4fee934 100644 (file)
@@ -74,7 +74,7 @@ public abstract class ClassProcessingBuilder extends ModuleLevelBuilder {
     final String progress = getProgressMessage();
     final boolean shouldShowProgress = !StringUtil.isEmptyOrSpaces(progress);
     if (shouldShowProgress) {
-      context.processMessage(new ProgressMessage(progress + " [" + chunk.getName() + "]"));
+      context.processMessage(new ProgressMessage(progress + " [" + chunk.getPresentableShortName() + "]"));
     }
 
     ExitCode exitCode = ExitCode.NOTHING_DONE;
index 645cdd648bbb40c29f5e5047b610f4219e2b0843..aa10534dd4a48ea9070ea97f354817d6105c9908 100644 (file)
@@ -243,7 +243,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
     // begin compilation round
     final Mappings delta = pd.dataManager.getMappings().createDelta();
     final Callbacks.Backend mappingsCallback = delta.getCallback();
-    final OutputFilesSink outputSink = new OutputFilesSink(context, outputConsumer, mappingsCallback, chunk.getName());
+    final OutputFilesSink outputSink = new OutputFilesSink(context, outputConsumer, mappingsCallback, chunk.getPresentableShortName());
     try {
       if (hasSourcesToCompile) {
         final AtomicReference<String> ref = COMPILER_VERSION_INFO.get(context);
@@ -264,7 +264,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
         final DiagnosticSink diagnosticSink = new DiagnosticSink(context);
         
         final String chunkName = chunk.getName();
-        context.processMessage(new ProgressMessage("Parsing java... [" + chunkName + "]"));
+        context.processMessage(new ProgressMessage("Parsing java... [" + chunk.getPresentableShortName() + "]"));
 
         final int filesCount = files.size();
         boolean compiledOk = true;
index 9d34bbb0536684e5955e9a6db16da38229732f1d..2d40d9faf1e6bc3f18d0fd7743dfe055005d7038 100644 (file)
@@ -37,19 +37,19 @@ public class CompilerMessage extends BuildMessage {
   private final long myLine;
   private final long myColumn;
 
-  public CompilerMessage(String compilerName, @NotNull Throwable internalError) {
+  public CompilerMessage(@NotNull String compilerName, @NotNull Throwable internalError) {
     this(compilerName, Kind.ERROR, getTextFromThrowable(internalError), null, -1L, -1L, -1L, -1L, -1L);
   }
 
-  public CompilerMessage(String compilerName, Kind kind, String messageText) {
+  public CompilerMessage(@NotNull String compilerName, Kind kind, String messageText) {
     this(compilerName, kind, messageText, null, -1L, -1L, -1L, -1L, -1L);
   }
 
-  public CompilerMessage(String compilerName, Kind kind, String messageText, String sourcePath) {
+  public CompilerMessage(@NotNull String compilerName, Kind kind, String messageText, String sourcePath) {
     this(compilerName, kind, messageText, sourcePath, -1L, -1L, -1L, -1L, -1L);
   }
 
-  public CompilerMessage(String compilerName, Kind kind, String messageText,
+  public CompilerMessage(@NotNull String compilerName, Kind kind, String messageText,
                          @Nullable String sourcePath,
                          long problemBeginOffset,
                          long problemEndOffset,
@@ -66,6 +66,7 @@ public class CompilerMessage extends BuildMessage {
     myColumn = locationColumn;
   }
 
+  @NotNull
   public String getCompilerName() {
     return myCompilerName;
   }
similarity index 62%
rename from lib/netty-all-5.0.0.Alpha1.jar
rename to lib/netty-all-5.0.0.Alpha2.jar
index ff0afa01af446f9e6f5eaeb382b5043249a6ea71..d4b646a22a83408be4765fd5ecd6c11e17481fc5 100644 (file)
Binary files a/lib/netty-all-5.0.0.Alpha1.jar and b/lib/netty-all-5.0.0.Alpha2.jar differ
index 2e7c8bfb3469df2f34a43f208473fc6f61edbcc2..c368b9076142fa0b2ae43bfe721e148da9d4ab82 100644 (file)
@@ -40,7 +40,7 @@ microba.jar
 miglayout-swing.jar
 nanoxml-2.2.3.jar
 nekohtml-1.9.14.jar
-netty-all-5.0.0.Alpha1.jar
+netty-all-5.0.0.Alpha2.jar
 oromatcher.jar
 picocontainer.jar
 protobuf-2.5.0.jar
similarity index 68%
rename from lib/src/netty-all-5.0.0.Alpha1-sources.jar
rename to lib/src/netty-all-5.0.0.Alpha2-sources.jar
index 767b4fb269df8226e1ea50246425d86fab614510..354781d9601a88ee16908731258c987e5ca0883e 100644 (file)
Binary files a/lib/src/netty-all-5.0.0.Alpha1-sources.jar and b/lib/src/netty-all-5.0.0.Alpha2-sources.jar differ
index d823f67b2a16d47c33b03442a6dfba21072a66f7..ede02461408d7e36be8c67f16907777266bd6b94 100644 (file)
@@ -32,13 +32,13 @@ public interface CodeInsightColors {
   TextAttributesKey DEPRECATED_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("DEPRECATED_ATTRIBUTES");
 
   TextAttributesKey LOCAL_VARIABLE_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("LOCAL_VARIABLE_ATTRIBUTES");
-  TextAttributesKey REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES");
-  TextAttributesKey REASSIGNED_PARAMETER_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("REASSIGNED_PARAMETER_ATTRIBUTES");
+  TextAttributesKey PARAMETER_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("PARAMETER_ATTRIBUTES");
+  TextAttributesKey REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES", LOCAL_VARIABLE_ATTRIBUTES);
+  TextAttributesKey REASSIGNED_PARAMETER_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("REASSIGNED_PARAMETER_ATTRIBUTES", PARAMETER_ATTRIBUTES);
   TextAttributesKey IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES");
   TextAttributesKey INSTANCE_FIELD_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("INSTANCE_FIELD_ATTRIBUTES");
   TextAttributesKey STATIC_FIELD_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("STATIC_FIELD_ATTRIBUTES");
   TextAttributesKey STATIC_FINAL_FIELD_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("STATIC_FINAL_FIELD_ATTRIBUTES", STATIC_FIELD_ATTRIBUTES);
-  TextAttributesKey PARAMETER_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("PARAMETER_ATTRIBUTES");
   TextAttributesKey CLASS_NAME_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("CLASS_NAME_ATTRIBUTES");
   TextAttributesKey ANONYMOUS_CLASS_NAME_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("ANONYMOUS_CLASS_NAME_ATTRIBUTES");
   TextAttributesKey TYPE_PARAMETER_NAME_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("TYPE_PARAMETER_NAME_ATTRIBUTES");
index 34907f8384c12904263f91c14d5baec6364c894e..5a9a904e575801f8528398b0df61a2ec4f31a24d 100644 (file)
@@ -53,6 +53,11 @@ public abstract class EncodingRegistry {
 
   public abstract void setEncoding(@Nullable("null means project") VirtualFile virtualFileOrDir, @Nullable("null means remove mapping") Charset charset);
 
+  @Nullable("null means 'use system-default'")
+  public Charset getDefaultCharsetForPropertiesFiles(@Nullable VirtualFile virtualFile) {
+    return null;
+  }
+
   public static EncodingRegistry getInstance() {
     if (ourInstanceGetter == null) {
       return (EncodingRegistry)ApplicationManager.getApplication().getPicoContainer().getComponentInstance("com.intellij.openapi.vfs.encoding.EncodingManager");
index 19854ccdb88e779996a772e08eff8b9742863b52..5172e155cd14d39d937d6236103d98f3e9517d35 100644 (file)
@@ -24,7 +24,7 @@ public class PlatformUtilsCore {
   public static final String APPCODE_PREFIX = "AppCode";
   public static final String CPP_PREFIX = "CppIde";
   public static final String PYCHARM_PREFIX = "Python";
-  public static final String PYCHARM_PREFIX2 = "PyCharm";
+  public static final String PYCHARM_PREFIX2 = "PyCharmCore";
   public static final String RUBY_PREFIX = "Ruby";
   public static final String PHP_PREFIX = "PhpStorm";
   public static final String WEB_PREFIX = "WebStorm";
index 2a2249b60e57c6cfc8f6d62a86fcf6e755d10cc5..c3424e3bc51f19b123907865014b9a225b6a2852 100644 (file)
@@ -713,6 +713,8 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
     }
     assertInsideCommand();
 
+    getLineSet(); // initialize line set to track changed lines
+
     DocumentEvent event = new DocumentEventImpl(this, offset, oldString, newString, myModificationStamp, wholeTextReplaced);
 
     if (!ShutDownTracker.isShutdownHookRunning()) {
@@ -744,12 +746,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
     try {
       if (LOG.isDebugEnabled()) LOG.debug(event.toString());
 
-      synchronized (myLineSetLock) {
-        LineSet lineSet = myLineSet;
-        if (lineSet != null) {
-          lineSet.changedUpdate(event);
-        }
-      }
+      getLineSet().changedUpdate(event);
       setModificationStamp(newModificationStamp);
 
       if (!ShutDownTracker.isShutdownHookRunning()) {
index b11ff743642ecf09e30461f0a1f5b0a817398fe4..9fd72279c4f23386346e36c96a0477f3261f88ba 100644 (file)
@@ -110,7 +110,7 @@ public class MarkupModelWindow extends UserDataHolderBase implements MarkupModel
   }
 
   @Override
-  public RangeHighlighter addPersistentLineHighlighter(final int line, final int layer, final TextAttributes textAttributes) {
+  public RangeHighlighterEx addPersistentLineHighlighter(final int line, final int layer, final TextAttributes textAttributes) {
     int hostLine = myDocument.injectedToHostLine(line);
     return myHostModel.addPersistentLineHighlighter(hostLine, layer, textAttributes);
   }
index 284ef90e20077129d534dd9a39c82489d1c7150c..28d8cb447d7ce073642a0b0fea0dcf5cc158073a 100644 (file)
@@ -33,7 +33,7 @@ public interface MarkupModelEx extends MarkupModel {
   void dispose();
 
   @Nullable
-  RangeHighlighter addPersistentLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes);
+  RangeHighlighterEx addPersistentLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes);
 
   void fireAttributesChanged(@NotNull RangeHighlighterEx segmentHighlighter, boolean renderersChanged);
 
index d9e5c4bd51bd419bd21884341987462395f96251..a3ac344e23bff1c773bb656054cefb1647fdfdb2 100644 (file)
@@ -109,7 +109,7 @@ public class EmptyMarkupModel implements MarkupModelEx {
   }
 
   @Override
-  public RangeHighlighter addPersistentLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes) {
+  public RangeHighlighterEx addPersistentLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes) {
     return null;
   }
 
index 1612546040229582acccdc865eb06f66746885c9..5724189b0110e6148ec00cd976ecfa028af865bb 100644 (file)
@@ -76,7 +76,7 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx
 
   @Override
   @Nullable
-  public RangeHighlighter addPersistentLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes) {
+  public RangeHighlighterEx addPersistentLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes) {
     if (isNotValidLine(lineNumber)) {
       return null;
     }
index e38cac95243cfa6b8bc2cf815ef5715014065942..652ea08712159bfbc3ede0333cba68e01cf7a8ea 100644 (file)
@@ -32,13 +32,17 @@ import javax.swing.*;
  */
 public class StopProcessAction extends DumbAwareAction implements AnAction.TransparentUpdate {
 
-  private final ProcessHandler myProcessHandler;
+  private ProcessHandler myProcessHandler;
 
-  public StopProcessAction(@NotNull String text, @Nullable String description, @NotNull ProcessHandler processHandler) {
+  public StopProcessAction(@NotNull String text, @Nullable String description, @Nullable ProcessHandler processHandler) {
     super(text, description, AllIcons.Actions.Suspend);
     myProcessHandler = processHandler;
   }
 
+  public void setProcessHandler(@Nullable ProcessHandler processHandler) {
+    myProcessHandler = processHandler;
+  }
+
   @Override
   public void update(final AnActionEvent e) {
     update(e.getPresentation(), getTemplatePresentation(), myProcessHandler);
@@ -72,7 +76,7 @@ public class StopProcessAction extends DumbAwareAction implements AnAction.Trans
     stopProcess(myProcessHandler);
   }
 
-  public static void stopProcess(@NotNull ProcessHandler processHandler) {
+  public static void stopProcess(@Nullable ProcessHandler processHandler) {
     if (processHandler instanceof KillableProcess && processHandler.isProcessTerminating()) {
       // process termination was requested, but it's still alive
       // in this case 'force quit' will be performed
@@ -80,11 +84,13 @@ public class StopProcessAction extends DumbAwareAction implements AnAction.Trans
       return;
     }
 
-    if (processHandler.detachIsDefault()) {
-      processHandler.detachProcess();
-    }
-    else {
-      processHandler.destroyProcess();
+    if (processHandler != null) {
+      if (processHandler.detachIsDefault()) {
+        processHandler.detachProcess();
+      }
+      else {
+        processHandler.destroyProcess();
+      }
     }
   }
 
index 4c11fe213535a2f562f8f1b15d03263e9ab89903..7bc0e0c595f806f0740b6cad1e6177c6f6d70eb1 100644 (file)
@@ -127,7 +127,7 @@ public class FindInProjectManager {
                     return processor.process(usage);
                   }
                 };
-                FindInProjectUtil.findUsages(findModelCopy, psiDirectory, myProject, true, consumer, processPresentation);
+                FindInProjectUtil.findUsages(findModelCopy, psiDirectory, myProject, consumer, processPresentation);
               }
               finally {
                 myIsFindInProgress = false;
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java
new file mode 100644 (file)
index 0000000..3650e18
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Copyright 2000-2014 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.find.impl;
+
+import com.intellij.find.FindBundle;
+import com.intellij.find.FindModel;
+import com.intellij.find.ngrams.TrigramIndex;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.progress.EmptyProgressIndicator;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.DumbService;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectCoreUtil;
+import com.intellij.openapi.roots.*;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.util.text.TrigramBuilder;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileFilter;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.cache.CacheManager;
+import com.intellij.psi.impl.cache.impl.id.IdIndex;
+import com.intellij.psi.impl.search.PsiSearchHelperImpl;
+import com.intellij.psi.search.*;
+import com.intellij.usageView.UsageInfo;
+import com.intellij.usages.FindUsagesProcessPresentation;
+import com.intellij.usages.UsageLimitUtil;
+import com.intellij.usages.impl.UsageViewManagerImpl;
+import com.intellij.util.CommonProcessors;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.indexing.FileBasedIndex;
+import com.intellij.util.indexing.FileBasedIndexImpl;
+import gnu.trove.TIntHashSet;
+import gnu.trove.TIntIterator;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * @author peter
+ */
+class FindInProjectTask {
+  private static final int FILES_SIZE_LIMIT = 70 * 1024 * 1024; // megabytes.
+  private static final int SINGLE_FILE_SIZE_LIMIT = 5 * 1024 * 1024; // megabytes.
+  private final FindModel myFindModel;
+  private final Project myProject;
+  private final PsiManager myPsiManager;
+  @Nullable private final PsiDirectory myPsiDirectory;
+  private final FileIndex myFileIndex;
+  private final Condition<VirtualFile> myFileMask;
+  private final ProgressIndicator myProgress;
+  @Nullable private final Module myModule;
+  private final Set<PsiFile> myLargeFiles = ContainerUtil.newTroveSet();
+  private boolean myWarningShown;
+
+  FindInProjectTask(@NotNull final FindModel findModel,
+                    @NotNull final Project project,
+                    @Nullable final PsiDirectory psiDirectory) {
+    myFindModel = findModel;
+    myProject = project;
+    myPsiDirectory = psiDirectory;
+    myPsiManager = PsiManager.getInstance(project);
+
+    final String moduleName = findModel.getModuleName();
+    myModule = moduleName == null ? null : ApplicationManager.getApplication().runReadAction(new Computable<Module>() {
+      @Override
+      public Module compute() {
+        return ModuleManager.getInstance(project).findModuleByName(moduleName);
+      }
+    });
+    myFileIndex = myModule == null ?
+                  ProjectRootManager.getInstance(project).getFileIndex() :
+                  ModuleRootManager.getInstance(myModule).getFileIndex();
+
+    final String filter = findModel.getFileFilter();
+    final Pattern pattern = FindInProjectUtil.createFileMaskRegExp(filter);
+
+    //noinspection unchecked
+    myFileMask = pattern == null ? Condition.TRUE : new Condition<VirtualFile>() {
+      @Override
+      public boolean value(VirtualFile file) {
+        return file != null && pattern.matcher(file.getName()).matches();
+      }
+    };
+
+    final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
+    myProgress = progress != null ? progress : new EmptyProgressIndicator();
+  }
+
+  public void findUsages(@NotNull final Processor<UsageInfo> consumer, @NotNull FindUsagesProcessPresentation processPresentation) {
+    try {
+      myProgress.setIndeterminate(true);
+      myProgress.setText("Scanning indexed files...");
+      final Set<PsiFile> filesForFastWordSearch = getFilesForFastWordSearch();
+      myProgress.setIndeterminate(false);
+
+      searchInFiles(consumer, processPresentation, filesForFastWordSearch);
+
+      myProgress.setIndeterminate(true);
+      myProgress.setText("Scanning non-indexed files...");
+      final Collection<PsiFile> otherFiles = collectFilesInScope(filesForFastWordSearch);
+      myProgress.setIndeterminate(false);
+
+      searchInFiles(consumer, processPresentation, otherFiles);
+    }
+    catch (ProcessCanceledException e) {
+      // fine
+    }
+
+    if (!myLargeFiles.isEmpty()) {
+      processPresentation.setLargeFilesWereNotScanned(myLargeFiles);
+    }
+
+    if (!myProgress.isCanceled()) {
+      myProgress.setText(FindBundle.message("find.progress.search.completed"));
+    }
+  }
+
+  private void searchInFiles(Processor<UsageInfo> consumer, FindUsagesProcessPresentation processPresentation, Collection<PsiFile> psiFiles) {
+    int i = 0;
+    long totalFilesSize = 0;
+    int count = 0;
+
+    for (final PsiFile psiFile : psiFiles) {
+      final VirtualFile virtualFile = psiFile.getVirtualFile();
+      final int index = i++;
+      if (virtualFile == null) continue;
+
+      long fileLength = UsageViewManagerImpl.getFileLength(virtualFile);
+      if (fileLength == -1) continue; // Binary or invalid
+
+      if (ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile) && !Registry.is("find.search.in.project.files")) continue;
+
+      if (fileLength > SINGLE_FILE_SIZE_LIMIT) {
+        myLargeFiles.add(psiFile);
+        continue;
+      }
+
+      myProgress.checkCanceled();
+      myProgress.setFraction((double)index / psiFiles.size());
+      String text = FindBundle.message("find.searching.for.string.in.file.progress",
+                                       myFindModel.getStringToFind(), virtualFile.getPresentableUrl());
+      myProgress.setText(text);
+      myProgress.setText2(FindBundle.message("find.searching.for.string.in.file.occurrences.progress", count));
+
+      int countInFile = FindInProjectUtil.processUsagesInFile(psiFile, myFindModel, consumer);
+
+      count += countInFile;
+      if (countInFile > 0) {
+        totalFilesSize += fileLength;
+        if (totalFilesSize > FILES_SIZE_LIMIT && !myWarningShown) {
+          myWarningShown = true;
+          String message = FindBundle.message("find.excessive.total.size.prompt",
+                                              UsageViewManagerImpl.presentableSize(totalFilesSize),
+                                              ApplicationNamesInfo.getInstance().getProductName());
+          UsageLimitUtil.showAndCancelIfAborted(myProject, message, processPresentation.getUsageViewPresentation());
+        }
+      }
+    }
+  }
+
+  @NotNull
+  private Collection<PsiFile> collectFilesInScope(@NotNull final Set<PsiFile> alreadySearched) {
+    SearchScope customScope = myFindModel.getCustomScope();
+    final GlobalSearchScope globalCustomScope = toGlobal(customScope);
+
+    final boolean skipIndexed = canRelyOnIndices();
+
+    class EnumContentIterator implements ContentIterator {
+      final Set<PsiFile> myFiles = new LinkedHashSet<PsiFile>();
+
+      @Override
+      public boolean processFile(@NotNull final VirtualFile virtualFile) {
+        ApplicationManager.getApplication().runReadAction(new Runnable() {
+          public void run() {
+            ProgressManager.checkCanceled();
+            if (virtualFile.isDirectory() || !virtualFile.isValid() ||
+                !myFileMask.value(virtualFile) ||
+                (globalCustomScope != null && !globalCustomScope.contains(virtualFile))) {
+              return;
+            }
+
+            if (skipIndexed && isCoveredByIdIndex(virtualFile)) {
+              return;
+            }
+
+            PsiFile psiFile = myPsiManager.findFile(virtualFile);
+            if (psiFile != null && !(psiFile instanceof PsiBinaryFile) && !alreadySearched.contains(psiFile)) {
+              PsiFile sourceFile = (PsiFile)psiFile.getNavigationElement();
+              if (sourceFile != null) psiFile = sourceFile;
+              myFiles.add(psiFile);
+            }
+          }
+        });
+        return true;
+      }
+
+      @NotNull
+      private Collection<PsiFile> getFiles() {
+        return myFiles;
+      }
+    }
+
+    EnumContentIterator iterator = new EnumContentIterator();
+
+    if (customScope instanceof LocalSearchScope) {
+      for (VirtualFile file : getLocalScopeFiles((LocalSearchScope)customScope)) {
+        iterator.processFile(file);
+      }
+    }
+    else if (myPsiDirectory != null) {
+      myFileIndex.iterateContentUnderDirectory(myPsiDirectory.getVirtualFile(), iterator);
+    }
+    else {
+      boolean success = myFileIndex.iterateContent(iterator);
+      if (success && globalCustomScope != null && globalCustomScope.isSearchInLibraries()) {
+        final VirtualFile[] librarySources = ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile[]>() {
+          @Override
+          public VirtualFile[] compute() {
+            OrderEnumerator enumerator = myModule == null ? OrderEnumerator.orderEntries(myProject) : OrderEnumerator.orderEntries(myModule);
+            return enumerator.withoutModuleSourceEntries().withoutDepModules().getSourceRoots();
+          }
+        });
+        iterateAll(librarySources, globalCustomScope, iterator);
+      }
+    }
+    return iterator.getFiles();
+  }
+
+  private static boolean isCoveredByIdIndex(VirtualFile file) {
+    return IdIndex.isIndexable(FileBasedIndexImpl.getFileType(file)) &&
+           ((FileBasedIndexImpl)FileBasedIndex.getInstance()).isIndexingCandidate(file, IdIndex.NAME);
+  }
+
+  private static boolean iterateAll(@NotNull VirtualFile[] files, @NotNull final GlobalSearchScope searchScope, @NotNull final ContentIterator iterator) {
+    final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
+    final VirtualFileFilter contentFilter = new VirtualFileFilter() {
+      @Override
+      public boolean accept(@NotNull final VirtualFile file) {
+        return file.isDirectory() ||
+               !fileTypeManager.isFileIgnored(file) && !file.getFileType().isBinary() && searchScope.contains(file);
+      }
+    };
+    for (VirtualFile file : files) {
+      if (!VfsUtilCore.iterateChildrenRecursively(file, contentFilter, iterator)) return false;
+    }
+    return true;
+  }
+
+  @Nullable
+  private GlobalSearchScope toGlobal(@Nullable final SearchScope scope) {
+    if (scope instanceof GlobalSearchScope || scope == null) {
+      return (GlobalSearchScope)scope;
+    }
+    return ApplicationManager.getApplication().runReadAction(new Computable<GlobalSearchScope>() {
+      @Override
+      public GlobalSearchScope compute() {
+        return GlobalSearchScope.filesScope(myProject, getLocalScopeFiles((LocalSearchScope)scope));
+      }
+    });
+  }
+
+  @NotNull
+  private static Set<VirtualFile> getLocalScopeFiles(@NotNull LocalSearchScope scope) {
+    Set<VirtualFile> files = new LinkedHashSet<VirtualFile>();
+    for (PsiElement element : scope.getScope()) {
+      PsiFile file = element.getContainingFile();
+      if (file != null) {
+        ContainerUtil.addIfNotNull(files, file.getVirtualFile());
+      }
+    }
+    return files;
+  }
+
+  private boolean canRelyOnIndices() {
+    if (DumbService.isDumb(myProject)) return false;
+
+    if (myFindModel.isRegularExpressions()) return false;
+
+    // a local scope may be over a non-indexed file
+    if (myFindModel.getCustomScope() instanceof LocalSearchScope) return false;
+
+    String text = myFindModel.getStringToFind();
+    if (StringUtil.isEmptyOrSpaces(text)) return false;
+
+    if (TrigramIndex.ENABLED) return !TrigramBuilder.buildTrigram(text).isEmpty();
+
+    // $ is used to separate words when indexing plain-text files but not when indexing
+    // Java identifiers, so we can't consistently break a string containing $ characters into words
+
+    return myFindModel.isWholeWordsOnly() && text.indexOf('$') < 0;
+  }
+
+
+  @NotNull
+  private Set<PsiFile> getFilesForFastWordSearch() {
+    String stringToFind = myFindModel.getStringToFind();
+    if (stringToFind.isEmpty() || DumbService.getInstance(myProject).isDumb()) {
+      return Collections.emptySet();
+    }
+
+    SearchScope customScope = myFindModel.getCustomScope();
+    GlobalSearchScope scope = myPsiDirectory != null
+                              ? GlobalSearchScopesCore.directoryScope(myPsiDirectory, true)
+                              : myModule != null
+                                ? myModule.getModuleContentScope()
+                                : customScope instanceof GlobalSearchScope
+                                  ? (GlobalSearchScope)customScope
+                                  : toGlobal(customScope);
+    if (scope == null) {
+      scope = ProjectScope.getContentScope(myProject);
+    }
+
+    final Set<PsiFile> resultFiles = new LinkedHashSet<PsiFile>();
+
+    if (TrigramIndex.ENABLED) {
+      Set<Integer> keys = ContainerUtil.newTroveSet();
+      TIntHashSet trigrams = TrigramBuilder.buildTrigram(stringToFind);
+      TIntIterator it = trigrams.iterator();
+      while (it.hasNext()) {
+        keys.add(it.next());
+      }
+
+      if (!keys.isEmpty()) {
+        List<VirtualFile> hits = new ArrayList<VirtualFile>();
+        FileBasedIndex.getInstance().getFilesWithKey(TrigramIndex.INDEX_ID, keys, new CommonProcessors.CollectProcessor<VirtualFile>(hits), scope);
+
+        for (VirtualFile hit : hits) {
+          if (myFileMask.value(hit)) {
+            resultFiles.add(findFile(hit));
+          }
+        }
+
+        return resultFiles;
+      }
+    }
+
+    PsiSearchHelperImpl helper = (PsiSearchHelperImpl)PsiSearchHelper.SERVICE.getInstance(myProject);
+    helper.processFilesWithText(scope, UsageSearchContext.ANY, myFindModel.isCaseSensitive(), stringToFind, new Processor<VirtualFile>() {
+      @Override
+      public boolean process(VirtualFile file) {
+        if (myFileMask.value(file)) {
+          ContainerUtil.addIfNotNull(resultFiles, findFile(file));
+        }
+        return true;
+      }
+    });
+
+    // in case our word splitting is incorrect
+    for (PsiFile file : CacheManager.SERVICE.getInstance(myProject)
+      .getFilesWithWord(stringToFind, UsageSearchContext.ANY, scope, myFindModel.isCaseSensitive())) {
+      if (myFileMask.value(file.getVirtualFile())) {
+        resultFiles.add(file);
+      }
+    }
+
+    return resultFiles;
+  }
+
+  private PsiFile findFile(@NotNull final VirtualFile virtualFile) {
+    return ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
+      @Override
+      public PsiFile compute() {
+        return myPsiManager.findFile(virtualFile);
+      }
+    });
+  }
+
+}
index 2fefcc9649d47b14d43ea287dee4a0258ffa5313..d788d9c6abe943dcc6ceaa49d11574280bb1e211 100644 (file)
@@ -19,73 +19,54 @@ package com.intellij.find.impl;
 import com.intellij.BundleBase;
 import com.intellij.find.*;
 import com.intellij.find.findInProject.FindInProjectManager;
-import com.intellij.find.ngrams.TrigramIndex;
 import com.intellij.icons.AllIcons;
 import com.intellij.ide.DataManager;
 import com.intellij.navigation.ItemPresentation;
 import com.intellij.openapi.actionSystem.*;
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ApplicationNamesInfo;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.fileEditor.FileEditor;
-import com.intellij.openapi.fileTypes.FileTypeManager;
 import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleManager;
 import com.intellij.openapi.progress.ProcessCanceledException;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.progress.util.ProgressWrapper;
 import com.intellij.openapi.progress.util.TooManyUsagesStatus;
-import com.intellij.openapi.project.DumbService;
 import com.intellij.openapi.project.IndexNotReadyException;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectCoreUtil;
-import com.intellij.openapi.roots.*;
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.Factory;
-import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.TextRange;
-import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.util.text.TrigramBuilder;
-import com.intellij.openapi.vfs.*;
+import com.intellij.openapi.vfs.LocalFileProvider;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.openapi.vfs.ex.VirtualFileManagerEx;
 import com.intellij.psi.*;
-import com.intellij.psi.impl.cache.CacheManager;
-import com.intellij.psi.impl.cache.impl.id.IdIndex;
-import com.intellij.psi.search.*;
+import com.intellij.psi.search.LocalSearchScope;
+import com.intellij.psi.search.SearchScope;
 import com.intellij.ui.content.Content;
 import com.intellij.usageView.UsageInfo;
 import com.intellij.usageView.UsageViewManager;
 import com.intellij.usages.ConfigurableUsageTarget;
 import com.intellij.usages.FindUsagesProcessPresentation;
-import com.intellij.usages.UsageLimitUtil;
 import com.intellij.usages.UsageViewPresentation;
-import com.intellij.usages.impl.UsageViewManagerImpl;
-import com.intellij.util.CommonProcessors;
 import com.intellij.util.Function;
 import com.intellij.util.PatternUtil;
 import com.intellij.util.Processor;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.indexing.FileBasedIndex;
-import com.intellij.util.indexing.FileBasedIndexImpl;
-import gnu.trove.THashSet;
-import gnu.trove.TIntHashSet;
-import gnu.trove.TIntIterator;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import java.io.File;
-import java.util.*;
+import java.util.List;
 import java.util.regex.Pattern;
 
 public class FindInProjectUtil {
   private static final int USAGES_PER_READ_ACTION = 100;
-  private static final int FILES_SIZE_LIMIT = 70 * 1024 * 1024; // megabytes.
-  private static final int SINGLE_FILE_SIZE_LIMIT = 5 * 1024 * 1024; // megabytes.
 
   private FindInProjectUtil() {}
 
@@ -156,34 +137,6 @@ public class FindInProjectUtil {
     return virtualFile == null ? null : psiManager.findDirectory(virtualFile);
   }
 
-  private static void addFilesUnderDirectory(@NotNull PsiDirectory directory,
-                                             @NotNull Collection<PsiFile> fileList,
-                                             boolean isRecursive,
-                                             @Nullable Pattern fileMaskRegExp) {
-    final PsiElement[] children = directory.getChildren();
-
-    for (PsiElement child : children) {
-      if (child instanceof PsiFile &&
-          (fileMaskRegExp == null ||
-           fileMaskRegExp.matcher(((PsiFile)child).getName()).matches()
-          )
-        ) {
-        PsiFile file = (PsiFile)child;
-        PsiFile sourceFile = (PsiFile)file.getNavigationElement();
-        if (sourceFile != null) file = sourceFile;
-        fileList.add(file);
-      }
-      else if (isRecursive && child instanceof PsiDirectory) {
-        addFilesUnderDirectory((PsiDirectory)child, fileList, isRecursive, fileMaskRegExp);
-      }
-    }
-  }
-
-  @Nullable
-  private static Pattern createFileMaskRegExp(@NotNull FindModel findModel) {
-    final String filter = findModel.getFileFilter();
-    return createFileMaskRegExp(filter);
-  }
 
   @Nullable
   public static Pattern createFileMaskRegExp(@Nullable String filter) {
@@ -210,74 +163,12 @@ public class FindInProjectUtil {
   public static void findUsages(@NotNull FindModel findModel,
                                 final PsiDirectory psiDirectory,
                                 @NotNull final Project project,
-                                boolean showWarnings,
                                 @NotNull final Processor<UsageInfo> consumer,
                                 @NotNull FindUsagesProcessPresentation processPresentation) {
-    final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
-
-    final Collection<PsiFile> psiFiles = getFilesToSearchIn(findModel, project, psiDirectory);
-    try {
-      final Set<PsiFile> largeFiles = new THashSet<PsiFile>();
-
-      int i = 0;
-      long totalFilesSize = 0;
-      int count = 0;
-      final boolean[] warningShown = {false};
-
-      for (final PsiFile psiFile : psiFiles) {
-        final VirtualFile virtualFile = psiFile.getVirtualFile();
-        final int index = i++;
-        if (virtualFile == null) continue;
-
-        long fileLength = UsageViewManagerImpl.getFileLength(virtualFile);
-        if (fileLength == -1) continue; // Binary or invalid
-
-        if (ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile) && !Registry.is("find.search.in.project.files")) continue;
-
-        if (fileLength > SINGLE_FILE_SIZE_LIMIT) {
-          largeFiles.add(psiFile);
-          continue;
-        }
-
-        if (progress != null) {
-          progress.checkCanceled();
-          progress.setFraction((double)index / psiFiles.size());
-          String text = FindBundle.message("find.searching.for.string.in.file.progress",
-                                           findModel.getStringToFind(), virtualFile.getPresentableUrl());
-          progress.setText(text);
-          progress.setText2(FindBundle.message("find.searching.for.string.in.file.occurrences.progress", count));
-        }
-
-        int countInFile = processUsagesInFile(psiFile, findModel, consumer);
-
-        count += countInFile;
-        if (countInFile > 0) {
-          totalFilesSize += fileLength;
-          if (totalFilesSize > FILES_SIZE_LIMIT && !warningShown[0]) {
-            warningShown[0] = true;
-            String message = FindBundle.message("find.excessive.total.size.prompt",
-                                                UsageViewManagerImpl.presentableSize(totalFilesSize),
-                                                ApplicationNamesInfo.getInstance().getProductName());
-            UsageLimitUtil.showAndCancelIfAborted(project, message, processPresentation.getUsageViewPresentation());
-          }
-        }
-      }
-
-
-      if (!largeFiles.isEmpty()) {
-        processPresentation.setLargeFilesWereNotScanned(largeFiles);
-      }
-    }
-    catch (ProcessCanceledException e) {
-      // fine
-    }
-
-    if (progress != null && !progress.isCanceled()) {
-      progress.setText(FindBundle.message("find.progress.search.completed"));
-    }
+    new FindInProjectTask(findModel, project, psiDirectory).findUsages(consumer, processPresentation);
   }
 
-  private static int processUsagesInFile(@NotNull final PsiFile psiFile,
+  static int processUsagesInFile(@NotNull final PsiFile psiFile,
                                          @NotNull final FindModel findModel,
                                          @NotNull final Processor<UsageInfo> consumer) {
     if (findModel.getStringToFind().isEmpty()) {
@@ -317,279 +208,6 @@ public class FindInProjectUtil {
     return count;
   }
 
-  private static PsiFile findFile(@NotNull final PsiManager psiManager, @NotNull final VirtualFile virtualFile) {
-    return ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
-      @Override
-      public PsiFile compute() {
-        return psiManager.findFile(virtualFile);
-      }
-    });
-  }
-
-  @NotNull
-  private static Collection<PsiFile> getFilesToSearchIn(@NotNull final FindModel findModel,
-                                                        @NotNull final Project project,
-                                                        final PsiDirectory psiDirectory) {
-    final String moduleName = findModel.getModuleName();
-    final Module module = moduleName == null ? null : ApplicationManager.getApplication().runReadAction(new Computable<Module>() {
-      @Override
-      public Module compute() {
-        return ModuleManager.getInstance(project).findModuleByName(moduleName);
-      }
-    });
-    final FileIndex fileIndex = module == null ?
-                                ProjectRootManager.getInstance(project).getFileIndex() :
-                                ModuleRootManager.getInstance(module).getFileIndex();
-
-    if (psiDirectory == null || findModel.isWithSubdirectories() && fileIndex.isInContent(psiDirectory.getVirtualFile())) {
-      final Pattern fileMaskRegExp = createFileMaskRegExp(findModel);
-      // optimization
-      Pair<Boolean, Collection<PsiFile>> fastWords = getFilesForFastWordSearch(findModel, project, psiDirectory, fileMaskRegExp, module, fileIndex);
-      final Collection<PsiFile> filesForFastWordSearch = fastWords.getSecond();
-
-      final boolean useIdIndex = fastWords.getFirst() && canOptimizeForFastWordSearch(findModel);
-
-      SearchScope customScope = findModel.getCustomScope();
-      final GlobalSearchScope globalCustomScope = toGlobal(project, customScope);
-
-      class EnumContentIterator implements ContentIterator {
-        final Set<PsiFile> myFiles = new LinkedHashSet<PsiFile>(filesForFastWordSearch);
-        final PsiManager psiManager = PsiManager.getInstance(project);
-
-        @Override
-        public boolean processFile(@NotNull VirtualFile virtualFile) {
-          ProgressManager.checkCanceled();
-          if (virtualFile.isDirectory() ||
-              (fileMaskRegExp != null && !fileMaskRegExp.matcher(virtualFile.getName()).matches()) ||
-              (globalCustomScope != null && !globalCustomScope.contains(virtualFile))) {
-            return true;
-          }
-          
-          if (useIdIndex && isCoveredByIdIndex(virtualFile)) {
-            return true;
-          }
-
-          PsiFile psiFile = findFile(psiManager, virtualFile);
-          if (psiFile != null && !(psiFile instanceof PsiBinaryFile)) {
-            myFiles.add(psiFile);
-          }
-          return true;
-        }
-
-        @NotNull
-        private Collection<PsiFile> getFiles() {
-          return myFiles;
-        }
-      }
-
-      EnumContentIterator iterator = new EnumContentIterator();
-
-      if (customScope instanceof LocalSearchScope) {
-        for (VirtualFile file : getLocalScopeFiles((LocalSearchScope)customScope)) {
-          iterator.processFile(file);
-        }
-      }
-
-      if (psiDirectory == null) {
-        boolean success = fileIndex.iterateContent(iterator);
-        if (success && globalCustomScope != null && globalCustomScope.isSearchInLibraries()) {
-          final VirtualFile[] librarySources = ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile[]>() {
-            @Override
-            public VirtualFile[] compute() {
-              OrderEnumerator enumerator = module == null ? OrderEnumerator.orderEntries(project) : OrderEnumerator.orderEntries(module);
-              return enumerator.withoutModuleSourceEntries().withoutDepModules().getSourceRoots();
-            }
-          });
-          iterateAll(librarySources, globalCustomScope, iterator);
-        }
-      }
-      else {
-        fileIndex.iterateContentUnderDirectory(psiDirectory.getVirtualFile(), iterator);
-      }
-      return iterator.getFiles();
-    }
-    if (psiDirectory.isValid()) {
-      final Collection<PsiFile> fileList = new THashSet<PsiFile>();
-      ApplicationManager.getApplication().runReadAction(new Runnable() {
-        @Override
-        public void run() {
-          addFilesUnderDirectory(psiDirectory, fileList, findModel.isWithSubdirectories(), createFileMaskRegExp(findModel));
-        }
-      });
-
-      return fileList;
-    }
-    return Collections.emptyList();
-  }
-
-  private static boolean isCoveredByIdIndex(VirtualFile file) {
-    return IdIndex.isIndexable(FileBasedIndexImpl.getFileType(file)) && 
-           ((FileBasedIndexImpl)FileBasedIndex.getInstance()).isIndexingCandidate(file, IdIndex.NAME);
-  }
-
-  private static boolean iterateAll(@NotNull VirtualFile[] files, @NotNull final GlobalSearchScope searchScope, @NotNull final ContentIterator iterator) {
-    final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
-    final VirtualFileFilter contentFilter = new VirtualFileFilter() {
-      @Override
-      public boolean accept(@NotNull final VirtualFile file) {
-        return file.isDirectory() ||
-               !fileTypeManager.isFileIgnored(file) && !file.getFileType().isBinary() && searchScope.contains(file);
-      }
-    };
-    for (VirtualFile file : files) {
-      if (!VfsUtilCore.iterateChildrenRecursively(file, contentFilter, iterator)) return false;
-    }
-    return true;
-  }
-
-  @Nullable
-  private static GlobalSearchScope toGlobal(@NotNull final Project project, @Nullable final SearchScope scope) {
-    if (scope instanceof GlobalSearchScope || scope == null) {
-      return (GlobalSearchScope)scope;
-    }
-    return ApplicationManager.getApplication().runReadAction(new Computable<GlobalSearchScope>() {
-      @Override
-      public GlobalSearchScope compute() {
-        return GlobalSearchScope.filesScope(project, getLocalScopeFiles((LocalSearchScope)scope));
-      }
-    });
-  }
-
-  @NotNull
-  private static Set<VirtualFile> getLocalScopeFiles(@NotNull LocalSearchScope scope) {
-    Set<VirtualFile> files = new LinkedHashSet<VirtualFile>();
-    for (PsiElement element : scope.getScope()) {
-      PsiFile file = element.getContainingFile();
-      if (file != null) {
-        ContainerUtil.addIfNotNull(files, file.getVirtualFile());
-      }
-    }
-    return files;
-  }
-
-  @NotNull
-  private static Pair<Boolean, Collection<PsiFile>> getFilesForFastWordSearch(@NotNull final FindModel findModel,
-                                                                              @NotNull final Project project,
-                                                                              @Nullable final PsiDirectory psiDirectory,
-                                                                              final Pattern fileMaskRegExp,
-                                                                              @Nullable final Module module,
-                                                                              @NotNull FileIndex fileIndex) {
-    if (DumbService.getInstance(project).isDumb()) {
-      return new Pair<Boolean, Collection<PsiFile>>(false, Collections.<PsiFile>emptyList());
-    }
-
-    final PsiManager pm = PsiManager.getInstance(project);
-    CacheManager cacheManager = CacheManager.SERVICE.getInstance(project);
-    SearchScope customScope = findModel.getCustomScope();
-    GlobalSearchScope scope = psiDirectory != null
-                              ? GlobalSearchScopesCore.directoryScope(psiDirectory, true)
-                              : module != null
-                                ? module.getModuleContentScope()
-                                : customScope instanceof GlobalSearchScope
-                                  ? (GlobalSearchScope)customScope
-                                  : toGlobal(project, customScope);
-    if (scope == null) {
-      scope = ProjectScope.getContentScope(project);
-    }
-
-    Set<Integer> keys = new THashSet<Integer>(30);
-    final Set<PsiFile> resultFiles = new THashSet<PsiFile>();
-    boolean fast = false;
-
-    String stringToFind = findModel.getStringToFind();
-    if (TrigramIndex.ENABLED) {
-      TIntHashSet trigrams = TrigramBuilder.buildTrigram(stringToFind);
-      TIntIterator it = trigrams.iterator();
-      while (it.hasNext()) {
-        keys.add(it.next());
-      }
-
-      if (!keys.isEmpty()) {
-        fast = true;
-        List<VirtualFile> hits = new ArrayList<VirtualFile>();
-        FileBasedIndex.getInstance().getFilesWithKey(TrigramIndex.INDEX_ID, keys, new CommonProcessors.CollectProcessor<VirtualFile>(hits), scope);
-
-        for (VirtualFile hit : hits) {
-          resultFiles.add(findFile(pm, hit));
-        }
-
-        filterMaskedFiles(resultFiles, fileMaskRegExp);
-        if (resultFiles.isEmpty()) return new Pair<Boolean, Collection<PsiFile>>(true, resultFiles);
-      }
-    }
-
-
-    // $ is used to separate words when indexing plain-text files but not when indexing
-    // Java identifiers, so we can't consistently break a string containing $ characters into words
-
-    fast |= findModel.isWholeWordsOnly() && stringToFind.indexOf('$') < 0;
-
-    List<String> words = StringUtil.getWordsInStringLongestFirst(stringToFind);
-
-    for (int i = 0; i < words.size(); i++) {
-      String word = words.get(i);
-
-      PsiFile[] files = cacheManager.getFilesWithWord(word, UsageSearchContext.ANY, scope, findModel.isCaseSensitive());
-      if (files.length == 0) {
-        resultFiles.clear();
-        break;
-      }
-
-      final List<PsiFile> psiFiles = Arrays.asList(files);
-
-      if (i == 0 && keys.isEmpty()) {
-        resultFiles.addAll(psiFiles);
-      }
-      else {
-        resultFiles.retainAll(psiFiles);
-      }
-
-      filterMaskedFiles(resultFiles, fileMaskRegExp);
-      if (resultFiles.isEmpty()) break;
-    }
-
-    if (stringToFind.isEmpty()) {
-      fileIndex.iterateContent(new ContentIterator() {
-        @Override
-        public boolean processFile(VirtualFile file) {
-          if (!file.isDirectory() && fileMaskRegExp.matcher(file.getName()).matches()) {
-            PsiFile psiFile = findFile(pm, file);
-            if (psiFile != null) {
-              resultFiles.add(psiFile);
-            }
-          }
-          return true;
-        }
-      });
-    }
-    else {
-      // in case our word splitting is incorrect
-      PsiFile[] allWordsFiles =
-        cacheManager.getFilesWithWord(stringToFind, UsageSearchContext.ANY, scope, findModel.isCaseSensitive());
-      ContainerUtil.addAll(resultFiles, allWordsFiles);
-
-      filterMaskedFiles(resultFiles, fileMaskRegExp);
-    }
-
-    return new Pair<Boolean, Collection<PsiFile>>(fast, resultFiles);
-  }
-
-  private static void filterMaskedFiles(@NotNull final Set<PsiFile> resultFiles, @Nullable final Pattern fileMaskRegExp) {
-    if (fileMaskRegExp != null) {
-      for (Iterator<PsiFile> iterator = resultFiles.iterator(); iterator.hasNext();) {
-        PsiFile file = iterator.next();
-        if (!fileMaskRegExp.matcher(file.getName()).matches()) {
-          iterator.remove();
-        }
-      }
-    }
-  }
-
-  private static boolean canOptimizeForFastWordSearch(@NotNull final FindModel findModel) {
-    return !findModel.isRegularExpressions()
-           && (findModel.getCustomScope() == null || findModel.getCustomScope() instanceof GlobalSearchScope);
-  }
-
   private static int addToUsages(@NotNull Document document, @NotNull Processor<UsageInfo> consumer, @NotNull FindModel findModel,
                                  @NotNull final PsiFile psiFile, @NotNull int[] offsetRef, int maxUsages) {
     int count = 0;
index 86fe9de9b5a863c82ccb34463cdbce85d4f0cd95..7e220c1493696a64bdaab90167dad9ee492bebb2 100644 (file)
@@ -569,7 +569,7 @@ public class ReplaceInProjectManager {
             myIsFindInProgress = true;
 
             FindInProjectUtil.findUsages(myFindModelCopy, myPsiDirectory, myProject,
-                                         true, new AdapterProcessor<UsageInfo, Usage>(processor, UsageInfo2UsageAdapter.CONVERTER),
+                                         new AdapterProcessor<UsageInfo, Usage>(processor, UsageInfo2UsageAdapter.CONVERTER),
                                          myProcessPresentation);
           }
           finally {
index 81a7851da874a30d2c82bcd806a48e0a85988a09..69512b3576f95aaacd9c10f67de2deddf56d0dc7 100644 (file)
@@ -23,11 +23,11 @@ import com.intellij.find.FindBundle;
 import com.intellij.find.FindManager;
 import com.intellij.find.FindModel;
 import com.intellij.find.FindResult;
-import com.intellij.openapi.editor.EditorLastActionTracker;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.actionSystem.IdeActions;
 import com.intellij.openapi.editor.Caret;
 import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.EditorLastActionTracker;
 import com.intellij.openapi.editor.ScrollType;
 import com.intellij.openapi.editor.actionSystem.EditorAction;
 import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -145,7 +145,7 @@ public class SelectNextOccurrenceAction extends EditorAction {
 
     private static boolean isRepeatedActionInvocation() {
       String lastActionId = EditorLastActionTracker.getInstance().getLastActionId();
-      return IdeActions.ACTION_SELECT_NEXT_OCCURENCE.equals(lastActionId) || IdeActions.ACTION_UNSELECT_LAST_OCCURENCE.equals(lastActionId);
+      return IdeActions.ACTION_SELECT_NEXT_OCCURENCE.equals(lastActionId) || IdeActions.ACTION_UNSELECT_PREVIOUS_OCCURENCE.equals(lastActionId);
     }
   }
 }
similarity index 93%
rename from platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectLastOccurrenceAction.java
rename to platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java
index 192e41cdfdb66b3408fdffb3c2fceff08c659650..8db261e6336a84f3b7d931ec7a49b883a66cda96 100644 (file)
@@ -23,8 +23,8 @@ import com.intellij.openapi.editor.actionSystem.EditorAction;
 import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
 import org.jetbrains.annotations.Nullable;
 
-public class UnselectLastOccurrenceAction extends EditorAction {
-  protected UnselectLastOccurrenceAction() {
+public class UnselectPreviousOccurrenceAction extends EditorAction {
+  protected UnselectPreviousOccurrenceAction() {
     super(new Handler());
   }
 
index 4a94d1ad3781155fe99053fd13b00de1455f5b72..80188761441315f8a8166707fbe5d9e0d620c0bc 100644 (file)
@@ -33,6 +33,7 @@ import javax.swing.*;
 public class EnforcedPlainTextFileTypeFactory extends FileTypeFactory {
 
   public static final LayeredIcon ENFORCED_PLAIN_TEXT_ICON = new LayeredIcon(2);
+  public static final String ENFORCED_PLAIN_TEXT = "Enforced Plain Text";
 
   static {
     ENFORCED_PLAIN_TEXT_ICON.setIcon(AllIcons.FileTypes.Text, 0);
@@ -59,13 +60,13 @@ public class EnforcedPlainTextFileTypeFactory extends FileTypeFactory {
       @NotNull
       @Override
       public String getName() {
-        return "Enforced Plain Text";
+        return ENFORCED_PLAIN_TEXT;
       }
 
       @NotNull
       @Override
       public String getDescription() {
-        return "Enforced Plain Text";
+        return ENFORCED_PLAIN_TEXT;
       }
 
       @NotNull
index 830681b9ba5e7fbf35e0f2e4d66bb66a582003e0..e8a18e423423d4f951f4e8386eb1f198b16c4e38 100644 (file)
@@ -26,9 +26,8 @@ import com.intellij.openapi.project.ProjectManager;
 import com.intellij.openapi.project.ProjectManagerListener;
 import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
 import com.intellij.openapi.util.EmptyRunnable;
-import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.newvfs.impl.StubVirtualFile;
+import com.intellij.openapi.vfs.VirtualFileWithId;
 import com.intellij.util.containers.ConcurrentHashMap;
 import com.intellij.util.indexing.FileBasedIndex;
 import org.jetbrains.annotations.NotNull;
@@ -45,18 +44,21 @@ import java.util.Map;
  */
 public class EnforcedPlainTextFileTypeManager implements ProjectManagerListener {
   private final Map<Project, Collection<VirtualFile>> myPlainTextFileSets = new ConcurrentHashMap<Project, Collection<VirtualFile>>();
-  private final Ref<Boolean> mySetsInitialized = new Ref<Boolean>(false);
+  private volatile boolean mySetsInitialized = false;
+  private static final Object LOCK = new Object();
 
   public EnforcedPlainTextFileTypeManager() {
     ProjectManager.getInstance().addProjectManagerListener(this);
   }
 
   public boolean isMarkedAsPlainText(VirtualFile file) {
-    if (file instanceof StubVirtualFile || file.isDirectory()) return false;
-    synchronized (mySetsInitialized) {
-      if (!mySetsInitialized.get()) {
-        initPlainTextFileSets();
-        mySetsInitialized.set(true);
+    if (!(file instanceof VirtualFileWithId) || file.isDirectory()) return false;
+    if (!mySetsInitialized) {
+      synchronized (LOCK) {
+        if (!mySetsInitialized) {
+          initPlainTextFileSets();
+          mySetsInitialized = true;
+        }
       }
     }
     for (Project project : myPlainTextFileSets.keySet()) {
@@ -74,7 +76,7 @@ public class EnforcedPlainTextFileTypeManager implements ProjectManagerListener
   }
 
   public static boolean isApplicableFor(@NotNull VirtualFile file) {
-    if (file instanceof StubVirtualFile || file.isDirectory()) return false;
+    if (!(file instanceof VirtualFileWithId) || file.isDirectory()) return false;
     FileType originalType = FileTypeManager.getInstance().getFileTypeByFileName(file.getName());
     return !originalType.isBinary() && originalType != FileTypes.PLAIN_TEXT && originalType != StdFileTypes.JAVA;
   }
@@ -96,7 +98,7 @@ public class EnforcedPlainTextFileTypeManager implements ProjectManagerListener
     fireRootsChanged(filesToSync, isPlainText);
   }
 
-  private static void fireRootsChanged(final Collection<VirtualFile> files, final boolean isAdded) {
+  private void fireRootsChanged(final Collection<VirtualFile> files, final boolean isAdded) {
     ApplicationManager.getApplication().runWriteAction(new Runnable() {
       @Override
       public void run() {
@@ -105,6 +107,7 @@ public class EnforcedPlainTextFileTypeManager implements ProjectManagerListener
           ProjectPlainTextFileTypeManager projectPlainTextFileTypeManager = ProjectPlainTextFileTypeManager.getInstance(project);
           for (VirtualFile file : files) {
             if (projectPlainTextFileTypeManager.hasProjectContaining(file)) {
+              ensureProjectFileSetAdded(project, projectPlainTextFileTypeManager);
               if (isAdded) {
                 projectPlainTextFileTypeManager.addFile(file);
               }
@@ -118,6 +121,13 @@ public class EnforcedPlainTextFileTypeManager implements ProjectManagerListener
     });
   }
 
+  private void ensureProjectFileSetAdded(@NotNull Project project,
+                                         @NotNull ProjectPlainTextFileTypeManager projectPlainTextFileTypeManager) {
+    if (!myPlainTextFileSets.containsKey(project)) {
+      myPlainTextFileSets.put(project, projectPlainTextFileTypeManager.getFiles());
+    }
+  }
+
   private static class EnforcedPlainTextFileTypeManagerHolder {
     private static final EnforcedPlainTextFileTypeManager ourInstance = ServiceManager.getService(EnforcedPlainTextFileTypeManager.class);
   }
index 6cf91fe5a0c06cb4a12165b4f7e6163e0521ccd5..67b19d6fa54f39fb60690ffe12bdef3150ff8daf 100644 (file)
@@ -19,7 +19,7 @@ import com.intellij.openapi.components.PersistentStateComponent;
 import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.VirtualFileManager;
-import com.intellij.openapi.vfs.newvfs.impl.StubVirtualFile;
+import com.intellij.openapi.vfs.VirtualFileWithId;
 import com.intellij.util.containers.HashSet;
 import org.jdom.Attribute;
 import org.jdom.Element;
@@ -37,7 +37,7 @@ public class PersistentFileSetManager implements PersistentStateComponent<Elemen
   private final Set<VirtualFile> myFiles = new HashSet<VirtualFile>();
   
   protected boolean addFile(VirtualFile file) {
-    if (file instanceof StubVirtualFile || file.isDirectory()) return false;
+    if (!(file instanceof VirtualFileWithId) || file.isDirectory()) return false;
     myFiles.add(file);
     return true;
   }
index cd8c1bf76994bfd46e123cd930e017e131acffd9..40e1e793a23f321ccba00ef981fbc8404c75f6d9 100644 (file)
@@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.checkin;
 import com.intellij.ide.todo.TodoFilter;
 import com.intellij.ide.todo.TodoIndexPatternProvider;
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.ComparisonPolicy;
 import com.intellij.openapi.diff.impl.fragments.LineFragment;
@@ -302,7 +303,8 @@ public class TodoCheckinHandlerWorker {
 
   private static ArrayList<LineFragment> getLineFragments(final String fileName, String beforeContent, String afterContent) throws VcsException {
     try {
-      DiffFragment[] woFormattingBlocks = DiffPolicy.LINES_WO_FORMATTING.buildFragments(beforeContent, afterContent);
+      DiffFragment[] woFormattingBlocks =
+        DiffPolicy.LINES_WO_FORMATTING.buildFragments(DiffString.create(beforeContent), DiffString.create(afterContent));
       DiffFragment[] step1lineFragments =
         new DiffCorrection.TrueLineBlocks(ComparisonPolicy.IGNORE_SPACE).correctAndNormalize(woFormattingBlocks);
       return new DiffFragmentsProcessor().process(step1lineFragments);
index a42a1bfab18a75c0604e3133ce0842b10fe26e9c..445ac01260474d0776fb0ad0817c825071cccf44 100644 (file)
@@ -240,7 +240,7 @@ public class GeneralCommandLine implements UserDataHolder {
       commands = CommandLineUtil.toCommandLine(myExePath, myProgramParams.getList());
     }
     catch (ExecutionException e) {
-      LOG.warn(e);
+      LOG.info(e);
       throw e;
     }
 
@@ -248,7 +248,7 @@ public class GeneralCommandLine implements UserDataHolder {
       return startProcess(commands);
     }
     catch (IOException e) {
-      LOG.warn(e);
+      LOG.info(e);
       throw new ProcessNotCreatedException(e.getMessage(), e, this);
     }
   }
index b515b84e8f3f5e2daf38060e3ec507c1e3d94562..22f9be6347212c41b2f083db9c4f851c96760ffa 100644 (file)
@@ -115,7 +115,7 @@ public interface IdeActions {
   @NonNls String ACTION_FIND_NEXT = "FindNext";
   @NonNls String ACTION_FIND_PREVIOUS = "FindPrevious";
   @NonNls String ACTION_SELECT_NEXT_OCCURENCE = "SelectNextOccurrence";
-  @NonNls String ACTION_UNSELECT_LAST_OCCURENCE = "UnselectLastOccurrence";
+  @NonNls String ACTION_UNSELECT_PREVIOUS_OCCURENCE = "UnselectPreviousOccurrence";
   @NonNls String ACTION_COMPILE = "Compile";
   @NonNls String ACTION_COMPILE_PROJECT = "CompileProject";
   @NonNls String ACTION_MAKE_MODULE = "MakeModule";
index 55960fb8296e2012fcd25e076c578b137b06800b..9a0af4ad83a2c1fd3a224e3519fff2a68f8aad70 100644 (file)
@@ -16,6 +16,7 @@
 package com.intellij.openapi.diff;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.EditorFactory;
 import com.intellij.openapi.fileEditor.OpenFileDescriptor;
@@ -29,8 +30,8 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.io.*;
-import java.nio.charset.Charset;
 import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
 
 /**
  * Allows to compare some text not associated with file or document.
@@ -210,16 +211,18 @@ public class SimpleContent extends DiffContent {
   private static class LineSeparators {
     private String mySeparator;
 
-    public String correctText(String text) {
-      LineTokenizer lineTokenizer = new LineTokenizer(text);
-      String[] lines = lineTokenizer.execute();
+    @NotNull
+    public String correctText(@NotNull String text) {
+      DiffString.LineTokenizer lineTokenizer = new DiffString.LineTokenizer(DiffString.create(text));
+      DiffString[] lines = lineTokenizer.execute();
       mySeparator = lineTokenizer.getLineSeparator();
       LOG.assertTrue(mySeparator == null || !mySeparator.isEmpty());
       if (mySeparator == null) mySeparator = SystemProperties.getLineSeparator();
-      return LineTokenizer.concatLines(lines);
+      return DiffString.concatenate(lines).toString();
     }
 
-    public String restoreText(String text) {
+    @NotNull
+    public String restoreText(@NotNull String text) {
       if (mySeparator == null) throw new NullPointerException();
       return text.replaceAll("\n", mySeparator);
     }
index b975ff8a666ddd426d376e666513524d3d2b82bd..1f29a08d8612183f058133471ce20bc039ff8658 100644 (file)
@@ -122,6 +122,9 @@ Button.darcula.selection.color2=233143
 Button.darcula.selectedButtonForeground=bbbbbb
 Button.darcula.disabledText.shadow=00000000
 
+ToggleButton.border=com.intellij.ide.ui.laf.darcula.ui.DarculaButtonPainter
+ToggleButtonUI=com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI
+
 MenuItem.acceleratorForeground=eeeeee
 PopupMenu.translucentBackground=3c3f41
 
index f4fbc75dd935e8ab3956070af2b0c1ef8b2f5e77..8deb957d21f1d9d31548360bf3c0a8fa7c06d49a 100644 (file)
@@ -50,7 +50,7 @@ public class DarculaButtonUI extends BasicButtonUI {
       final Insets ins = border.getBorderInsets(c);
       final int yOff = (ins.top + ins.bottom) / 4;
       if (!square) {
-        if (((JButton)c).isDefaultButton()) {
+        if (c instanceof JButton && ((JButton)c).isDefaultButton()) {
           ((Graphics2D)g).setPaint(UIUtil.getGradientPaint(0, 0, getSelectedButtonColor1(), 0, c.getHeight(), getSelectedButtonColor2()));
         }
         else {
@@ -100,7 +100,7 @@ public class DarculaButtonUI extends BasicButtonUI {
   @Override
   public void update(Graphics g, JComponent c) {
     super.update(g, c);
-    if (((JButton)c).isDefaultButton() && !SystemInfo.isMac) {
+    if (c instanceof JButton && ((JButton)c).isDefaultButton() && !SystemInfo.isMac) {
       if (!c.getFont().isBold()) {
        c.setFont(c.getFont().deriveFont(Font.BOLD));
       }
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaToggleButtonUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaToggleButtonUI.java
new file mode 100644 (file)
index 0000000..b35ac61
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2014 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.ide.ui.laf.darcula.ui;
+
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+
+public class DarculaToggleButtonUI extends DarculaButtonUI {
+  @SuppressWarnings("MethodOverridesStaticMethodOfSuperclass")
+  public static ComponentUI createUI(JComponent c) {
+    return new DarculaToggleButtonUI();
+  }
+}
index 116adfe47398c33c92785498a53e777da05c85e4..cd99cb129fd044fea6595d5e42117617e384b9a0 100644 (file)
@@ -130,6 +130,9 @@ Button.darcula.selection.color2=3a6bc6
 Button.darcula.selectedButtonForeground=f0f0f0
 Button.darcula.disabledText.shadow=ffffff
 
+ToggleButton.border=com.intellij.ide.ui.laf.darcula.ui.DarculaButtonPainter
+ToggleButtonUI=com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI
+
 MenuItem.acceleratorForeground=505050
 PopupMenu.translucentBackground=e8e8e8
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/DiffPanelComboBoxAction.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/DiffPanelComboBoxAction.java
new file mode 100644 (file)
index 0000000..b3ef959
--- /dev/null
@@ -0,0 +1,94 @@
+package com.intellij.openapi.diff.actions;
+
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
+import com.intellij.openapi.diff.DiffBundle;
+import com.intellij.openapi.diff.ex.DiffPanelEx;
+import com.intellij.openapi.diff.impl.DiffPanelImpl;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.util.containers.HashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.Map;
+
+public abstract class DiffPanelComboBoxAction<T> extends ComboBoxAction implements DumbAware {
+  @NotNull private final Map<T, AnAction> myActions = new HashMap<T, AnAction>();
+  @NotNull private final T[] myActionOrder;
+
+  protected DiffPanelComboBoxAction(@NotNull T[] actionOrder) {
+    myActionOrder = actionOrder;
+  }
+
+  @NotNull
+  protected abstract String getActionName();
+
+  @NotNull
+  protected abstract T getCurrentOption(@NotNull DiffPanelEx diffPanel);
+
+  @Nullable
+  private static DiffPanelEx getDiffPanel(@NotNull DataContext context) {
+    return DiffPanelImpl.fromDataContext(context);
+  }
+
+  protected void addAction(T key, @NotNull AnAction action) {
+    myActions.put(key, action);
+  }
+
+  @Override
+  public JComponent createCustomComponent(final Presentation presentation) {
+    JPanel panel = new JPanel(new BorderLayout());
+    final JLabel label = new JLabel(getActionName());
+    label.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4));
+    panel.add(label, BorderLayout.WEST);
+    panel.add(super.createCustomComponent(presentation), BorderLayout.CENTER);
+    return panel;
+  }
+
+  @NotNull
+  @Override
+  protected DefaultActionGroup createPopupActionGroup(JComponent button) {
+    DefaultActionGroup actionGroup = new DefaultActionGroup();
+    for (T option : myActionOrder) {
+      actionGroup.add(myActions.get(option));
+    }
+    return actionGroup;
+  }
+
+  @Override
+  public void update(AnActionEvent e) {
+    super.update(e);
+    Presentation presentation = e.getPresentation();
+    DiffPanelEx diffPanel = getDiffPanel(e.getDataContext());
+    if (diffPanel != null && diffPanel.getComponent().isDisplayable()) {
+      AnAction action = myActions.get(getCurrentOption(diffPanel));
+      Presentation templatePresentation = action.getTemplatePresentation();
+      presentation.setIcon(templatePresentation.getIcon());
+      presentation.setText(templatePresentation.getText());
+      presentation.setEnabled(true);
+    }
+    else {
+      presentation.setIcon(null);
+      presentation.setText(DiffBundle.message("diff.panel.combo.box.action.not.available.action.name"));
+      presentation.setEnabled(false);
+    }
+  }
+
+  protected static abstract class DiffPanelAction extends DumbAwareAction {
+    public DiffPanelAction(@NotNull String text) {
+      super(text);
+    }
+
+    public void actionPerformed(AnActionEvent e) {
+      final DiffPanelEx diffPanel = getDiffPanel(e.getDataContext());
+      if (diffPanel != null) {
+        perform(diffPanel);
+      }
+    }
+
+    protected abstract void perform(@NotNull DiffPanelEx diffPanel);
+  }
+}
index 8ae6fa277738ccc0be7246949c3f2d6994c66759..65f5eb346120b9dcb8d11ff6beb4c6ba5146f77b 100644 (file)
  */
 package com.intellij.openapi.diff.actions;
 
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.DefaultActionGroup;
-import com.intellij.openapi.actionSystem.Presentation;
-import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
 import com.intellij.openapi.diff.DiffBundle;
 import com.intellij.openapi.diff.ex.DiffPanelEx;
-import com.intellij.openapi.diff.impl.DiffPanelImpl;
 import com.intellij.openapi.diff.impl.processing.HighlightMode;
-import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.project.DumbAwareAction;
-import com.intellij.util.containers.HashMap;
 import org.jetbrains.annotations.NotNull;
 
-import javax.swing.*;
-import java.awt.*;
-import java.util.Map;
-
-public class HighlightModeAction extends ComboBoxAction implements DumbAware {
-  private final Map<HighlightMode, AnAction> myActions = new HashMap<HighlightMode, AnAction>();
-  private static final HighlightMode[] ourActionOrder =
-    new HighlightMode[]{HighlightMode.BY_WORD, HighlightMode.BY_LINE, HighlightMode.NO_HIGHLIGHTING};
+public class HighlightModeAction extends DiffPanelComboBoxAction<HighlightMode> {
+  private static final HighlightMode[] ourActionOrder = new HighlightMode[]{
+    HighlightMode.BY_WORD,
+    HighlightMode.BY_LINE,
+    HighlightMode.NO_HIGHLIGHTING
+  };
 
   public HighlightModeAction() {
-    myActions.put(HighlightMode.BY_WORD,
-                  new SetHighlightModeAction(DiffBundle.message("diff.acton.highlight.mode.action.by.word"), HighlightMode.BY_WORD));
-    myActions.put(HighlightMode.BY_LINE,
-                  new SetHighlightModeAction(DiffBundle.message("diff.acton.highlight.mode.action.by.line"), HighlightMode.BY_LINE));
-    myActions.put(HighlightMode.NO_HIGHLIGHTING,
-                  new SetHighlightModeAction(DiffBundle.message("diff.acton.highlight.mode.action.no.highlighting"),
-                                             HighlightMode.NO_HIGHLIGHTING));
+    super(ourActionOrder);
+    addAction(HighlightMode.BY_WORD, new HighlightingModeAction(DiffBundle.message("diff.acton.highlight.mode.action.by.word"), HighlightMode.BY_WORD));
+    addAction(HighlightMode.BY_LINE, new HighlightingModeAction(DiffBundle.message("diff.acton.highlight.mode.action.by.line"), HighlightMode.BY_LINE));
+    addAction(HighlightMode.NO_HIGHLIGHTING, new HighlightingModeAction(DiffBundle.message("diff.acton.highlight.mode.action.no.highlighting"), HighlightMode.NO_HIGHLIGHTING));
   }
 
+  @NotNull
   @Override
-  public JComponent createCustomComponent(final Presentation presentation) {
-    JPanel panel = new JPanel(new BorderLayout());
-    final JLabel label = new JLabel(DiffBundle.message("diff.acton.highlight.mode.action.name"));
-    label.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4));
-    panel.add(label, BorderLayout.WEST);
-    panel.add(super.createCustomComponent(presentation), BorderLayout.CENTER);
-    return panel;
+  protected String getActionName() {
+    return DiffBundle.message("diff.acton.highlight.mode.action.name");
   }
 
   @NotNull
-  protected DefaultActionGroup createPopupActionGroup(JComponent button) {
-    DefaultActionGroup actionGroup = new DefaultActionGroup();
-    for (HighlightMode comparisonPolicy : ourActionOrder) {
-      actionGroup.add(myActions.get(comparisonPolicy));
-    }
-    return actionGroup;
-  }
-
-  public void update(AnActionEvent e) {
-    super.update(e);
-    Presentation presentation = e.getPresentation();
-    DiffPanelEx diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext());
-    if (diffPanel != null && diffPanel.getComponent().isDisplayable()) {
-      AnAction action = myActions.get(diffPanel.getHighlightMode());
-      Presentation templatePresentation = action.getTemplatePresentation();
-      presentation.setIcon(templatePresentation.getIcon());
-      presentation.setText(templatePresentation.getText());
-      presentation.setEnabled(true);
-    }
-    else {
-      presentation.setIcon(null);
-      presentation.setText(DiffBundle.message("diff.acton.highlight.mode.not.available.action.name"));
-      presentation.setEnabled(false);
-    }
+  @Override
+  protected HighlightMode getCurrentOption(@NotNull DiffPanelEx diffPanel) {
+    return diffPanel.getHighlightMode();
   }
 
-  private static class SetHighlightModeAction extends DumbAwareAction {
+  private static class HighlightingModeAction extends DiffPanelAction {
     private final HighlightMode myHighlightMode;
 
-    public SetHighlightModeAction(String text, HighlightMode mode) {
+    public HighlightingModeAction(String text, HighlightMode highlightMode) {
       super(text);
-      myHighlightMode = mode;
+      myHighlightMode = highlightMode;
     }
 
-    public void actionPerformed(AnActionEvent e) {
-      final DiffPanelImpl diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext());
-      if (diffPanel != null) {
-        diffPanel.setHighlightMode(myHighlightMode);
-      }
+    @Override
+    protected void perform(@NotNull DiffPanelEx diffPanel) {
+      diffPanel.setHighlightMode(myHighlightMode);
     }
   }
 }
index 930db0e4f3371b14a67c432b77360af3bfe4d64b..a46d8b1516c73c9c882a2817d5b743d84dc850b9 100644 (file)
  */
 package com.intellij.openapi.diff.actions;
 
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.DefaultActionGroup;
-import com.intellij.openapi.actionSystem.Presentation;
-import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
 import com.intellij.openapi.diff.DiffBundle;
 import com.intellij.openapi.diff.ex.DiffPanelEx;
 import com.intellij.openapi.diff.impl.ComparisonPolicy;
-import com.intellij.openapi.diff.impl.DiffPanelImpl;
-import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.project.DumbAwareAction;
-import com.intellij.util.containers.HashMap;
 import org.jetbrains.annotations.NotNull;
 
-import javax.swing.*;
-import java.awt.*;
-import java.util.Map;
-
-public class IgnoreWhiteSpacesAction extends ComboBoxAction implements DumbAware {
-  private final Map<ComparisonPolicy, AnAction> myActions = new HashMap<ComparisonPolicy, AnAction>();
+public class IgnoreWhiteSpacesAction extends DiffPanelComboBoxAction<ComparisonPolicy> {
   private static final ComparisonPolicy[] ourActionOrder = new ComparisonPolicy[]{
     ComparisonPolicy.DEFAULT,
     ComparisonPolicy.TRIM_SPACE,
-    ComparisonPolicy.IGNORE_SPACE};
+    ComparisonPolicy.IGNORE_SPACE
+  };
 
   public IgnoreWhiteSpacesAction() {
-    myActions.put(ComparisonPolicy.DEFAULT, new IgnoringPolicyAction(DiffBundle.message("diff.acton.ignore.whitespace.policy.do.not.ignore"), ComparisonPolicy.DEFAULT));
-    myActions.put(ComparisonPolicy.TRIM_SPACE, new IgnoringPolicyAction(DiffBundle.message("diff.acton.ignore.whitespace.policy.leading.and.trailing"), ComparisonPolicy.TRIM_SPACE));
-    myActions.put(ComparisonPolicy.IGNORE_SPACE, new IgnoringPolicyAction(DiffBundle.message("diff.acton.ignore.whitespace.policy.all"), ComparisonPolicy.IGNORE_SPACE));
+    super(ourActionOrder);
+    addAction(ComparisonPolicy.DEFAULT, new IgnoringPolicyAction(DiffBundle.message("diff.acton.ignore.whitespace.policy.do.not.ignore"), ComparisonPolicy.DEFAULT));
+    addAction(ComparisonPolicy.TRIM_SPACE, new IgnoringPolicyAction(DiffBundle.message("diff.acton.ignore.whitespace.policy.leading.and.trailing"), ComparisonPolicy.TRIM_SPACE));
+    addAction(ComparisonPolicy.IGNORE_SPACE, new IgnoringPolicyAction(DiffBundle.message("diff.acton.ignore.whitespace.policy.all"), ComparisonPolicy.IGNORE_SPACE));
   }
 
+  @NotNull
   @Override
-  public JComponent createCustomComponent(final Presentation presentation) {
-    JPanel panel = new JPanel(new BorderLayout());
-    final JLabel label = new JLabel(DiffBundle.message("ignore.whitespace.acton.name"));
-    label.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4));
-    panel.add(label, BorderLayout.WEST);
-    panel.add(super.createCustomComponent(presentation), BorderLayout.CENTER);
-    return panel;
+  protected String getActionName() {
+    return DiffBundle.message("ignore.whitespace.acton.name");
   }
 
   @NotNull
-  protected DefaultActionGroup createPopupActionGroup(JComponent button) {
-    DefaultActionGroup actionGroup = new DefaultActionGroup();
-    for (ComparisonPolicy comparisonPolicy : ourActionOrder) {
-      actionGroup.add(myActions.get(comparisonPolicy));
-    }
-    return actionGroup;
-  }
-
-  public void update(AnActionEvent e) {
-    super.update(e);
-    Presentation presentation = e.getPresentation();
-    DiffPanelEx diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext());
-    if (diffPanel != null && diffPanel.getComponent().isDisplayable()) {
-      AnAction action = myActions.get(diffPanel.getComparisonPolicy());
-      Presentation templatePresentation = action.getTemplatePresentation();
-      presentation.setIcon(templatePresentation.getIcon());
-      presentation.setText(templatePresentation.getText());
-      presentation.setEnabled(true);
-    } else {
-      presentation.setIcon(null);
-      presentation.setText(DiffBundle.message("ignore.whitespace.action.not.available.action.name"));
-      presentation.setEnabled(false);
-    }
+  @Override
+  protected ComparisonPolicy getCurrentOption(@NotNull DiffPanelEx diffPanel) {
+    return diffPanel.getComparisonPolicy();
   }
 
-  private static class IgnoringPolicyAction extends DumbAwareAction {
+  private static class IgnoringPolicyAction extends DiffPanelAction {
     private final ComparisonPolicy myPolicy;
 
     public IgnoringPolicyAction(String text, ComparisonPolicy policy) {
@@ -90,11 +54,9 @@ public class IgnoreWhiteSpacesAction extends ComboBoxAction implements DumbAware
       myPolicy = policy;
     }
 
-    public void actionPerformed(AnActionEvent e) {
-      final DiffPanelImpl diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext());
-      if (diffPanel != null) {
-        diffPanel.setComparisonPolicy(myPolicy);
-      }
+    @Override
+    protected void perform(@NotNull DiffPanelEx diffPanel) {
+      diffPanel.setComparisonPolicy(myPolicy);
     }
   }
 }
index a3715fdeaec442669ab30f7f702845399353ed47..1ee83be742243e33968d849238586c0af399c988 100644 (file)
@@ -19,11 +19,10 @@ import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.diff.DiffContent;
 import com.intellij.openapi.diff.DiffContentUtil;
 import com.intellij.openapi.diff.DiffViewer;
-import com.intellij.openapi.diff.LineTokenizer;
-import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.external.DiffManagerImpl;
 import com.intellij.openapi.diff.impl.fragments.Fragment;
 import com.intellij.openapi.diff.impl.fragments.LineFragment;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.impl.util.FocusDiffSide;
 import com.intellij.openapi.diff.impl.util.TextDiffType;
 import com.intellij.openapi.editor.Document;
@@ -34,7 +33,6 @@ import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.fileTypes.FileTypes;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.FrameWrapper;
-import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.ImageLoader;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
@@ -47,7 +45,7 @@ public class DiffUtil {
   private DiffUtil() {
   }
 
-  public static void initDiffFrame(Project project, FrameWrapper frameWrapper, final DiffViewer diffPanel, final JComponent mainComponent) {
+  public static void initDiffFrame(Project project, @NotNull FrameWrapper frameWrapper, @NotNull final DiffViewer diffPanel, final JComponent mainComponent) {
     frameWrapper.setComponent(mainComponent);
     frameWrapper.setProject(project);
     frameWrapper.setImage(ImageLoader.loadFromResource("/diff/Diff.png"));
@@ -56,15 +54,17 @@ public class DiffUtil {
   }
 
   @Nullable
-  public static FocusDiffSide getFocusDiffSide(DataContext dataContext) {
+  public static FocusDiffSide getFocusDiffSide(@NotNull DataContext dataContext) {
     return FocusDiffSide.DATA_KEY.getData(dataContext);
   }
 
-  public static String[] convertToLines(@NotNull String text) {
-    return new LineTokenizer(text).execute();
+  @NotNull
+  public static DiffString[] convertToLines(@NotNull String text) {
+    return DiffString.create(text).tokenize();
   }
 
-  public static FileType[] chooseContentTypes(DiffContent[] contents) {
+  @NotNull
+  public static FileType[] chooseContentTypes(@NotNull DiffContent[] contents) {
     FileType commonType = FileTypes.PLAIN_TEXT;
     for (DiffContent content : contents) {
       FileType contentType = content.getContentType();
@@ -78,7 +78,7 @@ public class DiffUtil {
     return result;
   }
 
-  public static boolean isWritable(DiffContent content) {
+  public static boolean isWritable(@NotNull DiffContent content) {
     Document document = content.getDocument();
     return document != null && document.isWritable();
   }
@@ -92,7 +92,7 @@ public class DiffUtil {
     return editor;
   }
 
-  public static void drawBoldDottedFramingLines(Graphics2D g, int startX, int endX, int startY, int bottomY, Color color) {
+  public static void drawBoldDottedFramingLines(@NotNull Graphics2D g, int startX, int endX, int startY, int bottomY, @NotNull Color color) {
     UIUtil.drawBoldDottedLine(g, startX, endX, startY, null, color, false);
     UIUtil.drawBoldDottedLine(g, startX, endX, bottomY, null, color, false);
   }
@@ -102,8 +102,9 @@ public class DiffUtil {
     UIUtil.drawLine(g, startX, y + 1, endX, y + 1, null, color);
   }
 
-  public static Color getFramingColor(@NotNull Color backgroundColor) {
-    return backgroundColor.darker();
+  @Nullable
+  public static Color getFramingColor(@Nullable Color backgroundColor) {
+    return backgroundColor != null ? backgroundColor.darker() : null;
   }
 
   @NotNull
index d3b273fdaba971e2033783d7835db5cf0464bf3d..7e395c1b4a9ecb0eabb822bd69fff5f34b66a590 100644 (file)
@@ -137,7 +137,8 @@ public class FragmentedDiffPanelState extends DiffPanelState {
     //setDiffPolicy(diffPolicy);
     diffPolicy.setRanges(ranges);
 
-    return addMarkup(new TextCompareProcessor(myComparisonPolicy, diffPolicy).process(myAppender1.getText(), myAppender2.getText()));
+    return addMarkup(
+      new TextCompareProcessor(myComparisonPolicy, diffPolicy, myHighlightMode).process(myAppender1.getText(), myAppender2.getText()));
   }
 
   private BeforeAfter<Integer> lineStarts(int i) {
index db11ed063c7e722200ebcfc72a5e362f707a259e..044fe0a08a28f72b730a37eb7a247e9fd66b5046 100644 (file)
  */
 package com.intellij.openapi.diff.impl.highlighting;
 
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.processing.DiffPolicy;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.util.BeforeAfter;
 import com.intellij.util.diff.FilesTooBigForDiffException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.TestOnly;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -39,13 +42,22 @@ public class PresetBlocksDiffPolicy implements DiffPolicy {
     myDelegate = delegate;
   }
 
+  @TestOnly
+  @NotNull
   @Override
-  public DiffFragment[] buildFragments(String text1, String text2) throws FilesTooBigForDiffException {
+  public DiffFragment[] buildFragments(@NotNull String text1, @NotNull String text2) throws FilesTooBigForDiffException {
+    return buildFragments(DiffString.create(text1), DiffString.create(text2));
+  }
+
+  @NotNull
+  @Override
+  public DiffFragment[] buildFragments(@NotNull DiffString text1, @NotNull DiffString text2) throws FilesTooBigForDiffException {
     final List<DiffFragment> fragments = new ArrayList<DiffFragment>();
     for (int i = 0; i < myRanges.size(); i++) {
       final BeforeAfter<TextRange> range = myRanges.get(i);
-      fragments.addAll(Arrays.asList(myDelegate.buildFragments(new String(text1.substring(range.getBefore().getStartOffset(), range.getBefore().getEndOffset())),
-                       new String(text2.substring(range.getAfter().getStartOffset(), range.getAfter().getEndOffset())))));
+      fragments.addAll(Arrays.asList(myDelegate.buildFragments(
+        text1.substring(range.getBefore().getStartOffset(), range.getBefore().getEndOffset()).copy(),
+        text2.substring(range.getAfter().getStartOffset(), range.getAfter().getEndOffset()).copy())));
     }
 
     return fragments.toArray(new DiffFragment[fragments.size()]);
index 14c235470347cdc1d4e70fc7d91f771d05240d9e..d3e1dfd5a64a4b793f007d0c943b11144cc0cbef 100644 (file)
@@ -30,8 +30,8 @@ import com.intellij.util.diff.FilesTooBigForDiffException;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 
 public abstract class SimpleDiffPanelState implements Disposable  {
   protected ComparisonPolicy myComparisonPolicy = ComparisonPolicy.DEFAULT;
@@ -84,7 +84,7 @@ public abstract class SimpleDiffPanelState implements Disposable  {
   public void dispose() {
   }
 
-  private LineBlocks addMarkup(final ArrayList<LineFragment> lines) {
+  private LineBlocks addMarkup(final List<LineFragment> lines) {
     ApplicationManager.getApplication().runWriteAction(new Runnable() {
       public void run() {
         final FragmentHighlighterImpl fragmentHighlighter = new FragmentHighlighterImpl(myAppender1, myAppender2);
@@ -114,12 +114,8 @@ public abstract class SimpleDiffPanelState implements Disposable  {
       return LineBlocks.EMPTY;
     }
 
-    if (myHighlightMode == HighlightMode.NO_HIGHLIGHTING) {
-      return LineBlocks.fromLineFragments(Collections.<LineFragment>emptyList());
-    }
-
-    return addMarkup(new TextCompareProcessor(myComparisonPolicy, myDiffPolicy, myHighlightMode == HighlightMode.BY_WORD)
-                       .process(myAppender1.getText(), myAppender2.getText()));
+    return addMarkup(
+      new TextCompareProcessor(myComparisonPolicy, myDiffPolicy, myHighlightMode).process(myAppender1.getText(), myAppender2.getText()));
   }
 
   public Project getProject() { return myProject; }
index dc0e98e722fbb03f0f004265ac1850d2d2ef0231..bbd8c929c2038a61a63d3d0cae8f938e4e15ee44 100644 (file)
@@ -16,6 +16,7 @@
 package com.intellij.openapi.diff.impl.incrementalMerge;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.ComparisonPolicy;
 import com.intellij.openapi.diff.impl.DiffUtil;
@@ -29,6 +30,7 @@ import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.HashSet;
 import com.intellij.util.diff.FilesTooBigForDiffException;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.*;
 
@@ -108,12 +110,12 @@ public class ChangeList {
 
   private ArrayList<Change> buildChanges() throws FilesTooBigForDiffException {
     Document base = getDocument(FragmentSide.SIDE1);
-    String[] baseLines = DiffUtil.convertToLines(base.getText());
+    DiffString[] baseLines = DiffUtil.convertToLines(base.getText());
     Document version = getDocument(FragmentSide.SIDE2);
-    String[] versionLines = DiffUtil.convertToLines(version.getText());
+    DiffString[] versionLines = DiffUtil.convertToLines(version.getText());
     DiffFragment[] fragments = ComparisonPolicy.DEFAULT.buildDiffFragmentsFromLines(baseLines, versionLines);
     final ArrayList<Change> result = new ArrayList<Change>();
-    new DiffFragmemntsEnumerator(fragments) {
+    new DiffFragmentsEnumerator(fragments) {
       protected void process(DiffFragment fragment) {
         if (fragment.isEqual()) return;
         Context context = getContext();
@@ -129,11 +131,11 @@ public class ChangeList {
     return myChanges.get(index);
   }
 
-  private abstract static class DiffFragmemntsEnumerator {
+  private abstract static class DiffFragmentsEnumerator {
     private final DiffFragment[] myFragments;
     private final Context myContext;
 
-    private DiffFragmemntsEnumerator(DiffFragment[] fragments) {
+    private DiffFragmentsEnumerator(DiffFragment[] fragments) {
       myContext = new Context();
       myFragments = fragments;
     }
@@ -142,8 +144,8 @@ public class ChangeList {
       for (DiffFragment fragment : myFragments) {
         myContext.myFragment = fragment;
         process(fragment);
-        String text1 = fragment.getText1();
-        String text2 = fragment.getText2();
+        DiffString text1 = fragment.getText1();
+        DiffString text2 = fragment.getText2();
         myContext.myStarts[0] += StringUtil.length(text1);
         myContext.myStarts[1] += StringUtil.length(text2);
         myContext.myLines[0] += countLines(text1);
@@ -151,7 +153,7 @@ public class ChangeList {
       }
     }
 
-    private static int countLines(String text) {
+    private static int countLines(@Nullable DiffString text) {
       if (text == null) return 0;
       return StringUtil.countNewLines(text);
     }
index 2c1b1e267b15a81f2ac76ca08eac818031c5c6ac..d3a0b5a50d581e6934689e4b2f551ffa186ff07e 100644 (file)
@@ -24,6 +24,7 @@ import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.diff.DiffBundle;
 import com.intellij.openapi.diff.DiffContent;
 import com.intellij.openapi.diff.DiffRequest;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
 import com.intellij.openapi.diff.impl.incrementalMerge.ui.MergePanel2;
@@ -149,8 +150,8 @@ public class MergeList implements UserDataHolder {
                                                  @NotNull String baseText,
                                                  @NotNull String rightText,
                                                  @NotNull ContextLogger logger) throws FilesTooBigForDiffException {
-    DiffFragment[] leftFragments = DiffPolicy.DEFAULT_LINES.buildFragments(baseText, leftText);
-    DiffFragment[] rightFragments = DiffPolicy.DEFAULT_LINES.buildFragments(baseText, rightText);
+    DiffFragment[] leftFragments = DiffPolicy.DEFAULT_LINES.buildFragments(DiffString.create(baseText), DiffString.create(leftText));
+    DiffFragment[] rightFragments = DiffPolicy.DEFAULT_LINES.buildFragments(DiffString.create(baseText), DiffString.create(rightText));
     int[] leftOffsets = {0, 0};
     int[] rightOffsets = {0, 0};
     int leftIndex = 0;
@@ -188,7 +189,7 @@ public class MergeList implements UserDataHolder {
     leftOffsets[1] += versionLength;
   }
 
-  private static int getTextLength(@Nullable String text1) {
+  private static int getTextLength(@Nullable DiffString text1) {
     return text1 != null ? text1.length() : 0;
   }
 
index 2a6a01c104147f56f1bc7eb4fa119bb2d57ad29b..2d41620f6de20f193b9b3c6a5fe6953e78501f07 100644 (file)
@@ -18,35 +18,47 @@ package com.intellij.openapi.diff.impl.processing;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.util.text.StringUtil;
 
 class PreferWholeLines implements DiffCorrection {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.processing.PreferWholeLines");
   public static final DiffCorrection INSTANCE = new PreferWholeLines();
+
   public DiffFragment[] correct(DiffFragment[] fragments) {
     for (int i = 1; i < fragments.length - 1; i++) {
       DiffFragment fragment = fragments[i];
       if (!fragment.isOneSide()) continue;
       DiffFragment nextFragment = fragments[i + 1];
       FragmentSide side = FragmentSide.chooseSide(fragment);
+
+      DiffString fragmentText = side.getText(fragment);
+      DiffString otherNextFragmentText = side.getOtherText(nextFragment);
+      DiffString nextFragmentText = side.getText(nextFragment);
+
       if (nextFragment.isOneSide()) {
-        LOG.error("<" + side.getText(fragment) + "> <" + side.getOtherText(nextFragment) + ">");
+        LOG.error("<" + fragmentText + "> <" + otherNextFragmentText + ">");
       }
-      if (StringUtil.startsWithChar(side.getText(fragment), '\n') &&
-          StringUtil.startsWithChar(side.getText(nextFragment), '\n') &&
-          StringUtil.startsWithChar(side.getOtherText(nextFragment), '\n')) {
+      if (StringUtil.startsWithChar(fragmentText, '\n') &&
+          StringUtil.startsWithChar(nextFragmentText, '\n') &&
+          StringUtil.startsWithChar(otherNextFragmentText, '\n')) {
+
         DiffFragment previous = fragments[i - 1];
-        previous = side.createFragment(side.getText(previous) + "\n",
-                                       side.getOtherText(previous) + "\n",
-                                       previous.isModified());
+        DiffString previousText = side.getText(previous);
+        DiffString otherPreciousText = side.getOtherText(previous);
+
+        assert previous != null;
+        assert previousText != null;
+        assert otherPreciousText != null;
+        assert fragmentText != null;
+        assert nextFragmentText != null;
+        assert otherNextFragmentText != null;
+
+        previous = side.createFragment(previousText.append('\n'), otherPreciousText.append('\n'), previous.isModified());
         fragments[i - 1] = previous;
-        fragment = side.createFragment(side.getText(fragment).substring(1) + "\n",
-                                       side.getOtherText(fragment),
-                                       fragment.isModified());
+        fragment = side.createFragment(fragmentText.substring(1).append('\n'), side.getOtherText(fragment), fragment.isModified());
         fragments[i] = fragment;
-        nextFragment = side.createFragment(side.getText(nextFragment).substring(1),
-                                           side.getOtherText(nextFragment).substring(1),
-                                           nextFragment.isModified());
+        nextFragment = side.createFragment(nextFragmentText.substring(1), otherNextFragmentText.substring(1), nextFragment.isModified());
         fragments[i + 1] = nextFragment;
       }
     }
index e527964a5c0d595c2556f4d7449f4fb90deecad8..bdf414c53935fa5146486b62d8b4aaa74e45a926 100644 (file)
@@ -23,53 +23,59 @@ import com.intellij.openapi.diff.impl.fragments.LineFragment;
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
 import com.intellij.openapi.diff.impl.highlighting.LineBlockDivider;
 import com.intellij.openapi.diff.impl.highlighting.Util;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.diff.FilesTooBigForDiffException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 public class TextCompareProcessor {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.processing.Processor");
   private final DiffPolicy myDiffPolicy;
   @NotNull private final ComparisonPolicy myComparisonPolicy;
-  private final boolean mySearchForSubFragments;
+  @NotNull private final HighlightMode myHighlightMode;
 
   public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy,
-                              final DiffPolicy diffPolicy,
-                              boolean searchForSubFragments) {
+                              @NotNull DiffPolicy diffPolicy,
+                              @NotNull HighlightMode highlightMode) {
     myComparisonPolicy = comparisonPolicy;
     myDiffPolicy = diffPolicy;
-    mySearchForSubFragments = searchForSubFragments;
-  }
-
-  public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy, final DiffPolicy diffPolicy) {
-    this(comparisonPolicy, diffPolicy, true);
+    myHighlightMode = highlightMode;
   }
 
   public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy) {
-    this(comparisonPolicy, DiffPolicy.LINES_WO_FORMATTING);
+    this(comparisonPolicy, DiffPolicy.LINES_WO_FORMATTING, HighlightMode.BY_WORD);
   }
 
-  public ArrayList<LineFragment> process(@Nullable String text1, @Nullable String text2) throws FilesTooBigForDiffException {
+  public List<LineFragment> process(@Nullable String text1, @Nullable String text2) throws FilesTooBigForDiffException {
+    if (myHighlightMode == HighlightMode.NO_HIGHLIGHTING) {
+      return Collections.emptyList();
+    }
+
     text1 = StringUtil.notNullize(text1);
     text2 = StringUtil.notNullize(text2);
     if (text1.isEmpty() || text2.isEmpty()) {
       return new DummyDiffFragmentsProcessor().process(text1, text2);
     }
 
-    DiffFragment[] woFormattingBlocks = myDiffPolicy.buildFragments(text1, text2);
+    DiffString diffText1 = DiffString.create(text1);
+    DiffString diffText2 = DiffString.create(text2);
+
+    DiffFragment[] woFormattingBlocks = myDiffPolicy.buildFragments(diffText1, diffText2);
     DiffFragment[] step1lineFragments = new DiffCorrection.TrueLineBlocks(myComparisonPolicy).correctAndNormalize(woFormattingBlocks);
     ArrayList<LineFragment> lineBlocks = new DiffFragmentsProcessor().process(step1lineFragments);
 
     int badLinesCount = 0;
-    if (mySearchForSubFragments) {
+    if (myHighlightMode == HighlightMode.BY_WORD) {
       for (LineFragment lineBlock : lineBlocks) {
         if (lineBlock.isOneSide() || lineBlock.isEqual()) continue;
         try {
-          String subText1 = lineBlock.getText(text1, FragmentSide.SIDE1);
-          String subText2 = lineBlock.getText(text2, FragmentSide.SIDE2);
+          DiffString subText1 = lineBlock.getText(diffText1, FragmentSide.SIDE1);
+          DiffString subText2 = lineBlock.getText(diffText2, FragmentSide.SIDE2);
           ArrayList<LineFragment> subFragments = findSubFragments(subText1, subText2);
           lineBlock.setChildren(new ArrayList<Fragment>(subFragments));
           lineBlock.adjustTypeFromChildrenTypes();
@@ -84,7 +90,7 @@ public class TextCompareProcessor {
     return lineBlocks;
   }
 
-  private ArrayList<LineFragment> findSubFragments(String text1, String text2) throws FilesTooBigForDiffException {
+  private ArrayList<LineFragment> findSubFragments(@NotNull DiffString text1, @NotNull DiffString text2) throws FilesTooBigForDiffException {
     DiffFragment[] fragments = new ByWord(myComparisonPolicy).buildFragments(text1, text2);
     fragments = DiffCorrection.ConnectSingleSideToChange.INSTANCE.correct(fragments);
     fragments = UniteSameType.INSTANCE.correct(fragments);
index 33db73f3a8eb0fca4ca1dd3e3e5fb9c6e6124dd5..6e6a607025952f71dba675d1603967cea2b8f9b3 100644 (file)
@@ -23,6 +23,8 @@ import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.LogicalPosition;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.util.ui.GraphicsUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.awt.*;
 import java.awt.geom.CubicCurve2D;
@@ -34,7 +36,7 @@ import java.util.ArrayList;
  */
 public class DividerPolygon {
 
-  private final Color myColor;
+  @Nullable private final Color myColor;
   private final int myStart1;
   private final int myStart2;
   private final int myEnd1;
@@ -43,7 +45,7 @@ public class DividerPolygon {
 
   public static final double CTRL_PROXIMITY_X = 0.3;
 
-  public DividerPolygon(int start1, int start2, int end1, int end2, Color color, boolean applied) {
+  public DividerPolygon(int start1, int start2, int end1, int end2, @Nullable Color color, boolean applied) {
     myApplied = applied;
     myStart1 = advance(start1);
     myStart2 = advance(start2);
@@ -150,7 +152,9 @@ public class DividerPolygon {
     //g.setComposite(composite);
   }
 
-  public static ArrayList<DividerPolygon> createVisiblePolygons(EditingSides sides, FragmentSide left, int diffDividerPolygonsOffset) {
+  public static ArrayList<DividerPolygon> createVisiblePolygons(@NotNull EditingSides sides,
+                                                                @NotNull FragmentSide left,
+                                                                int diffDividerPolygonsOffset) {
     Editor editor1 = sides.getEditor(left);
     Editor editor2 = sides.getEditor(left.otherSide());
     LineBlocks lineBlocks = sides.getLineBlocks();
@@ -174,7 +178,10 @@ public class DividerPolygon {
     return new FoldingTransformation(editor);
   }
 
-  private static DividerPolygon createPolygon(Transformation[] transformations, Trapezium trapezium, Color color, FragmentSide left,
+  private static DividerPolygon createPolygon(@NotNull Transformation[] transformations,
+                                              @NotNull Trapezium trapezium,
+                                              @Nullable Color color,
+                                              @NotNull FragmentSide left,
                                               int diffDividerPolygonsOffset, boolean applied) {
     Interval base1 = trapezium.getBase(left);
     Interval base2 = trapezium.getBase(left.otherSide());
index 4a3c268d25e200eab0eb91baf1d4ad1d27f66b71..d54bfcc304b473b9a8dd7105889b98e8ac7e53c7 100644 (file)
@@ -251,6 +251,7 @@ public class PluginsAdvertiser implements StartupActivity {
               if (project.isDisposed()) return;
               if (extensions == null) {
                 loadSupportedExtensions(myAllPlugins);
+                if (project.isDisposed()) return;
                 EditorNotifications.getInstance(project).updateAllNotifications();
               }
               final Map<String, Plugin> ids = new HashMap<String, Plugin>();
index d0e7e97902f2ad77d754b24ded87e63e85fe240e..8908c3451a72914471779bc4e9e774cb7fc3e47b 100644 (file)
@@ -18,6 +18,7 @@ package com.intellij.remotesdk;
 import com.intellij.openapi.util.PasswordUtil;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.xmlb.annotations.Transient;
+import org.jdom.Element;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -204,7 +205,7 @@ public class RemoteCredentialsHolder implements MutableRemoteCredentials {
     }
   }
 
-  public void copyTo(RemoteSdkCredentials to) {
+  public void copyRemoteCredentialsTo(RemoteSdkCredentials to) {
     to.setHost(getHost());
     to.setPort(getPort());
     to.setAnonymous(isAnonymous());
@@ -216,4 +217,41 @@ public class RemoteCredentialsHolder implements MutableRemoteCredentials {
     to.setStorePassword(isStorePassword());
     to.setStorePassphrase(isStorePassphrase());
   }
+
+  public void load(Element element) {
+    setHost(element.getAttributeValue(HOST));
+    setPort(StringUtil.parseInt(element.getAttributeValue(PORT), 22));
+    setAnonymous(StringUtil.parseBoolean(element.getAttributeValue(ANONYMOUS), false));
+    setSerializedUserName(element.getAttributeValue(USERNAME));
+    setSerializedPassword(element.getAttributeValue(PASSWORD));
+    setPrivateKeyFile(StringUtil.nullize(element.getAttributeValue(PRIVATE_KEY_FILE)));
+    setKnownHostsFile(StringUtil.nullize(element.getAttributeValue(KNOWN_HOSTS_FILE)));
+    setSerializedPassphrase(element.getAttributeValue(PASSPHRASE));
+    setUseKeyPair(StringUtil.parseBoolean(element.getAttributeValue(USE_KEY_PAIR), false));
+  }
+
+  public void save(Element rootElement) {
+    rootElement.setAttribute(HOST, StringUtil.notNullize(getHost()));
+    rootElement.setAttribute(PORT, Integer.toString(getPort()));
+    rootElement.setAttribute(ANONYMOUS, Boolean.toString(isAnonymous()));
+    rootElement.setAttribute(USERNAME, getSerializedUserName());
+    rootElement.setAttribute(PASSWORD, getSerializedPassword());
+    rootElement.setAttribute(PRIVATE_KEY_FILE, StringUtil.notNullize(getPrivateKeyFile()));
+    rootElement.setAttribute(KNOWN_HOSTS_FILE, StringUtil.notNullize(getKnownHostsFile()));
+    rootElement.setAttribute(PASSPHRASE, getSerializedPassphrase());
+    rootElement.setAttribute(USE_KEY_PAIR, Boolean.toString(isUseKeyPair()));
+  }
+
+  public void copyFrom(RemoteCredentials from) {
+    setHost(from.getHost());
+    setPort(from.getPort());
+    setAnonymous(from.isAnonymous());
+    setUserName(from.getUserName());
+    setPassword(from.getPassword());
+    setUseKeyPair(from.isUseKeyPair());
+    setPrivateKeyFile(from.getPrivateKeyFile());
+    setKnownHostsFile(from.getKnownHostsFile());
+    setStorePassword(from.isStorePassword());
+    setStorePassphrase(from.isStorePassphrase());
+  }
 }
index 11f14f05119dec730f54d623a977299ea0493e42..8d094aea8c46e47a301fe3734f42d4a100c0c79c 100644 (file)
@@ -4,4 +4,5 @@ package com.intellij.remotesdk;
  * @author traff
  */
 public interface RemoteSdkCredentials extends MutableRemoteCredentials, RemoteSdkProperties {
+  String getFullInterpreterPath();
 }
index 88663598f9c67262bca6ebe0176c66e8815accdb..6a2e5c2a485b9bd95739e5b3d0d3882a659bc145 100644 (file)
@@ -1,11 +1,10 @@
 package com.intellij.remotesdk;
 
-import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.remotesdk2.RemoteConnectionCredentialsWrapper;
 import org.jdom.Element;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.LinkedList;
 import java.util.List;
 
 /**
@@ -13,11 +12,6 @@ import java.util.List;
  */
 public class RemoteSdkCredentialsHolder extends RemoteCredentialsHolder implements RemoteSdkCredentials {
   public static final String SSH_PREFIX = "ssh://";
-  private static final String INTERPRETER_PATH = "INTERPRETER_PATH";
-  private static final String HELPERS_PATH = "HELPERS_PATH";
-  private static final String REMOTE_ROOTS = "REMOTE_ROOTS";
-  private static final String REMOTE_PATH = "REMOTE_PATH";
-  private static final String INITIALIZED = "INITIALIZED";
 
   @NotNull
   private final RemoteSdkPropertiesHolder myRemoteSdkProperties;
@@ -30,7 +24,6 @@ public class RemoteSdkCredentialsHolder extends RemoteCredentialsHolder implemen
     return SSH_PREFIX + cred.getUserName() + "@" + cred.getHost() + ":" + cred.getPort() + cred.getInterpreterPath();
   }
 
-
   /**
    * Extracts interpreter path from full path generated by method getFullInterpreterPath
    * Returns fullPath as fallback
@@ -118,7 +111,7 @@ public class RemoteSdkCredentialsHolder extends RemoteCredentialsHolder implemen
 
   @Override
   public String getFullInterpreterPath() {
-    return myRemoteSdkProperties.getFullInterpreterPath();
+    return constructSshCredentialsSdkFullPath(this);
   }
 
   @Override
@@ -126,6 +119,11 @@ public class RemoteSdkCredentialsHolder extends RemoteCredentialsHolder implemen
     myRemoteSdkProperties.setSdkId(sdkId);
   }
 
+  @Override
+  public String getSdkId() {
+    return myRemoteSdkProperties.getSdkId();
+  }
+
   @Override
   public boolean isInitialized() {
     return myRemoteSdkProperties.isInitialized();
@@ -138,64 +136,27 @@ public class RemoteSdkCredentialsHolder extends RemoteCredentialsHolder implemen
 
   public static boolean isRemoteSdk(@Nullable String path) {
     if (path != null) {
-      return path.startsWith(SSH_PREFIX);
+      return path.startsWith(SSH_PREFIX) || path.startsWith(RemoteConnectionCredentialsWrapper.VAGRANT_PREFIX) ||
+             path.startsWith(RemoteConnectionCredentialsWrapper.SFTP_DEPLOYMENT_PREFIX);
     }
     else {
       return false;
     }
   }
 
-  public void loadRemoteSdkCredentials(Element element) {
-    setHost(element.getAttributeValue(HOST));
-    setPort(StringUtil.parseInt(element.getAttributeValue(PORT), 22));
-    setAnonymous(StringUtil.parseBoolean(element.getAttributeValue(ANONYMOUS), false));
-    setSerializedUserName(element.getAttributeValue(USERNAME));
-    setSerializedPassword(element.getAttributeValue(PASSWORD));
-    setPrivateKeyFile(StringUtil.nullize(element.getAttributeValue(PRIVATE_KEY_FILE)));
-    setKnownHostsFile(StringUtil.nullize(element.getAttributeValue(KNOWN_HOSTS_FILE)));
-    setSerializedPassphrase(element.getAttributeValue(PASSPHRASE));
-    setUseKeyPair(StringUtil.parseBoolean(element.getAttributeValue(USE_KEY_PAIR), false));
-
-    setInterpreterPath(StringUtil.nullize(element.getAttributeValue(INTERPRETER_PATH)));
-    setHelpersPath(StringUtil.nullize(element.getAttributeValue(HELPERS_PATH)));
 
-    setRemoteRoots(loadStringsList(element, REMOTE_ROOTS, REMOTE_PATH));
+  @Override
+  public void load(Element element) {
+    super.load(element);
 
-    setInitialized(StringUtil.parseBoolean(element.getAttributeValue(INITIALIZED), true));
+    myRemoteSdkProperties.load(element);
   }
 
-  protected static List<String> loadStringsList(Element element, String rootName, String attrName) {
-    final List<String> paths = new LinkedList<String>();
-    if (element != null) {
-      @NotNull final List list = element.getChildren(rootName);
-      for (Object o : list) {
-        paths.add(((Element)o).getAttribute(attrName).getValue());
-      }
-    }
-    return paths;
-  }
+  @Override
+  public void save(Element rootElement) {
+    super.save(rootElement);
 
-  public void saveRemoteSdkData(Element rootElement) {
-    rootElement.setAttribute(HOST, StringUtil.notNullize(getHost()));
-    rootElement.setAttribute(PORT, Integer.toString(getPort()));
-    rootElement.setAttribute(ANONYMOUS, Boolean.toString(isAnonymous()));
-    rootElement.setAttribute(USERNAME, getSerializedUserName());
-    rootElement.setAttribute(PASSWORD, getSerializedPassword());
-    rootElement.setAttribute(PRIVATE_KEY_FILE, StringUtil.notNullize(getPrivateKeyFile()));
-    rootElement.setAttribute(KNOWN_HOSTS_FILE, StringUtil.notNullize(getKnownHostsFile()));
-    rootElement.setAttribute(PASSPHRASE, getSerializedPassphrase());
-    rootElement.setAttribute(USE_KEY_PAIR, Boolean.toString(isUseKeyPair()));
-
-    rootElement.setAttribute(INTERPRETER_PATH, StringUtil.notNullize(getInterpreterPath()));
-    rootElement.setAttribute(HELPERS_PATH, StringUtil.notNullize(getHelpersPath()));
-
-    rootElement.setAttribute(INITIALIZED, Boolean.toString(isInitialized()));
-
-    for (String remoteRoot : getRemoteRoots()) {
-      final Element child = new Element(REMOTE_ROOTS);
-      child.setAttribute(REMOTE_PATH, remoteRoot);
-      rootElement.addContent(child);
-    }
+    myRemoteSdkProperties.save(rootElement);
   }
 
 
@@ -268,8 +229,8 @@ public class RemoteSdkCredentialsHolder extends RemoteCredentialsHolder implemen
            '}';
   }
 
-  public void copyTo(RemoteSdkCredentialsHolder to) {
-    super.copyTo(to);
+  public void copyRemoteSdkCredentialsTo(RemoteSdkCredentialsHolder to) {
+    super.copyRemoteCredentialsTo(to);
     myRemoteSdkProperties.copyTo(to.getRemoteSdkProperties());
   }
 }
index 5e98352accf63f7c5389967704b144573998381c..ed7fe6bd00c0192b309dda87c3f6de729a48f4b4 100644 (file)
@@ -43,10 +43,10 @@ public interface RemoteSdkProperties {
 
   void setHelpersVersionChecked(boolean helpersVersionChecked);
 
-  String getFullInterpreterPath();
-
   void setSdkId(String sdkId);
 
+  String getSdkId();
+
   @Deprecated
   boolean isInitialized();
 
index 11f350ca10c5cc8a21279a12dbb08312793df57e..5b63720a5d50a214fee355509fca40837dc31608 100644 (file)
  */
 package com.intellij.remotesdk;
 
+import com.intellij.openapi.util.JDOMExternalizer;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jdom.Element;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -22,6 +26,12 @@ import java.util.List;
  * @author traff
  */
 public class RemoteSdkPropertiesHolder implements RemoteSdkProperties {
+  private static final String INTERPRETER_PATH = "INTERPRETER_PATH";
+  private static final String HELPERS_PATH = "HELPERS_PATH";
+  private static final String REMOTE_ROOTS = "REMOTE_ROOTS";
+  private static final String REMOTE_PATH = "REMOTE_PATH";
+  private static final String INITIALIZED = "INITIALIZED";
+
   private String mySdkId;
 
   private String myInterpreterPath;
@@ -93,15 +103,14 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties {
     myHelpersVersionChecked = helpersVersionChecked;
   }
 
-  @Override
-  public String getFullInterpreterPath() {
-    return mySdkId;
-  }
-
   public void setSdkId(String sdkId) {
     mySdkId = sdkId;
   }
 
+  public String getSdkId() {
+    return mySdkId;
+  }
+
   @Override
   public boolean isInitialized() {
     return myInitialized;
@@ -113,7 +122,7 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties {
 
   }
 
-  public void copyTo(RemoteSdkPropertiesHolder copy) {
+  public void copyTo(RemoteSdkProperties copy) {
     copy.setInterpreterPath(getInterpreterPath());
     copy.setHelpersPath(getHelpersPath());
     copy.setHelpersVersionChecked(isHelpersVersionChecked());
@@ -122,4 +131,26 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties {
 
     copy.setInitialized(isInitialized());
   }
+
+  public void save(Element rootElement) {
+    rootElement.setAttribute(INTERPRETER_PATH, StringUtil.notNullize(getInterpreterPath()));
+    rootElement.setAttribute(HELPERS_PATH, StringUtil.notNullize(getHelpersPath()));
+
+    rootElement.setAttribute(INITIALIZED, Boolean.toString(isInitialized()));
+
+    for (String remoteRoot : getRemoteRoots()) {
+      final Element child = new Element(REMOTE_ROOTS);
+      child.setAttribute(REMOTE_PATH, remoteRoot);
+      rootElement.addContent(child);
+    }
+  }
+
+  public void load(Element element) {
+    setInterpreterPath(StringUtil.nullize(element.getAttributeValue(INTERPRETER_PATH)));
+    setHelpersPath(StringUtil.nullize(element.getAttributeValue(HELPERS_PATH)));
+
+    setRemoteRoots(JDOMExternalizer.loadStringsList(element, REMOTE_ROOTS, REMOTE_PATH));
+
+    setInitialized(StringUtil.parseBoolean(element.getAttributeValue(INITIALIZED), true));
+  }
 }
diff --git a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteConnectionCredentialsWrapper.java b/platform/platform-impl/src/com/intellij/remotesdk2/RemoteConnectionCredentialsWrapper.java
new file mode 100644 (file)
index 0000000..b51c9fb
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2000-2014 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.remotesdk2;
+
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.UserDataHolderBase;
+import com.intellij.remotesdk.RemoteCredentials;
+import com.intellij.remotesdk.RemoteCredentialsHolder;
+import com.intellij.remotesdk.RemoteSdkCredentialsHolder;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author traff
+ */
+public class RemoteConnectionCredentialsWrapper {
+  public static final String VAGRANT_PREFIX = "vagrant://";
+  public static final String SFTP_DEPLOYMENT_PREFIX = "sftp://";
+
+  public final Key<VagrantBasedCredentialsHolder> VAGRANT_BASED_CREDENTIALS = Key.create("VAGRANT_BASED_CREDENTIALS");
+  public final Key<WebDeploymentCredentialsHolder> WEB_DEPLOYMENT_BASED_CREDENTIALS = Key.create("WEB_DEPLOYMENT_BASED_CREDENTIALS");
+
+  public final Key<RemoteCredentialsHolder> PLAIN_SSH_CREDENTIALS = Key.create("PLAIN_SSH_CREDENTIALS");
+
+  private UserDataHolderBase myCredentialsTypeHolder = new UserDataHolderBase();
+
+  public void setVagrantConnectionType(VagrantBasedCredentialsHolder vagrantBasedCredentials) {
+    myCredentialsTypeHolder.putUserData(VAGRANT_BASED_CREDENTIALS, vagrantBasedCredentials);
+  }
+
+
+  private VagrantBasedCredentialsHolder getVagrantCredentials() {
+    return myCredentialsTypeHolder.getUserData(VAGRANT_BASED_CREDENTIALS);
+  }
+
+  public void setPlainSshCredentials(RemoteCredentialsHolder credentials) {
+    myCredentialsTypeHolder.putUserData(PLAIN_SSH_CREDENTIALS, credentials);
+  }
+
+  private RemoteCredentialsHolder getPlainSshCredentials() {
+    return myCredentialsTypeHolder.getUserData(PLAIN_SSH_CREDENTIALS);
+  }
+
+
+  public void setWebDeploymentCredentials(WebDeploymentCredentialsHolder webDeploymentCredentials) {
+    myCredentialsTypeHolder.putUserData(WEB_DEPLOYMENT_BASED_CREDENTIALS, webDeploymentCredentials);
+  }
+
+  private WebDeploymentCredentialsHolder getWebDeploymentCredentials() {
+    return myCredentialsTypeHolder.getUserData(WEB_DEPLOYMENT_BASED_CREDENTIALS);
+  }
+
+  private boolean isVagrantConnection() {
+    return getVagrantCredentials() != null;
+  }
+
+  private boolean isPlainSshConnection() {
+    return getPlainSshCredentials() != null;
+  }
+
+  private boolean isWebDeploymentConnection() {
+    return getWebDeploymentCredentials() != null;
+  }
+
+
+  public Object getConnectionKey() {
+    if (isVagrantConnection()) {
+      return getVagrantCredentials();
+    }
+    else if (isPlainSshConnection()) {
+      return getPlainSshCredentials();
+    }
+    else if (isWebDeploymentConnection()) {
+      return getWebDeploymentCredentials();
+    }
+    else {
+      throw unknownConnectionType();
+    }
+  }
+
+  public void save(final Element rootElement) {
+    switchType(new RemoteSdkConnectionAcceptor() {
+      @Override
+      public void ssh(RemoteCredentialsHolder cred) {
+        cred.save(rootElement);
+      }
+
+      @Override
+      public void vagrant(VagrantBasedCredentialsHolder cred) {
+        cred.save(rootElement);
+      }
+
+      @Override
+      public void deployment(WebDeploymentCredentialsHolder cred) {
+        cred.save(rootElement);
+      }
+    });
+  }
+
+  public static IllegalStateException unknownConnectionType() {
+    return new IllegalStateException("Unknown connection type"); //TODO
+  }
+
+  public void copyTo(RemoteConnectionCredentialsWrapper copy) {
+    copy.myCredentialsTypeHolder = new UserDataHolderBase();
+    copy.setPlainSshCredentials(getPlainSshCredentials());
+    copy.setVagrantConnectionType(getVagrantCredentials());
+    copy.setWebDeploymentCredentials(getWebDeploymentCredentials());
+  }
+
+  public String getId() {
+    if (isVagrantConnection()) {
+      @NotNull VagrantBasedCredentialsHolder cred = getVagrantCredentials();
+
+      return VAGRANT_PREFIX + cred.getVagrantFolder();
+    }
+    else if (isPlainSshConnection()) {
+      RemoteCredentials cred = getPlainSshCredentials();
+
+      return constructSshCredentialsFullPath(cred);
+    }
+    else if (isWebDeploymentConnection()) {
+      WebDeploymentCredentialsHolder cred = getWebDeploymentCredentials();
+      return constructSftpCredentialsFullPath(cred.getSshCredentials());
+    }
+    else {
+      throw unknownConnectionType();
+    }
+  }
+
+  private static String constructSftpCredentialsFullPath(RemoteCredentials cred) {
+    return SFTP_DEPLOYMENT_PREFIX + cred.getUserName() + "@" + cred.getHost() + ":" + cred.getPort();
+  }
+
+
+  public static String constructSshCredentialsFullPath(RemoteCredentials cred) {
+    return RemoteSdkCredentialsHolder.SSH_PREFIX + cred.getUserName() + "@" + cred.getHost() + ":" + cred.getPort();
+  }
+
+  public void switchType(RemoteSdkConnectionAcceptor acceptor) {
+    if (isVagrantConnection()) {
+      acceptor.vagrant(getVagrantCredentials());
+    }
+    else if (isPlainSshConnection()) {
+      acceptor.ssh(getPlainSshCredentials());
+    }
+    else if (isWebDeploymentConnection()) {
+      acceptor.deployment(getWebDeploymentCredentials());
+    }
+    else {
+      throw unknownConnectionType();
+    }
+  }
+
+  public interface RemoteSdkConnectionAcceptor {
+    void ssh(RemoteCredentialsHolder cred);
+    void vagrant(VagrantBasedCredentialsHolder cred);
+    void deployment(WebDeploymentCredentialsHolder cred);
+  }
+}
index 92ec30233a6c2f42945d94bbdb9564c0755b9c78..c295a42c9598f5ce9459583e36a386768797b492 100644 (file)
@@ -19,6 +19,7 @@ import com.intellij.openapi.projectRoots.SdkAdditionalData;
 import com.intellij.remotesdk.RemoteSdkCredentials;
 import com.intellij.remotesdk.RemoteSdkCredentialsHolder;
 import com.intellij.remotesdk.RemoteSdkProperties;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * @author traff
@@ -33,9 +34,13 @@ public interface RemoteSdkAdditionalData2<T extends RemoteSdkCredentials>
 
   String getFullInterpreterPath();
 
+  void setVagrantConnectionType(@NotNull VagrantBasedCredentialsHolder vagrantBasedCredentials);
+
   /**
    * This method switches to use of ssh-credentials based data
    * @param credentials credentials that specify connection
    */
-  void setSshCredentials(RemoteSdkCredentialsHolder credentials);
+  void setSshCredentials(@NotNull RemoteSdkCredentialsHolder credentials);
+
+  void setDeploymentConnectionType(@NotNull WebDeploymentCredentialsHolder credentials);
 }
index 72c585b642cd19ba991c625ee2c029aab81d440b..0178ab8a275226252f2a4cbd009d71a5c5ab5a28 100644 (file)
@@ -24,7 +24,7 @@ import com.intellij.util.Consumer;
 public interface RemoteSdkProducer<T extends RemoteSdkCredentials> {
   T getRemoteSdkCredentials() throws InterruptedException;
   
-  void produceRemoteSdkCredentials(Consumer<T> remoteSdkConsumer);
+  void produceRemoteSdkCredentials(Consumer<T> remoteSdkCredentialsConsumer);
 
   Object getRemoteSdkDataKey();
 }
diff --git a/platform/platform-impl/src/com/intellij/remotesdk2/VagrantBasedCredentialsHolder.java b/platform/platform-impl/src/com/intellij/remotesdk2/VagrantBasedCredentialsHolder.java
new file mode 100644 (file)
index 0000000..8e9d36f
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2014 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.remotesdk2;
+
+import com.intellij.openapi.util.text.StringUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+
+/**
+* @author traff
+*/
+public class VagrantBasedCredentialsHolder {
+  private static final String VAGRANT_FOLDER = "VAGRANT_FOLDER";
+  private String myVagrantFolder;
+
+  public VagrantBasedCredentialsHolder() {
+  }
+
+  public VagrantBasedCredentialsHolder(@NotNull String folder) {
+    myVagrantFolder = folder;
+  }
+
+  public void setVagrantFolder(String vagrantFolder) {
+    myVagrantFolder = vagrantFolder;
+  }
+
+  @NotNull
+  public String getVagrantFolder() {
+    return myVagrantFolder;
+  }
+
+  public void load(Element element) {
+    setVagrantFolder(element.getAttributeValue(VAGRANT_FOLDER));
+  }
+
+  public void save(Element element) {
+    element.setAttribute(VAGRANT_FOLDER, getVagrantFolder());
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/remotesdk2/WebDeploymentCredentialsHolder.java b/platform/platform-impl/src/com/intellij/remotesdk2/WebDeploymentCredentialsHolder.java
new file mode 100644 (file)
index 0000000..d43d0cb
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2000-2014 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.remotesdk2;
+
+import com.intellij.remotesdk.RemoteCredentials;
+import com.intellij.remotesdk.RemoteCredentialsHolder;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author traff
+ */
+public class WebDeploymentCredentialsHolder {
+  public static final String WEB_SERVER_CONFIG_ID = "WEB_SERVER_CONFIG_ID";
+
+  private String myWebServerConfigId;
+  private final RemoteCredentialsHolder myRemoteCredentials = new RemoteCredentialsHolder();
+
+
+  public WebDeploymentCredentialsHolder() {
+  }
+
+  public WebDeploymentCredentialsHolder(@NotNull String webServerConfigId, @NotNull RemoteCredentials remoteCredentials) {
+    myWebServerConfigId = webServerConfigId;
+    myRemoteCredentials.copyFrom(remoteCredentials);
+  }
+
+  @NotNull
+  public String getWebServerConfigId() {
+    return myWebServerConfigId;
+  }
+
+  public void setWebServerConfigId(@NotNull String webServerConfigId) {
+    myWebServerConfigId = webServerConfigId;
+  }
+
+  public void load(Element element) {
+    myRemoteCredentials.load(element);
+    setWebServerConfigId(element.getAttributeValue(WEB_SERVER_CONFIG_ID));
+  }
+
+  public void save(Element element) {
+    element.setAttribute(WEB_SERVER_CONFIG_ID, getWebServerConfigId());
+
+    myRemoteCredentials.save(element);
+  }
+
+  public RemoteCredentials getSshCredentials() {
+    return myRemoteCredentials;
+  }
+}
index cf1104a405a2b9dbf6bbb2a205ab8e4528de37e3..51ebd5ef5c0c6a3846a8936a851cc2784bb86acf 100644 (file)
@@ -20,6 +20,8 @@ import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.TestOnly;
 import org.jetbrains.io.BuiltInServer;
 
+import java.util.Random;
+import java.util.UUID;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -39,11 +41,12 @@ public class BuiltInServerManagerImpl extends BuiltInServerManager {
   private BuiltInServer server;
   private boolean enabledInUnitTestMode = true;
 
-  //static {
-  //  // IDEA-120811
-  //  System.setProperty("io.netty.machineId", Integer.toHexString(new Random().nextInt()));
-  //  System.setProperty("io.netty.processId", "1");
-  //}
+  static {
+    // IDEA-120811
+    String id = UUID.randomUUID().toString();
+    System.setProperty("io.netty.machineId", id.substring(id.length() - 8));
+    System.setProperty("io.netty.processId", Integer.toString(new Random().nextInt(65535)));
+  }
 
   @Override
   public int getPort() {
index 2c4adec5a67474a7d3ced262a261fa1b5b1f218e..88d691d7ccdcddead94b05fda96ae8de8d2053dd 100644 (file)
@@ -108,7 +108,7 @@ action.EditorMoveDownAndScrollWithSelection.text=Move Down and Scroll with Selec
 action.EditorCloneCaretBelow.text=Clone Caret Below
 action.EditorCloneCaretAbove.text=Clone Caret Above
 action.SelectNextOccurrence.text=Select Next Occurrence
-action.UnselectLastOccurrence.text=Unselect Last Occurrence
+action.UnselectPreviousOccurrence.text=Unselect Occurrence
 action.EditorToggleStickySelection.text=Toggle Sticky Selection
 action.EditorSwapSelectionBoundaries.text=Swap selection boundaries
 action.EditorLineStart.text=Move Caret to Line Start
index 66a7bab05489475e359de2d82e1f1be497daf849..043f6f2231fd2f9f34a1aa4b5e21a82c7d512b8f 100644 (file)
@@ -32,7 +32,7 @@ diff.acton.ignore.whitespace.policy.do.not.ignore=Do not ignore
 diff.acton.ignore.whitespace.policy.leading.and.trailing=Leading and trailing
 diff.acton.ignore.whitespace.policy.all=All
 ignore.whitespace.acton.name=Ignore whitespace:
-ignore.whitespace.action.not.available.action.name=<Not available>
+diff.panel.combo.box.action.not.available.action.name=<Not available>
 diff.dialog.select.change.action.name=Select Change
 diff.dialog.select.change.action.description=Select changed text in this version and corresponding in other
 merge.files.dialog.title=Merge
@@ -88,5 +88,4 @@ diff.can.not.show.unknown=Can not show diff for unknown file type
 diff.acton.highlight.mode.action.by.word=By Word
 diff.acton.highlight.mode.action.by.line=By Line
 diff.acton.highlight.mode.action.no.highlighting=No Highlighting
-diff.acton.highlight.mode.not.available.action.name=<Not available>
 diff.acton.highlight.mode.action.name=Highlighting Mode:
index d43993b72313bfa3109f0f470fb5ff0d34d6b095..b3f6d7f21226a14840efef31543d2d6a26b57262 100644 (file)
           <option name="EFFECT_COLOR"/>
         </value>
       </option>
-      <option name="REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES">
-        <value>
-          <option name="FOREGROUND"/>
-          <option name="BACKGROUND"/>
-          <option name="EFFECT_COLOR"/>
-        </value>
-      </option>
-      <option name="REASSIGNED_PARAMETER_ATTRIBUTES">
-        <value>
-          <option name="FOREGROUND"/>
-          <option name="BACKGROUND"/>
-          <option name="EFFECT_COLOR"/>
-        </value>
-      </option>
       <option name="IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES">
         <value>
           <option name="FOREGROUND" value="660e7a"/>
index 447d4abfb64913f4edc965bd0e8ca538e13cc65f..1127d78f3ae3a76aa786e85c4ca4f69dd3ddf903 100644 (file)
   <action id="SelectNextOccurrence">
     <keyboard-shortcut first-keystroke="alt J"/>
   </action>
-  <action id="UnselectLastOccurrence">
+  <action id="UnselectPreviousOccurrence">
     <keyboard-shortcut first-keystroke="alt shift J"/>
   </action>
   <action id="GotoDeclaration">
index 2a28414bd583dadebecaa7368ce78caff9709235..ddc2dbc1b5ca9899692673d2fef988fa788f68f1 100644 (file)
     <action id="SelectNextOccurrence">
       <keyboard-shortcut first-keystroke="alt Y"/>
     </action>
-    <action id="UnselectLastOccurrence">
+    <action id="UnselectPreviousOccurrence">
       <keyboard-shortcut first-keystroke="alt shift Y"/>
     </action>
     <action id="FindUsages">
index 044d5b91c7c7db86d8a58e5fb1ff9870d97b89ea..a66911c122d4ab05c7957c5fe235e5e99d06f7a8 100644 (file)
     <action id="SelectNextOccurrence">
       <keyboard-shortcut first-keystroke="control G"/>
     </action>
-    <action id="UnselectLastOccurrence">
+    <action id="UnselectPreviousOccurrence">
       <keyboard-shortcut first-keystroke="control shift G"/>
     </action>
 
index 9d2b440f27976c93f1f6a7521ca927c0d36f0e0c..7e327885950405361b6f61a734f465bfb593a3a3 100644 (file)
     <action id="SelectNextOccurrence">
       <keyboard-shortcut first-keystroke="control G"/>
     </action>
-    <action id="UnselectLastOccurrence">
+    <action id="UnselectPreviousOccurrence">
       <keyboard-shortcut first-keystroke="control shift G"/>
     </action>
 
index e0e136024f2a38fa3ebe9b6febd9ee0c09b4cf82..fdd3809aed95ad26a10589d3a9e0c45a183782e2 100644 (file)
           <action id="FindPrevious" class="com.intellij.ide.actions.SearchBackAction"/>
           <action id="FindWordAtCaret" class="com.intellij.openapi.editor.actions.FindWordAtCaretAction"/>
           <action id="SelectNextOccurrence" class="com.intellij.openapi.editor.actions.SelectNextOccurrenceAction"/>
-          <action id="UnselectLastOccurrence" class="com.intellij.openapi.editor.actions.UnselectLastOccurrenceAction"/>
+          <action id="UnselectPreviousOccurrence" class="com.intellij.openapi.editor.actions.UnselectPreviousOccurrenceAction"/>
           <separator/>
           <action id="FindInPath" class="com.intellij.find.actions.FindInPathAction"/>
           <action id="ReplaceInPath" class="com.intellij.find.actions.ReplaceInPathAction"/>
index 7eb6c45e6b4f2b791fc5873d170c5a5745effc05..de5a6ba61b2b803cf026a5efd7cbee05555c58aa 100644 (file)
@@ -31,4 +31,13 @@ public class IgnoreWhiteSpaceTest extends TestCase {
     assertEquals(keys[1], keys[2]);
     assertFalse(keys[2].equals(keys[3]));
   }
+
+  public static void assertEquals(Object obj1, Object obj2) {
+    if (obj1 instanceof CharSequence && obj2 instanceof CharSequence) {
+      assertEquals(obj1.toString(), obj2.toString());
+      return;
+    }
+
+    assertEquals(obj1, obj2);
+  }
 }
index db929203a68abba5a19e0b69d68e02ee4096d350..1d19fb92ee44bcbbecd23945a24a7a088ed2a62c 100644 (file)
@@ -2,6 +2,7 @@ package com.intellij.openapi.diff.impl.highlighting;
 
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.MultiCheck;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.util.Assertion;
 import com.intellij.util.diff.Diff;
 import com.intellij.util.diff.FilesTooBigForDiffException;
@@ -209,10 +210,11 @@ public class UtilTest extends TestCase {
       last};
     lines = Util.uniteFormattingOnly(lines);
     CHECK.compareAll(new DiffFragment[][]{
-      first,
-      new DiffFragment[]{inline1, inline2, inline3, inline4},
-      last},
-                     lines);
+                       first,
+                       new DiffFragment[]{inline1, inline2, inline3, inline4},
+                       last},
+                     lines
+    );
   }
 
   public void testConcatenateEquals() {
@@ -246,7 +248,8 @@ public class UtilTest extends TestCase {
     CHECK.singleElement(Util.cutFirst(new DiffFragment[]{
                           DiffFragment.unchanged("ab", "ac")
                         }),
-                        DiffFragment.unchanged("b", "c"));
+                        DiffFragment.unchanged("b", "c")
+    );
 
     CHECK.compareAll(new DiffFragment[]{
                        new DiffFragment(null, "c")
@@ -264,7 +267,8 @@ public class UtilTest extends TestCase {
                      Util.cutFirst(new DiffFragment[]{
                        new DiffFragment(null, "ab"),
                        new DiffFragment("c", "d")
-                     }));
+                     })
+    );
   }
 
   public void testCutFirst2() {
@@ -293,4 +297,8 @@ public class UtilTest extends TestCase {
                      }));
 
   }
+
+  public static void assertEquals(CharSequence obj1, CharSequence obj2) {
+    assertEquals(obj1.toString(), obj2.toString());
+  }
 }
index badcc338a4458dec6b44ab79b8c4f11286b4ffa9..2baf119ba240be09b5e803b3d03529b5a20442cf 100644 (file)
@@ -5,7 +5,6 @@ import com.intellij.openapi.diff.impl.ComparisonPolicy;
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
 import com.intellij.openapi.diff.impl.highlighting.Util;
 import com.intellij.util.diff.FilesTooBigForDiffException;
-import junit.framework.Assert;
 import junit.framework.TestCase;
 
 public class LineBlocksDiffPolicyTest extends TestCase{
@@ -16,9 +15,9 @@ public class LineBlocksDiffPolicyTest extends TestCase{
     checkPolicy(diffPolicy, "abc\n123\n", "ABC\nXYZ");
   }
 
-  private void checkPolicy(DiffPolicy.LineBlocks diffPolicy, String text1, String text2) throws FilesTooBigForDiffException {
+  private static void checkPolicy(DiffPolicy.LineBlocks diffPolicy, String text1, String text2) throws FilesTooBigForDiffException {
     DiffFragment[] fragments = diffPolicy.buildFragments(text1, text2);
-    Assert.assertEquals(text1, Util.getText(fragments, FragmentSide.SIDE1));
-    assertEquals(text2, Util.getText(fragments, FragmentSide.SIDE2));
+    assertEquals(text1, Util.getText(fragments, FragmentSide.SIDE1).toString());
+    assertEquals(text2, Util.getText(fragments, FragmentSide.SIDE2).toString());
   }
 }
index 4d4ed9b9937fe7d8c9220d36c52b4f4ab43d8f28..854a17d47ebd2e6d9782d52163a2cd6addb12c97 100644 (file)
@@ -5,12 +5,12 @@ import com.intellij.openapi.diff.impl.fragments.LineFragment;
 import com.intellij.util.diff.FilesTooBigForDiffException;
 import junit.framework.TestCase;
 
-import java.util.ArrayList;
+import java.util.List;
 
 public class TextCompareProcessorTest extends TestCase {
   public void testIgnoreWrappingEqualText() throws FilesTooBigForDiffException {
     TextCompareProcessor processor = new TextCompareProcessor(ComparisonPolicy.IGNORE_SPACE);
-    ArrayList<LineFragment> lineFragments = processor.process("f(a, b)\n", "f(a,\nb)\n");
+    List<LineFragment> lineFragments = processor.process("f(a, b)\n", "f(a,\nb)\n");
     assertTrue(lineFragments.size() == 1);
     assertNull(lineFragments.get(0).getType());
   }
index 90a82e972379419473b753b19edb009ec3d26f5d..51653510c33181ea40fa7c9f034cb3c271d2d99d 100644 (file)
@@ -182,6 +182,6 @@ public class SelectUnselectOccurrenceActionsTest extends LightPlatformCodeInsigh
   }
 
   private void executeReverseAction() {
-    myFixture.performEditorAction(IdeActions.ACTION_UNSELECT_LAST_OCCURENCE);
+    myFixture.performEditorAction(IdeActions.ACTION_UNSELECT_PREVIOUS_OCCURENCE);
   }
 }
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/EnforcedPlaintTextFileTypeManagerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/EnforcedPlaintTextFileTypeManagerTest.java
new file mode 100644 (file)
index 0000000..2fe2787
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2014 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.fileTypes;
+
+import com.intellij.openapi.file.exclude.EnforcedPlainTextFileTypeFactory;
+import com.intellij.openapi.file.exclude.EnforcedPlainTextFileTypeManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
+
+/**
+ * @author Rustam Vishnyakov
+ */
+public class EnforcedPlaintTextFileTypeManagerTest extends LightPlatformCodeInsightFixtureTestCase {
+  public void testMarkAsPlainText() {
+    EnforcedPlainTextFileTypeManager manager = EnforcedPlainTextFileTypeManager.getInstance();
+    VirtualFile file = myFixture.getTempDirFixture().createFile("test.java");
+    FileType originalType = file.getFileType();
+    assertEquals("JAVA", originalType.getName());
+    manager.markAsPlainText(file);
+    FileType changedType = file.getFileType();
+    assertEquals(EnforcedPlainTextFileTypeFactory.ENFORCED_PLAIN_TEXT, changedType.getName());
+    manager.resetOriginalFileType(file);
+    FileType revertedType = file.getFileType();
+    assertEquals(originalType, revertedType);
+  }
+}
index 7aafcacf7fbb5dab1b50646418075861fb722693..e86567bde782ec9a77f208d0ff0a0493251087f1 100644 (file)
@@ -17,18 +17,14 @@ package com.intellij.openapi.diff;
 
 import com.intellij.util.ArrayUtil;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
 import java.util.List;
 
-public class LineTokenizer {
+public class LineTokenizer extends LineTokenizerBase<String> {
   private final char[] myChars;
   private final String myText;
 
-  private int myIndex = 0;
-  @Nullable private String myLineSeparator = null;
-
   public LineTokenizer(@NotNull String text) {
     myChars = text.toCharArray();
     myText = text;
@@ -36,71 +32,35 @@ public class LineTokenizer {
 
   @NotNull
   public String[] execute() {
-    List<String> lines = new ArrayList<String>();
-    while (notAtEnd()) {
-      int begin = myIndex;
-      skipToEOL();
-      int endIndex = myIndex;
-      boolean appendNewLine = false;
-
-      if (notAtEnd() && isAtEOL()) {
-        if (myChars[endIndex] == '\n') {
-          endIndex++;
-        }
-        else {
-          appendNewLine = true;
-        }
-        skipEOL();
-      }
-
-      String line = myText.substring(begin, endIndex);
-      if (appendNewLine) {
-        line += "\n";
-      }
-      lines.add(line);
-    }
+    ArrayList<String> lines = new ArrayList<String>();
+    doExecute(lines);
     return ArrayUtil.toStringArray(lines);
   }
 
-  private void skipEOL() {
-    int eolStart = myIndex;
-    boolean nFound = false;
-    boolean rFound = false;
-    while (notAtEnd()) {
-      boolean n = myChars[myIndex] == '\n';
-      boolean r = myChars[myIndex] == '\r';
-      if (!n && !r) {
-        break;
-      }
-      if ((nFound && n) || (rFound && r)) {
-        break;
-      }
-      nFound |= n;
-      rFound |= r;
-      myIndex++;
+  @Override
+  protected void addLine(List<String> lines, int start, int end, boolean appendNewLine) {
+    if (appendNewLine) {
+      lines.add(myText.substring(start, end) + "\n");
     }
-    if (myLineSeparator == null) {
-      myLineSeparator = new String(myChars, eolStart, myIndex - eolStart);
+    else {
+      lines.add(myText.substring(start, end));
     }
   }
 
-  @Nullable
-  public String getLineSeparator() {
-    return myLineSeparator;
+  @Override
+  protected char charAt(int index) {
+    return myChars[index];
   }
 
-  private void skipToEOL() {
-    while (notAtEnd() && !isAtEOL()) {
-      myIndex++;
-    }
-  }
-
-  private boolean notAtEnd() {
-    return myIndex < myChars.length;
+  @Override
+  protected int length() {
+    return myChars.length;
   }
 
-  private boolean isAtEOL() {
-    return myChars[myIndex] == '\r' || myChars[myIndex] == '\n';
+  @NotNull
+  @Override
+  protected String substring(int start, int end) {
+    return myText.substring(start, end);
   }
 
   @NotNull
diff --git a/platform/util/src/com/intellij/openapi/diff/LineTokenizerBase.java b/platform/util/src/com/intellij/openapi/diff/LineTokenizerBase.java
new file mode 100644 (file)
index 0000000..85fed35
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2000-2014 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;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public abstract class LineTokenizerBase<T> {
+  private int myIndex = 0;
+  private int myLineSeparatorStart = -1;
+  private int myLineSeparatorEnd = -1;
+
+  protected abstract void addLine(List<T> lines, int start, int end, boolean appendNewLine);
+
+  protected abstract char charAt(int index);
+
+  protected abstract int length();
+
+  @NotNull
+  protected abstract String substring(int start, int end);
+
+  public void doExecute(List<T> lines) {
+    while (notAtEnd()) {
+      int begin = myIndex;
+      skipToEOL();
+      int endIndex = myIndex;
+      boolean appendNewLine = false;
+
+      if (notAtEnd() && isAtEOL()) {
+        if (charAt(endIndex) == '\n') {
+          endIndex++;
+        }
+        else {
+          appendNewLine = true;
+        }
+        skipEOL();
+      }
+
+      addLine(lines, begin, endIndex, appendNewLine);
+    }
+  }
+
+  private void skipEOL() {
+    int eolStart = myIndex;
+    boolean nFound = false;
+    boolean rFound = false;
+    while (notAtEnd()) {
+      boolean n = charAt(myIndex) == '\n';
+      boolean r = charAt(myIndex) == '\r';
+      if (!n && !r) {
+        break;
+      }
+      if ((nFound && n) || (rFound && r)) {
+        break;
+      }
+      nFound |= n;
+      rFound |= r;
+      myIndex++;
+    }
+    if (myLineSeparatorStart == -1) {
+      myLineSeparatorStart = eolStart;
+      myLineSeparatorEnd = myIndex;
+    }
+  }
+
+  @Nullable
+  public String getLineSeparator() {
+    if (myLineSeparatorStart == -1) return null;
+    return substring(myLineSeparatorStart, myLineSeparatorEnd);
+  }
+
+  private void skipToEOL() {
+    while (notAtEnd() && !isAtEOL()) {
+      myIndex++;
+    }
+  }
+
+  private boolean notAtEnd() {
+    return myIndex < length();
+  }
+
+  private boolean isAtEOL() {
+    return charAt(myIndex) == '\r' || charAt(myIndex) == '\n';
+  }
+}
\ No newline at end of file
index 791d4a0c46e1ee79577491120d655869991b15f1..7ec348f81f939f63951e82a8143c016965748b0f 100644 (file)
  */
 package com.intellij.openapi.diff.ex;
 
+import com.intellij.openapi.diff.impl.string.DiffString;
+import com.intellij.openapi.diff.impl.string.DiffStringBuilder;
 import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
 
 public class DiffFragment {
   public static DiffFragment[] EMPTY_ARRAY = new DiffFragment[0];
 
-  private final String myText1;
-  private final String myText2;
+  @Nullable private CharSequence myText1;
+  @Nullable private CharSequence myText2;
   private boolean myIsModified;
 
-  private StringBuilder myText1Builder;
-  private StringBuilder myText2Builder;
+  @TestOnly
+  public DiffFragment(@Nullable String text1, @Nullable String text2) {
+    this(DiffString.createNullable(text1), DiffString.createNullable(text2));
+  }
 
-  public DiffFragment(String text1, String text2) {
+  public DiffFragment(@Nullable DiffString text1, @Nullable DiffString text2) {
     myText1 = text1;
     myText2 = text2;
     myIsModified = (text1 == null || text2 == null || !text1.equals(text2));
   }
 
-  public static boolean isEmpty(DiffFragment fragment) {
+  public static boolean isEmpty(@NotNull DiffFragment fragment) {
     return StringUtil.length(fragment.getText1()) == 0 &&
            StringUtil.length(fragment.getText2()) == 0;
   }
@@ -50,34 +57,70 @@ public class DiffFragment {
     myIsModified = modified;
   }
 
-  public void appendText1(String str) {
-    assert myText1 != null;
-    if (myText1Builder == null) {
-      myText1Builder = new StringBuilder(myText1);
+  public void appendText1(@Nullable DiffString str) {
+    if (str == null) return;
+    if (myText1 instanceof DiffStringBuilder) {
+      ((DiffStringBuilder)myText1).append(str);
+      return;
+    }
+
+    if (myText1 instanceof DiffString) {
+      DiffString text1 = (DiffString)myText1;
+      if (DiffString.canInplaceConcatenate(text1, str)) {
+        myText1 = DiffString.concatenate(text1, str);
+      }
+      else {
+        DiffStringBuilder builder = new DiffStringBuilder(text1.length() + str.length());
+        builder.append(text1);
+        builder.append(str);
+        myText1 = builder;
+      }
+      return;
     }
-    myText1Builder.append(str);
+
+    throw new IllegalStateException("Bad DiffFragment: " + (myText1 != null ? myText1.getClass() : "null"));
   }
 
-  public void appendText2(String str) {
-    assert myText2 != null;
-    if (myText2Builder == null) {
-      myText2Builder = new StringBuilder(myText2);
+  public void appendText2(@Nullable DiffString str) {
+    if (str == null) return;
+    if (myText2 instanceof DiffStringBuilder) {
+      ((DiffStringBuilder)myText2).append(str);
+      return;
     }
-    myText2Builder.append(str);
+
+    if (myText2 instanceof DiffString) {
+      DiffString text2 = (DiffString)myText2;
+      if (DiffString.canInplaceConcatenate(text2, str)) {
+        myText2 = DiffString.concatenate(text2, str);
+      }
+      else {
+        DiffStringBuilder builder = new DiffStringBuilder(text2.length() + str.length());
+        builder.append(text2);
+        builder.append(str);
+        myText2 = builder;
+      }
+      return;
+    }
+
+    throw new IllegalStateException("Bad DiffFragment: " + (myText2 != null ? myText2.getClass() : "null"));
   }
 
-  /**
-   * null if absent
-   */
-  public String getText1() {
-    return myText1Builder != null ? myText1Builder.toString() : myText1;
+  @Nullable
+  public DiffString getText1() {
+    if (myText1 == null) return null;
+    if (myText1 instanceof DiffString) return (DiffString)myText1;
+    if (myText1 instanceof DiffStringBuilder) return ((DiffStringBuilder)myText1).toDiffString();
+
+    throw new IllegalStateException("Bad DiffFragment: " + myText1.getClass());
   }
-  
-  /**
-   * null if absent
-   */
-  public String getText2() {
-    return myText2Builder != null ? myText2Builder.toString() : myText2;
+
+  @Nullable
+  public DiffString getText2() {
+    if (myText2 == null) return null;
+    if (myText2 instanceof DiffString) return (DiffString)myText2;
+    if (myText2 instanceof DiffStringBuilder) return ((DiffStringBuilder)myText2).toDiffString();
+
+    throw new IllegalStateException("Bad DiffFragment: " + myText2.getClass());
   }
 
   /**
@@ -85,23 +128,28 @@ public class DiffFragment {
    * @return true iff both texts are present and {@link #isModified()}
    */
   public boolean isChange() {
-    return myText1 != null && myText2 != null && isModified();
+    return (myText1 != null) && (myText2 != null) && isModified();
   }
 
   /**
    * @return true iff both texts are present and not {@link #isModified()}
    */
   public boolean isEqual() {
-    return myText1 != null && myText2 != null && !isModified();
+    return (myText1 != null) && (myText2 != null) && !isModified();
+  }
+
+  @TestOnly
+  public static DiffFragment unchanged(@Nullable String text1, @Nullable String text2) {
+    return unchanged(DiffString.createNullable(text1), DiffString.createNullable(text2));
   }
 
-  public static DiffFragment unchanged(String text1, String text2) {
+  public static DiffFragment unchanged(@Nullable DiffString text1, @Nullable DiffString text2) {
     DiffFragment result = new DiffFragment(text1, text2);
     result.setModified(false);
     return result;
   }
 
   public boolean isOneSide() {
-    return myText1 == null || myText2 == null;
+    return (myText1 == null) || (myText2 == null);
   }
 }
index 0767413e3f5b5173c89e3432ddc540c6750250a9..b38c827adf9f1a99f6c64a824f7d4907160f6526 100644 (file)
@@ -16,6 +16,7 @@
 package com.intellij.openapi.diff.impl;
 
 import com.intellij.CommonBundle;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
 import com.intellij.openapi.diff.impl.highlighting.Util;
@@ -24,18 +25,30 @@ import com.intellij.openapi.diff.impl.processing.Formatting;
 import com.intellij.openapi.diff.impl.processing.Word;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.TextRange;
-import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.diff.Diff;
 import com.intellij.util.diff.FilesTooBigForDiffException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
 
 public abstract class ComparisonPolicy {
+  public static final ComparisonPolicy DEFAULT = new DefaultPolicy();
+  public static final ComparisonPolicy TRIM_SPACE = new TrimSpacePolicy();
+  public static final ComparisonPolicy IGNORE_SPACE = new IgnoreSpacePolicy();
+  public static final ComparisonPolicy[] COMPARISON_POLICIES = new ComparisonPolicy[]{DEFAULT, IGNORE_SPACE, TRIM_SPACE};
+
   private final String myName;
 
   protected ComparisonPolicy(final String name) {
     myName = name;
   }
 
-  public DiffFragment[] buildFragments(String[] strings1, String[] strings2) throws FilesTooBigForDiffException {
+  public String getName() {
+    return myName;
+  }
+
+  @NotNull
+  public DiffFragment[] buildFragments(@NotNull DiffString[] strings1, @NotNull DiffString[] strings2) throws FilesTooBigForDiffException {
     DiffFragmentBuilder builder = new DiffFragmentBuilder(strings1, strings2);
     Object[] wrappers1 = getWrappers(strings1);
     Object[] wrappers2 = getWrappers(strings2);
@@ -43,7 +56,9 @@ public abstract class ComparisonPolicy {
     return builder.buildFragments(Util.concatEquals(change, wrappers1, wrappers2));
   }
 
-  public DiffFragment[] buildDiffFragmentsFromLines(String[] lines1, String[] lines2) throws FilesTooBigForDiffException {
+  @NotNull
+  public DiffFragment[] buildDiffFragmentsFromLines(@NotNull DiffString[] lines1, @NotNull DiffString[] lines2)
+    throws FilesTooBigForDiffException {
     DiffFragmentBuilder builder = new DiffFragmentBuilder(lines1, lines2);
     Object[] wrappers1 = getLineWrappers(lines1);
     Object[] wrappers2 = getLineWrappers(lines2);
@@ -51,19 +66,52 @@ public abstract class ComparisonPolicy {
     return builder.buildFragments(change);
   }
 
-  public static final ComparisonPolicy DEFAULT = new ComparisonPolicy(CommonBundle.message("comparison.policy.default.name")) {
+  @NotNull
+  public DiffFragment createFragment(@Nullable DiffString text1, @Nullable DiffString text2) {
+    text1 = toNull(text1);
+    text2 = toNull(text2);
+    if (text1 == null && text2 == null) return new DiffFragment(DiffString.EMPTY, DiffString.EMPTY);
+    DiffFragment result = new DiffFragment(text1, text2);
+    if (text1 != null && text2 != null) {
+      result.setModified(!getWrapper(text1).equals(getWrapper(text2)));
+    }
+    return result;
+  }
+
+  @NotNull
+  public abstract DiffFragment createFragment(@NotNull Word word1, @NotNull Word word2);
+
+  @NotNull
+  protected abstract Object[] getWrappers(@NotNull DiffString[] strings);
+
+  @NotNull
+  protected abstract Object[] getLineWrappers(@NotNull DiffString[] lines);
+
+  @NotNull
+  private Object getWrapper(@NotNull DiffString text) {
+    return getWrappers(new DiffString[]{text})[0];
+  }
+
+  private static class DefaultPolicy extends ComparisonPolicy {
+    public DefaultPolicy() {
+      super(CommonBundle.message("comparison.policy.default.name"));
+    }
+
+    @NotNull
     @Override
-    protected Object[] getWrappers(String[] strings) {
+    protected Object[] getWrappers(@NotNull DiffString[] strings) {
       return strings;
     }
 
+    @NotNull
     @Override
-    protected Object[] getLineWrappers(String[] lines) {
+    protected Object[] getLineWrappers(@NotNull DiffString[] lines) {
       return lines;
     }
 
+    @NotNull
     @Override
-    public DiffFragment createFragment(Word word1, Word word2) {
+    public DiffFragment createFragment(@NotNull Word word1, @NotNull Word word2) {
       return createFragment(word1.getText(), word2.getText());
     }
 
@@ -71,18 +119,24 @@ public abstract class ComparisonPolicy {
     public String toString() {
       return "DEFAULT";
     }
-  };
+  }
+
+  private static class TrimSpacePolicy extends ComparisonPolicy {
+    public TrimSpacePolicy() {
+      super(CommonBundle.message("comparison.policy.trim.space.name"));
+    }
 
-  public static final ComparisonPolicy TRIM_SPACE = new ComparisonPolicy(CommonBundle.message("comparison.policy.trim.space.name")) {
+    @NotNull
     @Override
-    protected Object[] getLineWrappers(String[] lines) {
+    protected Object[] getLineWrappers(@NotNull DiffString[] lines) {
       return trimStrings(lines);
     }
 
+    @NotNull
     @Override
-    public DiffFragment createFragment(Word word1, Word word2) {
-      String text1 = word1.getText();
-      String text2 = word2.getText();
+    public DiffFragment createFragment(@NotNull Word word1, @NotNull Word word2) {
+      DiffString text1 = word1.getText();
+      DiffString text2 = word2.getText();
       if (word1.isWhitespace() && word2.isWhitespace() &&
           word1.atEndOfLine() && word2.atEndOfLine()) {
         return DiffFragment.unchanged(text1, text2);
@@ -90,16 +144,17 @@ public abstract class ComparisonPolicy {
       return createFragment(text1, text2);
     }
 
+    @NotNull
     @Override
-    protected Object[] getWrappers(String[] strings) {
+    protected Object[] getWrappers(@NotNull DiffString[] strings) {
       Object[] result = new Object[strings.length];
       boolean atBeginning = true;
       for (int i = 0; i < strings.length; i++) {
-        String string = strings[i];
-        String wrapper = atBeginning ? StringUtil.trimLeading(string) : string;
-        if (StringUtil.endsWithChar(wrapper, '\n')) {
+        DiffString string = strings[i];
+        DiffString wrapper = atBeginning ? string.trimLeading() : string;
+        if (wrapper.endsWith('\n')) {
           atBeginning = true;
-          wrapper = StringUtil.trimTrailing(wrapper);
+          wrapper = wrapper.trimTrailing();
         }
         else {
           atBeginning = false;
@@ -109,128 +164,66 @@ public abstract class ComparisonPolicy {
       return result;
     }
 
-
-
     @SuppressWarnings({"HardCodedStringLiteral"})
     public String toString() {
       return "TRIM";
     }
-  };
-
-  public static final ComparisonPolicy IGNORE_SPACE = new IgnoreSpacePolicy();
-
-  private static String toNotNull(String text) {
-    return text == null ? "" : text;
   }
 
-  protected abstract Object[] getWrappers(String[] strings);
-
-  protected abstract Object[] getLineWrappers(String[] lines);
-
-  protected Object[] trimStrings(String[] strings) {
-    Object[] result = new Object[strings.length];
-    for (int i = 0; i < strings.length; i++) {
-      String string = strings[i];
-      result[i] = string.trim();
-    }
-    return result;
-  }
-
-  public DiffFragment createFragment(String text1, String text2) {
-    text1 = toNull(text1);
-    text2 = toNull(text2);
-    if (text1 == null && text2 == null) return new DiffFragment("", "");
-    DiffFragment result = new DiffFragment(text1, text2);
-    if (text1 != null && text2 != null) {
-      result.setModified(!getWrapper(text1).equals(getWrapper(text2)));
-    }
-    return result;
-  }
-
-  private String toNull(String text1) {
-    return text1 == null || text1.isEmpty() ? null : text1;
-  }
-
-  private Object getWrapper(String text) {
-    return getWrappers(new String[]{text})[0];
-  }
-
-  public boolean isEqual(DiffFragment fragment) {
-    if (fragment.isOneSide()) return false;
-    Object[] wrappers = getLineWrappers(new String[]{fragment.getText1(), fragment.getText2()});
-    return Comparing.equal(wrappers[0], wrappers[1]);
-  }
-
-  public Word createFormatting(String text, TextRange textRange) {
-    return new Formatting(text, textRange);
-  }
-
-  public abstract DiffFragment createFragment(Word word1, Word word2);
-
-  public String getName() {
-    return myName;
-  }
-
-  public static final ComparisonPolicy[] COMPARISON_POLICIES = new ComparisonPolicy[]{DEFAULT, IGNORE_SPACE, TRIM_SPACE};
-  
-  public static ComparisonPolicy[] getAllInstances() {
-    return COMPARISON_POLICIES;
-  }
-
-  private static class IgnoreSpacePolicy extends ComparisonPolicy implements DiffCorrection.FragmentProcessor<DiffCorrection.FragmentsCollector> {
+  private static class IgnoreSpacePolicy extends ComparisonPolicy
+    implements DiffCorrection.FragmentProcessor<DiffCorrection.FragmentsCollector> {
     public IgnoreSpacePolicy() {
       super(CommonBundle.message("comparison.policy.ignore.spaces.name"));
     }
 
+    @NotNull
     @Override
-    protected Object[] getLineWrappers(String[] lines) {
+    protected Object[] getLineWrappers(@NotNull DiffString[] lines) {
       Object[] result = new Object[lines.length];
       for (int i = 0; i < lines.length; i++) {
-        String line = lines[i];
+        DiffString line = lines[i];
         result[i] = getWrapper(line);
       }
       return result;
     }
 
+    @NotNull
     @Override
-    public DiffFragment[] buildFragments(String[] strings1, String[] strings2) throws FilesTooBigForDiffException {
+    public DiffFragment[] buildFragments(@NotNull DiffString[] strings1, @NotNull DiffString[] strings2)
+      throws FilesTooBigForDiffException {
       DiffFragment[] fragments = super.buildFragments(strings1, strings2);
       DiffCorrection.FragmentsCollector collector = new DiffCorrection.FragmentsCollector();
       collector.processAll(fragments, this);
       return collector.toArray();
     }
 
-    private Object getWrapper(String line) {
-      StringBuilder builder = new StringBuilder(line.length());
-      for (int i = 0; i < line.length(); i++) {
-        char aChar = line.charAt(i);
-        if (StringUtil.isWhiteSpace(aChar)) continue;
-        builder.append(aChar);
-      }
-      return builder.toString();
+    @NotNull
+    private static Object getWrapper(@NotNull DiffString line) {
+      return line.skipSpaces();
     }
 
+    @NotNull
     @Override
-    public DiffFragment createFragment(Word word1, Word word2) {
-      String text1 = word1.getText();
-      String text2 = word2.getText();
-      return word1.isWhitespace() && word2.isWhitespace() ?
-             DiffFragment.unchanged(text1, text2) :
-             createFragment(text1, text2);
+    public DiffFragment createFragment(@NotNull Word word1, @NotNull Word word2) {
+      DiffString text1 = word1.getText();
+      DiffString text2 = word2.getText();
+      return word1.isWhitespace() && word2.isWhitespace() ? DiffFragment.unchanged(text1, text2) : createFragment(text1, text2);
     }
 
+    @NotNull
     @Override
-    public DiffFragment createFragment(String text1, String text2) {
-      String toCompare1 = toNotNull(text1);
-      String toCompare2 = toNotNull(text2);
+    public DiffFragment createFragment(DiffString text1, DiffString text2) {
+      DiffString toCompare1 = toNotNull(text1);
+      DiffString toCompare2 = toNotNull(text2);
       if (getWrapper(toCompare1).equals(getWrapper(toCompare2))) {
         return DiffFragment.unchanged(toCompare1, toCompare2);
       }
       return new DiffFragment(text1, text2);
     }
 
+    @NotNull
     @Override
-    protected Object[] getWrappers(String[] strings) {
+    protected Object[] getWrappers(@NotNull DiffString[] strings) {
       return trimStrings(strings);
     }
 
@@ -240,21 +233,76 @@ public abstract class ComparisonPolicy {
     }
 
     @Override
-    public void process(DiffFragment fragment, DiffCorrection.FragmentsCollector collector) {
+    public void process(@NotNull DiffFragment fragment, @NotNull DiffCorrection.FragmentsCollector collector) {
       if (fragment.isEqual()) {
         collector.add(fragment);
         return;
       }
       if (fragment.isOneSide()) {
         FragmentSide side = FragmentSide.chooseSide(fragment);
-        String text = side.getText(fragment);
-        String trimed = text.trim();
+        DiffString text = side.getText(fragment);
+        DiffString trimed = text.trim();
         if (trimed.isEmpty()) {
-          collector.add(side.createFragment(text, "", false));
+          collector.add(side.createFragment(text, DiffString.EMPTY, false));
           return;
         }
       }
       collector.add(fragment);
     }
   }
+
+  @Nullable
+  private static DiffString toNull(@Nullable DiffString text1) {
+    return text1 == null || text1.isEmpty() ? null : text1;
+  }
+
+  @NotNull
+  private static DiffString toNotNull(@Nullable DiffString text) {
+    return text == null ? DiffString.EMPTY : text;
+  }
+
+  @NotNull
+  protected Object[] trimStrings(@NotNull DiffString[] strings) {
+    Object[] result = new Object[strings.length];
+    for (int i = 0; i < strings.length; i++) {
+      DiffString string = strings[i];
+      result[i] = string.trim();
+    }
+    return result;
+  }
+
+  public boolean isEqual(@NotNull DiffFragment fragment) {
+    if (fragment.isOneSide()) return false;
+    Object[] wrappers = getLineWrappers(new DiffString[]{fragment.getText1(), fragment.getText2()});
+    return Comparing.equal(wrappers[0], wrappers[1]);
+  }
+
+  @NotNull
+  public Word createFormatting(@NotNull DiffString text, @NotNull TextRange textRange) {
+    return new Formatting(text, textRange);
+  }
+
+  public static ComparisonPolicy[] getAllInstances() {
+    return COMPARISON_POLICIES;
+  }
+
+  @NotNull
+  @TestOnly
+  protected Object[] getWrappers(@NotNull String[] lines) {
+    DiffString[] unsafeStrings = new DiffString[lines.length];
+    for (int i = 0; i < lines.length; i++) {
+      unsafeStrings[i] = DiffString.createNullable(lines[i]);
+    }
+    return getWrappers(unsafeStrings);
+  }
+
+  @NotNull
+  @TestOnly
+  protected Object[] getLineWrappers(@NotNull String[] lines) {
+    DiffString[] unsafeStrings = new DiffString[lines.length];
+    for (int i = 0; i < lines.length; i++) {
+      unsafeStrings[i] = DiffString.createNullable(lines[i]);
+    }
+    return getLineWrappers(unsafeStrings);
+  }
 }
index 3b6a00b16fb97cb629e8055d547daca4567ab89a..64630e981753b85a75f7b08ba00365caf90c43d9 100644 (file)
 package com.intellij.openapi.diff.impl;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.util.diff.Diff;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.LinkedList;
 import java.util.List;
@@ -56,25 +59,26 @@ public class DiffFragmentBuilder {
 
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.DiffFragmentBuilder");
 
-  private final String[] mySource1;
-  private final String[] mySource2;
+  @NotNull private final DiffString[] mySource1;
+  @NotNull private final DiffString[] mySource2;
   private int myLastLine1 = 1;
   private int myLastLine2 = 1;
-  private final List<DiffFragment> myData = new LinkedList<DiffFragment>();
+  @NotNull private final List<DiffFragment> myData = new LinkedList<DiffFragment>();
 
-  public DiffFragmentBuilder(String[] source1, String[] source2) {
+  public DiffFragmentBuilder(@NotNull DiffString[] source1, @NotNull DiffString[] source2) {
     mySource1 = source1;
     mySource2 = source2;
     init();
   }
 
+  @NotNull
   private List<DiffFragment> getFragments() {
     return myData;
   }
 
   private void finish() {
-    String text1 = null;
-    String text2 = null;
+    DiffString text1 = null;
+    DiffString text2 = null;
     if (myLastLine1 &l