From 618a745fd00110222e289550a21c236d40598f98 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 8 Dec 2015 13:29:08 +0100 Subject: [PATCH 01/25] cleanup (as part of Meteor debug integration test) --- .../com/intellij/codeInsight/lookup/LookupElementBuilder.java | 3 ++- .../src/org/jetbrains/debugger/DebugProcessImpl.kt | 4 ++-- platform/testFramework/test-framework-java8/FixtureRule.kt | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java index e7fb55c2ff52..a2417f671801 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java +++ b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -66,6 +66,7 @@ public final class LookupElementBuilder extends LookupElement { this(lookupString, object, null, null, null, Collections.singleton(lookupString), true); } + @NotNull public static LookupElementBuilder create(@NotNull String lookupString) { return new LookupElementBuilder(lookupString, lookupString); } diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/DebugProcessImpl.kt b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/DebugProcessImpl.kt index f522e5a5b0f6..f960bfb483a4 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/DebugProcessImpl.kt +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/DebugProcessImpl.kt @@ -39,8 +39,8 @@ import java.util.concurrent.atomic.AtomicBoolean abstract class DebugProcessImpl>(session: XDebugSession, val connection: C, private val editorsProvider: XDebuggerEditorsProvider, - private val smartStepIntoHandler: XSmartStepIntoHandler<*>?, - protected val executionResult: ExecutionResult?) : XDebugProcess(session) { + private val smartStepIntoHandler: XSmartStepIntoHandler<*>? = null, + protected val executionResult: ExecutionResult? = null) : XDebugProcess(session) { protected val repeatStepInto: AtomicBoolean = AtomicBoolean() @Volatile protected var lastStep: StepAction? = null @Volatile protected var lastCallFrame: CallFrame? = null diff --git a/platform/testFramework/test-framework-java8/FixtureRule.kt b/platform/testFramework/test-framework-java8/FixtureRule.kt index e4bca84c931b..0d9d5b3806f3 100644 --- a/platform/testFramework/test-framework-java8/FixtureRule.kt +++ b/platform/testFramework/test-framework-java8/FixtureRule.kt @@ -91,12 +91,12 @@ class ProjectRule() : ExternalResource() { } } - override final fun before() { + override public final fun before() { IdeaTestApplication.getInstance() TestRunnerUtil.replaceIdeEventQueueSafely() } - override fun after() { + override public fun after() { if (projectOpened.compareAndSet(true, false)) { sharedProject?.let { runInEdtAndWait { (ProjectManager.getInstance() as ProjectManagerImpl).closeProject(it, false, false, false) } } } From 54161f9228567ce9af7bec3e4866b37ab1e5cbd9 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 8 Dec 2015 15:51:29 +0300 Subject: [PATCH 02/25] fix tests (redone commit 2b8541b) --- .../fixtures/LightCodeInsightFixtureTestCase.java | 5 +++++ .../com/intellij/testFramework/LightPlatformTestCase.java | 5 +++++ .../src/com/intellij/testFramework/UsefulTestCase.java | 4 ---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/java/testFramework/src/com/intellij/testFramework/fixtures/LightCodeInsightFixtureTestCase.java b/java/testFramework/src/com/intellij/testFramework/fixtures/LightCodeInsightFixtureTestCase.java index 768baa78943a..78fb3318f714 100644 --- a/java/testFramework/src/com/intellij/testFramework/fixtures/LightCodeInsightFixtureTestCase.java +++ b/java/testFramework/src/com/intellij/testFramework/fixtures/LightCodeInsightFixtureTestCase.java @@ -17,6 +17,7 @@ package com.intellij.testFramework.fixtures; import com.intellij.lang.Language; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.impl.ComplementaryFontsRegistry; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; @@ -102,6 +103,10 @@ public abstract class LightCodeInsightFixtureTestCase extends UsefulTestCase { myFixture.setTestDataPath(getTestDataPath()); myModule = myFixture.getModule(); + + // various tests can use different mocking techniques for font-related code + // so we must reset our font cache, to avoid potential impact of tests on other tests + ComplementaryFontsRegistry.resetCaches(); } /** diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java index 98ff484985d5..3617e5c3c93b 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java @@ -46,6 +46,7 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; +import com.intellij.openapi.editor.impl.ComplementaryFontsRegistry; import com.intellij.openapi.editor.impl.EditorFactoryImpl; import com.intellij.openapi.editor.impl.EditorImpl; import com.intellij.openapi.extensions.Extensions; @@ -303,6 +304,10 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da VirtualFilePointerManagerImpl filePointerManager = (VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance(); filePointerManager.storePointers(); + // various tests can use different mocking techniques for font-related code + // so we must reset our font cache, to avoid potential impact of tests on other tests + ComplementaryFontsRegistry.resetCaches(); + System.out.println("soft wraps enabled: " + EditorSettingsExternalizable.getInstance().isUseSoftWraps()); // temporary code to find out cause of test blinking } }); diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java index 8c7c14871e61..6dcf1fd6c7a6 100644 --- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java @@ -149,10 +149,6 @@ public abstract class UsefulTestCase extends TestCase { ApplicationInfoImpl.setInPerformanceTest(isPerformanceTest); // turn off Disposer debugging for performance tests oldDisposerDebug = Disposer.setDebugMode(Disposer.isDebugMode() && !isPerformanceTest); - - // various tests can use different mocking techniques for font-related code - // so we must reset our font cache, to avoid potential impact of tests on other tests - ComplementaryFontsRegistry.resetCaches(); } @Override From d54a007da703b4af9815b01f568e58a6b8340200 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 8 Dec 2015 16:23:09 +0300 Subject: [PATCH 03/25] remove temporary test code --- .../src/com/intellij/testFramework/LightPlatformTestCase.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java index 3617e5c3c93b..4f3279dbe97e 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java @@ -45,7 +45,6 @@ import com.intellij.openapi.command.undo.UndoManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; -import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.editor.impl.ComplementaryFontsRegistry; import com.intellij.openapi.editor.impl.EditorFactoryImpl; import com.intellij.openapi.editor.impl.EditorImpl; @@ -307,8 +306,6 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da // various tests can use different mocking techniques for font-related code // so we must reset our font cache, to avoid potential impact of tests on other tests ComplementaryFontsRegistry.resetCaches(); - - System.out.println("soft wraps enabled: " + EditorSettingsExternalizable.getInstance().isUseSoftWraps()); // temporary code to find out cause of test blinking } }); } From 16479fa68c2187f957baed3d13372d8bd9ab418a Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Tue, 8 Dec 2015 16:41:21 +0300 Subject: [PATCH 04/25] IDEA-132891 Form snapshot throwing NoClassDefFoundError --- .../InsertComponentProcessor.java | 10 +++++-- .../SnapShooterConfigurationExtension.java | 26 ++++++++++--------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/InsertComponentProcessor.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/InsertComponentProcessor.java index 165cf5384c69..2c91b10049b4 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/InsertComponentProcessor.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/InsertComponentProcessor.java @@ -27,6 +27,7 @@ import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiClass; @@ -525,8 +526,13 @@ public final class InsertComponentProcessor extends EventProcessor { } @Nullable - public static RadComponentFactory getRadComponentFactory(Project project, final String className) { - ClassLoader loader = LoaderFactory.getInstance(project).getProjectClassLoader(); + public static RadComponentFactory getRadComponentFactory(final Project project, final String className) { + ClassLoader loader = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public ClassLoader compute() { + return LoaderFactory.getInstance(project).getProjectClassLoader(); + } + }); return getRadComponentFactory(className, loader); } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/SnapShooterConfigurationExtension.java b/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/SnapShooterConfigurationExtension.java index fa7719348093..cf0d700298cd 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/SnapShooterConfigurationExtension.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/SnapShooterConfigurationExtension.java @@ -16,6 +16,7 @@ package com.intellij.uiDesigner.snapShooter; +import com.intellij.designer.DesignerEditorPanelFacade; import com.intellij.execution.Location; import com.intellij.execution.RunConfigurationExtension; import com.intellij.execution.application.ApplicationConfiguration; @@ -74,18 +75,19 @@ public class SnapShooterConfigurationExtension extends RunConfigurationExtension // add +1 because idea_rt.jar will be added as the last entry to the classpath params.getProgramParametersList().prepend(Integer.toString(params.getClassPath().getPathList().size() + 1)); Set paths = new TreeSet(); - paths.add(PathUtil.getJarPathForClass(SnapShooter.class)); // ui-designer-impl - paths.add(PathUtil.getJarPathForClass(BaseComponent.class)); // appcore-api - paths.add(PathUtil.getJarPathForClass(ProjectComponent.class)); // openapi - paths.add(PathUtil.getJarPathForClass(LwComponent.class)); // UIDesignerCore - paths.add(PathUtil.getJarPathForClass(GridConstraints.class)); // forms_rt - paths.add(PathUtil.getJarPathForClass(PaletteGroup.class)); // openapi - paths.add(PathUtil.getJarPathForClass(LafManagerListener.class)); // ui-impl - paths.add(PathUtil.getJarPathForClass(DataProvider.class)); // action-system-openapi - paths.add(PathUtil.getJarPathForClass(XmlStringUtil.class)); // idea - paths.add(PathUtil.getJarPathForClass(Navigatable.class)); // pom - paths.add(PathUtil.getJarPathForClass(AreaInstance.class)); // extensions - paths.add(PathUtil.getJarPathForClass(FormLayout.class)); // jgoodies + paths.add(PathUtil.getJarPathForClass(SnapShooter.class)); // ui-designer-impl + paths.add(PathUtil.getJarPathForClass(BaseComponent.class)); // appcore-api + paths.add(PathUtil.getJarPathForClass(ProjectComponent.class)); // openapi + paths.add(PathUtil.getJarPathForClass(DesignerEditorPanelFacade.class)); // platform-impl + paths.add(PathUtil.getJarPathForClass(LwComponent.class)); // UIDesignerCore + paths.add(PathUtil.getJarPathForClass(GridConstraints.class)); // forms_rt + paths.add(PathUtil.getJarPathForClass(PaletteGroup.class)); // openapi + paths.add(PathUtil.getJarPathForClass(LafManagerListener.class)); // ui-impl + paths.add(PathUtil.getJarPathForClass(DataProvider.class)); // action-system-openapi + paths.add(PathUtil.getJarPathForClass(XmlStringUtil.class)); // idea + paths.add(PathUtil.getJarPathForClass(Navigatable.class)); // pom + paths.add(PathUtil.getJarPathForClass(AreaInstance.class)); // extensions + paths.add(PathUtil.getJarPathForClass(FormLayout.class)); // jgoodies paths.addAll(PathManager.getUtilClassPath()); for(String path: paths) { params.getClassPath().addFirst(path); From 47e9533a1b22780e41487f6d5a6566db340b3378 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 8 Dec 2015 15:29:20 +0300 Subject: [PATCH 05/25] replaced with StringUtil.trimStart/trimEnd --- .idea/inspectionProfiles/idea_default.xml | 22 ++++++++++ .../DefaultRegExpPropertiesProvider.java | 40 +++++++++++++------ .../compiler/ant/ModuleChunkClasspath.java | 7 ++-- .../internal/UsedIconsListingAction.java | 5 +-- .../unscramble/UnscrambleListener.java | 7 ++-- .../psi/formatter/java/IndentTest.java | 12 ++---- .../psi/formatter/java/TabIndentingTest.java | 14 +++---- .../psi/formatter/java/WrapperTest.java | 5 +-- .../codeInsight/CodeInsightTestCase.java | 4 +- .../com/siyeh/ig/LightInspectionTestCase.java | 5 +-- .../packageSet/NamedPackageSetReference.java | 5 ++- .../org/jetbrains/ide/AboutHttpService.java | 5 +-- .../com/intellij/openapi/vfs/VfsUtilCore.java | 4 +- .../com/intellij/psi/search/IndexPattern.java | 7 ++-- .../ide/actions/CreateElementActionBase.java | 7 ++-- .../execution/impl/BeforeRunStepsPanel.java | 7 ++-- .../ide/actions/SearchEverywhereAction.java | 4 +- .../ide/fileTemplates/impl/UrlUtil.java | 7 ++-- .../process/ColoredOutputTypeRegistry.java | 24 ++++++++--- .../openapi/roots/ui/LightFilePointer.java | 7 ++-- .../options/pathMacros/PathMacroTable.java | 5 ++- .../actions/CreateLauncherScriptAction.java | 2 +- .../impl/JBProtocolOpenProjectCommand.java | 5 +-- .../vfs/impl/local/LocalFileSystemBase.java | 4 +- .../platform/LocationNameFieldsBinding.java | 7 ++-- .../openapi/project/ProjectUtilCore.java | 6 +-- .../projectRoots/impl/SimpleProjectRoot.java | 5 +-- .../sm/runner/ui/TestsPresentationUtil.java | 8 ++-- .../openapi/util/io/UniqueNameBuilder.java | 22 ++++++++-- .../util/src/com/intellij/ui/ColorUtil.java | 7 ++-- .../intellij/util/lang/ClasspathCache.java | 6 +-- .../com/intellij/util/lang/FileLoader.java | 3 +- .../intellij/util/lang/UrlClassLoader.java | 3 +- .../diff/impl/patch/UnifiedDiffWriter.java | 18 +++++---- .../CodeAnalysisBeforeCheckinHandler.java | 17 ++++---- .../vcs/checkin/TodoCheckinHandler.java | 5 +-- .../ConvertToScientificNotationPredicate.java | 7 ++-- .../config/execution/AntBuildMessageView.java | 5 +-- .../intellij/coverage/PackageAnnotator.java | 7 +++- .../src/com/intellij/cvsSupport2/CvsUtil.java | 11 ++--- .../changeBrowser/LogInformationWrapper.java | 11 ++--- .../CvsApplicationLevelConfiguration.java | 6 +-- .../intellij/cvsSupport2/ui/FormUtils.java | 7 ++-- .../command/status/StatusMessageParser.java | 7 ++-- plugins/devkit/src/dom/generator/Util.java | 5 ++- .../internal/UseJBColorInspection.java | 13 +++--- .../quickfix/AbstractRegisterFix.java | 5 +-- .../TestDataGuessByExistingFilesUtil.java | 6 +-- .../jetbrains/idea/eclipse/util/PathUtil.java | 23 +++++------ .../src/git4idea/push/GitPushSpecParser.java | 5 +-- .../tests/git4idea/test/RefParser.java | 20 ++++++++-- .../ConvertGStringToStringIntention.java | 11 ++--- .../groovy/mvc/MvcRunTargetDialog.java | 4 +- .../PrefixBasedPropertyReference.java | 6 +-- .../maven/indices/MavenClassSearcher.java | 4 +- .../idea/maven/project/MavenProject.java | 8 ++-- .../jetbrains/idea/maven/utils/MavenUtil.java | 2 +- .../importing/DependenciesImportingTest.java | 3 +- .../editor/PropertiesCopyHandler.java | 10 ++--- .../jira/jql/psi/impl/JqlElementImpl.java | 20 ++++++++-- .../intellij/tasks/bugzilla/BugzillaTask.java | 20 ++++++++-- .../actions/ProjectSpecificSettingsStep.java | 7 ++-- .../python/packaging/PyRequirement.java | 6 +-- .../jetbrains/python/PythonStringUtil.java | 8 ++-- .../pydev/AbstractPyCodeCompletion.java | 37 ++++++++--------- .../python/PythonHelpersLocator.java | 7 ++-- .../python/buildout/BuildoutFacet.java | 6 +-- .../docstrings/DocStringTypeReference.java | 7 ++-- .../python/psi/impl/PyBaseElementImpl.java | 7 ++-- .../psi/impl/references/PyReferenceImpl.java | 7 ++-- .../python/refactoring/NameSuggesterUtil.java | 6 +-- .../python/remote/PyRemoteSourceItem.java | 5 +-- .../AbstractPythonTestRunConfiguration.java | 6 +-- .../util/xml/ui/BasicDomElementComponent.java | 8 ++-- .../completion/XmlCompletionData.java | 7 ++-- .../XmlDocumentationProvider.java | 6 +-- 76 files changed, 353 insertions(+), 324 deletions(-) diff --git a/.idea/inspectionProfiles/idea_default.xml b/.idea/inspectionProfiles/idea_default.xml index c883baebc48c..aabceb3d9fed 100644 --- a/.idea/inspectionProfiles/idea_default.xml +++ b/.idea/inspectionProfiles/idea_default.xml @@ -648,6 +648,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/RegExpSupport/src/org/intellij/lang/regexp/DefaultRegExpPropertiesProvider.java b/RegExpSupport/src/org/intellij/lang/regexp/DefaultRegExpPropertiesProvider.java index 520d9542668e..1b94fc0c97c4 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/DefaultRegExpPropertiesProvider.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/DefaultRegExpPropertiesProvider.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.intellij.lang.regexp; import com.intellij.openapi.util.text.StringUtil; @@ -134,22 +149,21 @@ public final class DefaultRegExpPropertiesProvider { } public boolean isValidCategory(@NotNull String category) { - if (category.startsWith("In")) { - try { - return Character.UnicodeBlock.forName(category.substring(2)) != null; - } catch (IllegalArgumentException e) { - return false; - } + if (category.startsWith("In")) { + try { + return Character.UnicodeBlock.forName(category.substring(2)) != null; } - if (category.startsWith("Is")) { - category = category.substring(2); + catch (IllegalArgumentException e) { + return false; } - for (String[] name : myPropertyNames) { - if (name[0].equals(category)) { - return true; - } + } + category = StringUtil.trimStart(category, "Is"); + for (String[] name : myPropertyNames) { + if (name[0].equals(category)) { + return true; } - return false; + } + return false; } @Nullable diff --git a/java/compiler/impl/src/com/intellij/compiler/ant/ModuleChunkClasspath.java b/java/compiler/impl/src/com/intellij/compiler/ant/ModuleChunkClasspath.java index 0883913855ae..926fc39375fb 100644 --- a/java/compiler/impl/src/com/intellij/compiler/ant/ModuleChunkClasspath.java +++ b/java/compiler/impl/src/com/intellij/compiler/ant/ModuleChunkClasspath.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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.compiler.ant.taskdefs.PathRef; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.roots.*; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.ArrayUtil; @@ -163,9 +164,7 @@ public class ModuleChunkClasspath extends Path { // Module source entry? for (String url : getCompilationClasses(module, ((GenerationOptionsImpl)genOptions), generateRuntimeClasspath, generateTestClasspath, dependencyLevel == 0)) { - if (url.endsWith(JarFileSystem.JAR_SEPARATOR)) { - url = url.substring(0, url.length() - JarFileSystem.JAR_SEPARATOR.length()); - } + url = StringUtil.trimEnd(url, JarFileSystem.JAR_SEPARATOR); final String propertyRef = genOptions.getPropertyRefForUrl(url); if (propertyRef != null) { pathItems.add(new PathElementItem(propertyRef)); diff --git a/java/java-impl/src/com/intellij/internal/UsedIconsListingAction.java b/java/java-impl/src/com/intellij/internal/UsedIconsListingAction.java index 293819bf63be..65eb2d2c54bc 100644 --- a/java/java-impl/src/com/intellij/internal/UsedIconsListingAction.java +++ b/java/java-impl/src/com/intellij/internal/UsedIconsListingAction.java @@ -29,6 +29,7 @@ import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; @@ -89,9 +90,7 @@ public class UsedIconsListingAction extends AnAction { String str = (String)value; if (str.startsWith("\"")) { str = str.substring(0); - if (str.endsWith("\"")) { - str = str.substring(0, str.length() - 1); - } + str = StringUtil.trimEnd(str, "\""); } if (!str.startsWith("/")) { diff --git a/java/java-impl/src/com/intellij/unscramble/UnscrambleListener.java b/java/java-impl/src/com/intellij/unscramble/UnscrambleListener.java index 156fe4c2eda3..f0e279528494 100644 --- a/java/java-impl/src/com/intellij/unscramble/UnscrambleListener.java +++ b/java/java-impl/src/com/intellij/unscramble/UnscrambleListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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.application.ApplicationActivationListener; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFrame; import com.intellij.util.Alarm; @@ -77,9 +78,7 @@ public class UnscrambleListener extends ApplicationActivationListener.Adapter { for (String line : stacktrace.split("\n")) { line = line.trim(); if (line.length() == 0) continue; - if (line.endsWith("\r")) { - line = line.substring(0, line.length() - 1); - } + line = StringUtil.trimEnd(line, "\r"); if (STACKTRACE_LINE.matcher(line).matches()) { linesCount++; } diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/IndentTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/IndentTest.java index beed9ac5521a..f5266d02c9bf 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/IndentTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/IndentTest.java @@ -149,17 +149,13 @@ public class IndentTest extends LightIdeaTestCase { }); } }, null, null); - + String textAfter = loadFile(fileNameAfter); String fileText = file.getText(); - if (textAfter.startsWith("\n")) { - textAfter = textAfter.substring(1); - } - if (fileText.startsWith("\n")) { - fileText = fileText.substring(1); - } - + textAfter = StringUtil.trimStart(textAfter, "\n"); + fileText = StringUtil.trimStart(fileText, "\n"); + assertEquals(textAfter, fileText); } diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/TabIndentingTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/TabIndentingTest.java index 7644c9dcbc2a..03ea132fa4ee 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/TabIndentingTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/TabIndentingTest.java @@ -128,7 +128,7 @@ public class TabIndentingTest extends LightIdeaTestCase { doTest("SCR6197.java", "SCR6197_after.java"); } - private void doTest(String fileNameBefore, String fileNameAfter) throws Exception{ + private void doTest(String fileNameBefore, String fileNameAfter) throws Exception { String text = loadFile(fileNameBefore); final PsiFile file = createFile(fileNameBefore, text); CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { @@ -147,18 +147,14 @@ public class TabIndentingTest extends LightIdeaTestCase { }); } }, null, null); - + String textAfter = loadFile(fileNameAfter); String fileText = file.getText(); - if (textAfter.startsWith("\n")) { - textAfter = textAfter.substring(1); - } - if (fileText.startsWith("\n")) { - fileText = fileText.substring(1); - } - + textAfter = StringUtil.trimStart(textAfter, "\n"); + fileText = StringUtil.trimStart(fileText, "\n"); + if (!textAfter.equals(fileText)) { System.err.println("Expected:"); System.err.println(textAfter); diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/WrapperTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/WrapperTest.java index 5a0508f89447..fa747d2720c4 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/WrapperTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/WrapperTest.java @@ -17,6 +17,7 @@ package com.intellij.psi.formatter.java; import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; public class WrapperTest extends JavaFormatterTestCase { @@ -28,9 +29,7 @@ public class WrapperTest extends JavaFormatterTestCase { @Override protected String prepareText(final String text) { String result = text; - if (result.startsWith("\n")) { - result = result.substring(1); - } + result = StringUtil.trimStart(result, "\n"); return result; } diff --git a/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java b/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java index f429d0ede370..0afd2d66a48d 100644 --- a/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java @@ -308,9 +308,7 @@ public abstract class CodeInsightTestCase extends PsiTestCase { List streamsToClose = new ArrayList(); for (String relativePath : relativePaths) { - if (relativePath.startsWith("/")) { - relativePath = relativePath.substring(1); - } + relativePath = StringUtil.trimStart(relativePath, "/"); final VirtualFile fromFile = fromDir.findFileByRelativePath(relativePath); assertNotNull(fromDir.getPath() + "/" + relativePath, fromFile); VirtualFile toFile = toDir.findFileByRelativePath(relativePath); diff --git a/java/testFramework/src/com/siyeh/ig/LightInspectionTestCase.java b/java/testFramework/src/com/siyeh/ig/LightInspectionTestCase.java index fa85710f0c14..3a1d6f8cddc8 100644 --- a/java/testFramework/src/com/siyeh/ig/LightInspectionTestCase.java +++ b/java/testFramework/src/com/siyeh/ig/LightInspectionTestCase.java @@ -16,6 +16,7 @@ package com.siyeh.ig; import com.intellij.codeInspection.InspectionProfileEntry; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import com.intellij.util.ArrayUtil; import org.intellij.lang.annotations.Language; @@ -107,9 +108,7 @@ public abstract class LightInspectionTestCase extends LightCodeInsightFixtureTes basePath.append(word).append('/'); } String lastWord = words[lastWordIndex]; - if (lastWord.endsWith("Inspection")) { - lastWord = lastWord.substring(0, lastWord.length() - 10); - } + lastWord = StringUtil.trimEnd(lastWord, "Inspection"); final int length = lastWord.length(); boolean upperCase = false; for (int i = 0; i < length; i++) { diff --git a/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/NamedPackageSetReference.java b/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/NamedPackageSetReference.java index d851e2da635d..fb42e0f95e80 100644 --- a/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/NamedPackageSetReference.java +++ b/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/NamedPackageSetReference.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -15,6 +15,7 @@ */ package com.intellij.psi.search.scope.packageSet; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; @@ -22,7 +23,7 @@ public class NamedPackageSetReference extends PackageSetBase { private final String myName; public NamedPackageSetReference(String name) { - myName = name.startsWith("$") ? name.substring(1) : name; + myName = StringUtil.trimStart(name, "$"); } @Override diff --git a/platform/built-in-server/src/org/jetbrains/ide/AboutHttpService.java b/platform/built-in-server/src/org/jetbrains/ide/AboutHttpService.java index 11c05002b9fd..f45c6f309ede 100644 --- a/platform/built-in-server/src/org/jetbrains/ide/AboutHttpService.java +++ b/platform/built-in-server/src/org/jetbrains/ide/AboutHttpService.java @@ -24,6 +24,7 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeRegistry; import com.intellij.openapi.util.BuildNumber; import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.PlatformUtils; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; @@ -83,9 +84,7 @@ class AboutHttpService extends RestService { if (!PlatformUtils.isIdeaUltimate()) { String productName = ApplicationNamesInfo.getInstance().getProductName(); appName = appName.replace(productName + " (" + productName + ")", productName); - if (appName.startsWith("JetBrains ")) { - appName = appName.substring("JetBrains ".length()); - } + appName = StringUtil.trimStart(appName, "JetBrains "); } writer.name("name").value(appName); diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java index 25895bce1077..ef6a0c962725 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java @@ -550,9 +550,7 @@ public class VfsUtilCore { uri = uri.substring("file:/".length()); if (!SystemInfo.isWindows) uri = "/" + uri; } - else if (uri.startsWith("file:")) { - uri = uri.substring("file:".length()); - } + else uri = StringUtil.trimStart(uri, "file:"); VirtualFile file = null; diff --git a/platform/indexing-api/src/com/intellij/psi/search/IndexPattern.java b/platform/indexing-api/src/com/intellij/psi/search/IndexPattern.java index 0066c260f1b3..c88d45c1160b 100644 --- a/platform/indexing-api/src/com/intellij/psi/search/IndexPattern.java +++ b/platform/indexing-api/src/com/intellij/psi/search/IndexPattern.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -15,6 +15,7 @@ */ package com.intellij.psi.search; +import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -81,9 +82,7 @@ public class IndexPattern { } myPattern = Pattern.compile(myPatternString, flags); String optimizedPattern = myPatternString; - if (optimizedPattern.startsWith(".*")) { - optimizedPattern = optimizedPattern.substring(".*".length()); - } + optimizedPattern = StringUtil.trimStart(optimizedPattern, ".*"); myOptimizedIndexingPattern = Pattern.compile(optimizedPattern, flags); } catch(PatternSyntaxException e){ diff --git a/platform/lang-api/src/com/intellij/ide/actions/CreateElementActionBase.java b/platform/lang-api/src/com/intellij/ide/actions/CreateElementActionBase.java index cfee9818c139..b2a54ff7ff63 100644 --- a/platform/lang-api/src/com/intellij/ide/actions/CreateElementActionBase.java +++ b/platform/lang-api/src/com/intellij/ide/actions/CreateElementActionBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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.actionSystem.*; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.InputValidator; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NonNls; @@ -115,9 +116,7 @@ public abstract class CreateElementActionBase extends AnAction { public static String filterMessage(String message) { if (message == null) return null; @NonNls final String ioExceptionPrefix = "java.io.IOException:"; - if (message.startsWith(ioExceptionPrefix)) { - message = message.substring(ioExceptionPrefix.length()); - } + message = StringUtil.trimStart(message, ioExceptionPrefix); return message; } diff --git a/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunStepsPanel.java b/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunStepsPanel.java index 60d3819df9e2..8e1ebeb998ee 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunStepsPanel.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunStepsPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -32,6 +32,7 @@ import com.intellij.openapi.util.Conditions; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.*; import com.intellij.ui.components.JBList; import com.intellij.util.containers.hash.HashSet; @@ -211,9 +212,7 @@ class BeforeRunStepsPanel extends JPanel { Map.Entry entry = iterator.next(); BeforeRunTaskProvider provider = entry.getKey(); String name = provider.getName(); - if (name.startsWith("Run ")) { - name = name.substring(4); - } + name = StringUtil.trimStart(name, "Run "); if (sb.length() > 0) { sb.append(", "); } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java index 141db44b637d..9f7e41f69394 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java @@ -1330,9 +1330,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA } hit = hit.replace(" ", " "); //avoid extra spaces from mnemonics and xml conversion String text = hit.trim(); - if (text.endsWith(":")) { - text = text.substring(0, text.length() - 1); - } + text = StringUtil.trimEnd(text, ":"); return text; } diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/UrlUtil.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/UrlUtil.java index 7eb88034c6e3..db26d1a35bcd 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/UrlUtil.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/UrlUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -17,6 +17,7 @@ package com.intellij.ide.fileTemplates.impl; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.io.URLUtil; import java.io.BufferedInputStream; @@ -87,9 +88,7 @@ public class UrlUtil { private static List getChildPathsFromJar(URL root) throws IOException { final List paths = new ArrayList(); String file = root.getFile(); - if (file.startsWith(FILE_PROTOCOL_PREFIX)) { - file = file.substring(FILE_PROTOCOL_PREFIX.length()); - } + file = StringUtil.trimStart(file, FILE_PROTOCOL_PREFIX); final int jarSeparatorIndex = file.indexOf(JAR_SEPARATOR); assert jarSeparatorIndex > 0; diff --git a/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java b/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java index 896068aac412..6e84402ae9e2 100644 --- a/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java +++ b/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2015 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.execution.process; import com.intellij.execution.ui.ConsoleViewContentType; @@ -7,6 +22,7 @@ import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -76,12 +92,8 @@ public class ColoredOutputTypeRegistry { if (attribute.startsWith("\u001B[")) { attribute = attribute.substring(2); } - else if (attribute.startsWith("[")) { - attribute = attribute.substring(1); - } - if (attribute.endsWith("m")) { - attribute = attribute.substring(0, attribute.length() - 1); - } + else attribute = StringUtil.trimStart(attribute, "["); + attribute = StringUtil.trimEnd(attribute, "m"); if (attribute.equals("0")) { return ProcessOutputTypes.STDOUT; } diff --git a/platform/platform-api/src/com/intellij/openapi/roots/ui/LightFilePointer.java b/platform/platform-api/src/com/intellij/openapi/roots/ui/LightFilePointer.java index c124ad10856c..ab1b543a829b 100644 --- a/platform/platform-api/src/com/intellij/openapi/roots/ui/LightFilePointer.java +++ b/platform/platform-api/src/com/intellij/openapi/roots/ui/LightFilePointer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -15,6 +15,7 @@ */ package com.intellij.openapi.roots.ui; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; @@ -70,9 +71,7 @@ public class LightFilePointer implements VirtualFilePointer { public static String toPresentableUrl(String url) { String path = VirtualFileManager.extractPath(url); - if (path.endsWith(JarFileSystem.JAR_SEPARATOR)) { - path = path.substring(0, path.length() - JarFileSystem.JAR_SEPARATOR.length()); - } + path = StringUtil.trimEnd(path, JarFileSystem.JAR_SEPARATOR); return path.replace('/', File.separatorChar); } diff --git a/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroTable.java b/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroTable.java index 9950186c194a..0669e0b717cf 100644 --- a/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroTable.java +++ b/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroTable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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.application.PathMacros; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Couple; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.JBColor; import com.intellij.util.ui.Table; @@ -128,7 +129,7 @@ public class PathMacroTable extends Table { final String value = pair.getSecond(); if (value != null && value.trim().length() > 0) { String path = value.replace(File.separatorChar, '/'); - if (path.endsWith("/")) path = path.substring(0, path.length() - 1); + path = StringUtil.trimEnd(path, "/"); myPathMacros.setMacro(pair.getFirst(), path); } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java index 38daf69a2601..b624510b6cb2 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java @@ -149,7 +149,7 @@ public class CreateLauncherScriptAction extends DumbAwareAction { String runPath = PathManager.getHomePath(); String productName = ApplicationNamesInfo.getInstance().getProductName().toLowerCase(Locale.US); if (!SystemInfo.isMac) runPath += "/bin/" + productName + ".sh"; - else if (runPath.endsWith(CONTENTS)) runPath = runPath.substring(0, runPath.length() - CONTENTS.length()); + else runPath = StringUtil.trimEnd(runPath, CONTENTS); ClassLoader loader = CreateLauncherScriptAction.class.getClassLoader(); assert loader != null; diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/JBProtocolOpenProjectCommand.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/JBProtocolOpenProjectCommand.java index 0c846dd9963b..b41460cb2144 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/JBProtocolOpenProjectCommand.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/JBProtocolOpenProjectCommand.java @@ -17,6 +17,7 @@ package com.intellij.openapi.project.impl; import com.intellij.ide.impl.ProjectUtil; import com.intellij.openapi.application.JBProtocolCommand; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import org.jetbrains.annotations.NotNull; @@ -36,9 +37,7 @@ public class JBProtocolOpenProjectCommand extends JBProtocolCommand { @Override public void perform(String target, Map parameters) { String path = URLDecoder.decode(target); - if (path.startsWith(LocalFileSystem.PROTOCOL_PREFIX)) { - path = path.substring(LocalFileSystem.PROTOCOL_PREFIX.length()); - } + path = StringUtil.trimStart(path, LocalFileSystem.PROTOCOL_PREFIX); ProjectUtil.openProject(path, null, true); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java index 962c15f317eb..65a45613ec47 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java @@ -158,9 +158,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { final String[] names = new String[roots.length]; for (int i = 0; i < names.length; i++) { String name = roots[i].getPath(); - if (name.endsWith(File.separator)) { - name = name.substring(0, name.length() - File.separator.length()); - } + name = StringUtil.trimEnd(name, File.separator); names[i] = name; } return names; diff --git a/platform/platform-impl/src/com/intellij/platform/LocationNameFieldsBinding.java b/platform/platform-impl/src/com/intellij/platform/LocationNameFieldsBinding.java index f4b719465ddc..6c0cd917cf89 100644 --- a/platform/platform-impl/src/com/intellij/platform/LocationNameFieldsBinding.java +++ b/platform/platform-impl/src/com/intellij/platform/LocationNameFieldsBinding.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -23,6 +23,7 @@ import com.intellij.openapi.ui.TextComponentAccessor; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.DocumentAdapter; import org.jetbrains.annotations.NotNull; @@ -88,9 +89,7 @@ public class LocationNameFieldsBinding { } myModifyingLocation = true; String path = locationField.getText().trim(); - if (path.endsWith(File.separator)) { - path = path.substring(0, path.length() - File.separator.length()); - } + path = StringUtil.trimEnd(path, File.separator); int ind = path.lastIndexOf(File.separator); if (ind != -1) { String projectName = path.substring(ind + 1, path.length()); diff --git a/platform/projectModel-api/src/com/intellij/openapi/project/ProjectUtilCore.java b/platform/projectModel-api/src/com/intellij/openapi/project/ProjectUtilCore.java index 120605d93292..b4a97c938b61 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/project/ProjectUtilCore.java +++ b/platform/projectModel-api/src/com/intellij/openapi/project/ProjectUtilCore.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -83,9 +83,7 @@ public class ProjectUtilCore { } String projectName = FileUtil.toSystemIndependentName(location); - if (projectName.endsWith("/")) { - projectName = projectName.substring(0, projectName.length() - 1); - } + projectName = StringUtil.trimEnd(projectName, "/"); final int lastSlash = projectName.lastIndexOf('/'); if (lastSlash >= 0 && lastSlash + 1 < projectName.length()) { diff --git a/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/SimpleProjectRoot.java b/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/SimpleProjectRoot.java index c2ed28929c2d..be2d7a654feb 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/SimpleProjectRoot.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/SimpleProjectRoot.java @@ -17,6 +17,7 @@ package com.intellij.openapi.projectRoots.impl; import com.intellij.openapi.projectRoots.ex.ProjectRoot; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; @@ -58,9 +59,7 @@ public class SimpleProjectRoot implements ProjectRoot { @NotNull public String getPresentableString() { String path = VirtualFileManager.extractPath(myUrl); - if (path.endsWith(URLUtil.JAR_SEPARATOR)) { - path = path.substring(0, path.length() - URLUtil.JAR_SEPARATOR.length()); - } + path = StringUtil.trimEnd(path, URLUtil.JAR_SEPARATOR); return path.replace('/', File.separatorChar); } diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/TestsPresentationUtil.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/TestsPresentationUtil.java index 44ff3ddc45b9..acd78a94cb74 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/TestsPresentationUtil.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/TestsPresentationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -237,11 +237,9 @@ public class TestsPresentationUtil { } if (parentStartsWith) { presentationCandidate = name.substring(parentName.length()); - + // remove "." separator - if (presentationCandidate.startsWith(".")) { - presentationCandidate = presentationCandidate.substring(1); - } + presentationCandidate = StringUtil.trimStart(presentationCandidate, "."); } } } diff --git a/platform/util/src/com/intellij/openapi/util/io/UniqueNameBuilder.java b/platform/util/src/com/intellij/openapi/util/io/UniqueNameBuilder.java index 7ebbc1b788af..c7d2237dd273 100644 --- a/platform/util/src/com/intellij/openapi/util/io/UniqueNameBuilder.java +++ b/platform/util/src/com/intellij/openapi/util/io/UniqueNameBuilder.java @@ -1,9 +1,25 @@ +/* + * Copyright 2000-2015 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.util.io; +import com.intellij.openapi.util.text.StringUtil; import gnu.trove.THashMap; import gnu.trove.TIntObjectHashMap; -import java.util.*; +import java.util.Map; /** * @author yole @@ -40,12 +56,12 @@ public class UniqueNameBuilder { private final Node myRootNode = new Node('\0', null); public void addPath(T key, String value) { - if (value.startsWith(myRoot)) value = value.substring(myRoot.length()); + value = StringUtil.trimStart(value, myRoot); myPaths.put(key, value); Node current = myRootNode; - for(int i = value.length() - 1; i >=0; --i) { + for (int i = value.length() - 1; i >= 0; --i) { char ch = value.charAt(i); Node node = current.myChildren.get(ch); if (node == null) current.myChildren.put(ch, node = new Node(ch, current)); diff --git a/platform/util/src/com/intellij/ui/ColorUtil.java b/platform/util/src/com/intellij/ui/ColorUtil.java index 965e2b22ab9b..9eb0dc278b83 100644 --- a/platform/util/src/com/intellij/ui/ColorUtil.java +++ b/platform/util/src/com/intellij/ui/ColorUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,6 +19,7 @@ */ package com.intellij.ui; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -108,9 +109,7 @@ public class ColorUtil { * @return Color object */ public static Color fromHex(String str) { - if (str.startsWith("#")) { - str = str.substring(1); - } + str = StringUtil.trimStart(str, "#"); if (str.length() == 3) { return new Color( 17 * Integer.valueOf(String.valueOf(str.charAt(0)), 16).intValue(), diff --git a/platform/util/src/com/intellij/util/lang/ClasspathCache.java b/platform/util/src/com/intellij/util/lang/ClasspathCache.java index 19f31630c894..82f180d52d29 100644 --- a/platform/util/src/com/intellij/util/lang/ClasspathCache.java +++ b/platform/util/src/com/intellij/util/lang/ClasspathCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -201,9 +201,7 @@ public class ClasspathCache { } static String transformName(String name) { - if (name.endsWith("/")) { - name = name.substring(0, name.length() - 1); - } + name = StringUtil.trimEnd(name, "/"); name = name.substring(name.lastIndexOf('/') + 1); if (name.endsWith(UrlClassLoader.CLASS_EXTENSION)) { diff --git a/platform/util/src/com/intellij/util/lang/FileLoader.java b/platform/util/src/com/intellij/util/lang/FileLoader.java index 8d36b2462d6c..080cdc57d838 100644 --- a/platform/util/src/com/intellij/util/lang/FileLoader.java +++ b/platform/util/src/com/intellij/util/lang/FileLoader.java @@ -16,6 +16,7 @@ package com.intellij.util.lang; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -69,7 +70,7 @@ class FileLoader extends Loader { private String getRelativeResourcePath(final String absFilePath) { String relativePath = absFilePath.substring(myRootDirAbsolutePath.length()); relativePath = relativePath.replace(File.separatorChar, '/'); - if (relativePath.startsWith("/")) relativePath = relativePath.substring(1); + relativePath = StringUtil.trimStart(relativePath, "/"); return relativePath; } diff --git a/platform/util/src/com/intellij/util/lang/UrlClassLoader.java b/platform/util/src/com/intellij/util/lang/UrlClassLoader.java index 62f57f9cb2c9..c9ae43d9f0a7 100644 --- a/platform/util/src/com/intellij/util/lang/UrlClassLoader.java +++ b/platform/util/src/com/intellij/util/lang/UrlClassLoader.java @@ -20,6 +20,7 @@ import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.win32.IdeaWin32; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.WeakStringInterner; @@ -273,7 +274,7 @@ public class UrlClassLoader extends ClassLoader { @Nullable private Resource _getResource(final String name) { String n = name; - if (n.startsWith("/")) n = n.substring(1); + n = StringUtil.trimStart(n, "/"); return getClassPath().getResource(n, true); } diff --git a/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/diff/impl/patch/UnifiedDiffWriter.java b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/diff/impl/patch/UnifiedDiffWriter.java index 56997f1ea61f..59910be0b100 100644 --- a/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/diff/impl/patch/UnifiedDiffWriter.java +++ b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/diff/impl/patch/UnifiedDiffWriter.java @@ -73,15 +73,19 @@ public class UnifiedDiffWriter { lineSeparator); for(PatchLine line: hunk.getLines()) { char prefixChar = ' '; - switch(line.getType()) { - case ADD: prefixChar = '+'; break; - case REMOVE: prefixChar = '-'; break; - case CONTEXT: prefixChar = ' '; break; + switch (line.getType()) { + case ADD: + prefixChar = '+'; + break; + case REMOVE: + prefixChar = '-'; + break; + case CONTEXT: + prefixChar = ' '; + break; } String text = line.getText(); - if (text.endsWith("\n")) { - text = text.substring(0, text.length()-1); - } + text = StringUtil.trimEnd(text, "\n"); writeLine(writer, text, prefixChar); if (line.isSuppressNewLine()) { writer.write(lineSeparator + NO_NEWLINE_SIGNATURE + lineSeparator); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/CodeAnalysisBeforeCheckinHandler.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/CodeAnalysisBeforeCheckinHandler.java index d3630fb638d4..bcecf9e8d28f 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/CodeAnalysisBeforeCheckinHandler.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/CodeAnalysisBeforeCheckinHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -25,6 +25,7 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.CheckinProjectPanel; import com.intellij.openapi.vcs.CodeSmellDetector; import com.intellij.openapi.vcs.VcsBundle; @@ -33,13 +34,11 @@ import com.intellij.openapi.vcs.changes.CommitExecutor; import com.intellij.openapi.vcs.ui.RefreshableOnComponent; import com.intellij.ui.NonFocusableCheckBox; import com.intellij.util.PairConsumer; -import com.intellij.util.PlatformUtils; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.text.MessageFormat; import java.util.List; /** @@ -97,14 +96,14 @@ public class CodeAnalysisBeforeCheckinHandler extends CheckinHandler { int errorCount = collectErrors(codeSmells); int warningCount = codeSmells.size() - errorCount; String commitButtonText = executor != null ? executor.getActionText() : myCheckinPanel.getCommitActionName(); - if (commitButtonText.endsWith("...")) { - commitButtonText = commitButtonText.substring(0, commitButtonText.length()-3); - } + commitButtonText = StringUtil.trimEnd(commitButtonText, "..."); final int answer = Messages.showYesNoCancelDialog(myProject, - VcsBundle.message("before.commit.files.contain.code.smells.edit.them.confirm.text", errorCount, warningCount), - VcsBundle.message("code.smells.error.messages.tab.name"), VcsBundle.message("code.smells.review.button"), - commitButtonText, CommonBundle.getCancelButtonText(), UIUtil.getWarningIcon()); + VcsBundle.message("before.commit.files.contain.code.smells.edit.them.confirm.text", + errorCount, warningCount), + VcsBundle.message("code.smells.error.messages.tab.name"), + VcsBundle.message("code.smells.review.button"), + commitButtonText, CommonBundle.getCancelButtonText(), UIUtil.getWarningIcon()); if (answer == Messages.YES) { CodeSmellDetector.getInstance(myProject).showCodeSmellErrors(codeSmells); return ReturnResult.CLOSE_WINDOW; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.java index 61180a2b2415..bc67fe200a38 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.java @@ -33,6 +33,7 @@ import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.CheckinProjectPanel; import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vcs.VcsConfiguration; @@ -174,9 +175,7 @@ public class TodoCheckinHandler extends CheckinHandler { private ReturnResult showResults(final TodoCheckinHandlerWorker worker, CommitExecutor executor) { String commitButtonText = executor != null ? executor.getActionText() : myCheckinProjectPanel.getCommitActionName(); - if (commitButtonText.endsWith("...")) { - commitButtonText = commitButtonText.substring(0, commitButtonText.length()-3); - } + commitButtonText = StringUtil.trimEnd(commitButtonText, "..."); final String text = createMessage(worker); final String[] buttons; diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToScientificNotationPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToScientificNotationPredicate.java index 7c3fe43999a5..515542549ad1 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToScientificNotationPredicate.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToScientificNotationPredicate.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -15,6 +15,7 @@ */ package com.siyeh.ipp.integer; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiLiteralExpression; import com.intellij.psi.PsiType; @@ -39,9 +40,7 @@ class ConvertToScientificNotationPredicate implements PsiElementPredicate { return false; } text = text.toLowerCase(); - if (text.startsWith("-")) { - text = text.substring(1); - } + text = StringUtil.trimStart(text, "-"); if (!text.contains(".") && text.startsWith("0")) { return false; //Octal integer } diff --git a/plugins/ant/src/com/intellij/lang/ant/config/execution/AntBuildMessageView.java b/plugins/ant/src/com/intellij/lang/ant/config/execution/AntBuildMessageView.java index 9aa64f1508ea..82a2addbc7bf 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/execution/AntBuildMessageView.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/execution/AntBuildMessageView.java @@ -44,6 +44,7 @@ import com.intellij.openapi.util.Clock; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; @@ -468,9 +469,7 @@ public final class AntBuildMessageView extends JPanel implements DataProvider, O } private static AntMessage createErrorMessage(int priority, String text) { - if (text.startsWith(FILE_PREFIX)) { - text = text.substring(FILE_PREFIX.length()); - } + text = StringUtil.trimStart(text, FILE_PREFIX); int afterLineNumberIndex = text.indexOf(": "); // end of file_name_and_line_number sequence if (afterLineNumberIndex != -1) { diff --git a/plugins/coverage/src/com/intellij/coverage/PackageAnnotator.java b/plugins/coverage/src/com/intellij/coverage/PackageAnnotator.java index 46b34ceff994..51cf69353472 100644 --- a/plugins/coverage/src/com/intellij/coverage/PackageAnnotator.java +++ b/plugins/coverage/src/com/intellij/coverage/PackageAnnotator.java @@ -30,7 +30,10 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiPackage; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.rt.coverage.data.ClassData; import com.intellij.rt.coverage.data.LineCoverage; @@ -523,7 +526,7 @@ public class PackageAnnotator { private static String getSourceToplevelFQName(String classFQVMName) { final int index = classFQVMName.indexOf('$'); if (index > 0) classFQVMName = classFQVMName.substring(0, index); - if (classFQVMName.startsWith("/")) classFQVMName = classFQVMName.substring(1); + classFQVMName = StringUtil.trimStart(classFQVMName, "/"); return classFQVMName.replaceAll("/", "."); } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsUtil.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsUtil.java index 5c47e2a97e6d..1e9249acd033 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsUtil.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsUtil.java @@ -660,22 +660,17 @@ public class CvsUtil { } - public static String getRelativeRepositoryPath(String repository, String serverRoot) { + public static String getRelativeRepositoryPath(String repository, String serverRoot) { repository = repository.replace(File.separatorChar, '/'); serverRoot = serverRoot.replace(File.separatorChar, '/'); if (repository.startsWith(serverRoot)) { repository = repository.substring(serverRoot.length()); - if (repository.startsWith("/")) { - repository = repository.substring(1); - } - + repository = StringUtil.trimStart(repository, "/"); } - if (repository.startsWith("./")) { - repository = repository.substring(2); - } + repository = StringUtil.trimStart(repository, "./"); return repository; } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/LogInformationWrapper.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/LogInformationWrapper.java index 50538024438b..2f7ae5c24c7b 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/LogInformationWrapper.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/LogInformationWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -16,6 +16,7 @@ package com.intellij.cvsSupport2.changeBrowser; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; import org.netbeans.lib.cvsclient.command.log.LogInformation; @@ -66,12 +67,8 @@ public class LogInformationWrapper { private static LogInformationWrapper buildWrapper(LogInformation log, String rcsFileName, int length) { String relativePath = rcsFileName.substring(length); - if (relativePath.startsWith("/")) { - relativePath = relativePath.substring(1); - } - if (relativePath.endsWith(CVS_REPOSITORY_FILE_POSTFIX)) { - relativePath = relativePath.substring(0, relativePath.length() - CVS_REPOSITORY_FILE_POSTFIX.length()); - } + relativePath = StringUtil.trimStart(relativePath, "/"); + relativePath = StringUtil.trimEnd(relativePath, CVS_REPOSITORY_FILE_POSTFIX); return new LogInformationWrapper(relativePath, log.getRevisionList(), log.getAllSymbolicNames()); } } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/config/CvsApplicationLevelConfiguration.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/config/CvsApplicationLevelConfiguration.java index 23cbefd47cb6..dc2f13a18c21 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/config/CvsApplicationLevelConfiguration.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/config/CvsApplicationLevelConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -189,9 +189,7 @@ public class CvsApplicationLevelConfiguration implements NamedComponent, JDOMExt try { String line; while ((line = reader.readLine()) != null) { - if (line.startsWith("/1 ")) { - line = line.substring(3); - } + line = StringUtil.trimStart(line, "/1 "); final int sepPosition = line.indexOf(' '); if (sepPosition > 0) { final String cvsRoot = line.substring(0, sepPosition); diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/FormUtils.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/FormUtils.java index 865524ede23c..7a79aaf5a519 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/FormUtils.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/FormUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -18,6 +18,7 @@ package com.intellij.cvsSupport2.ui; import com.intellij.CvsBundle; import com.intellij.openapi.ui.InputException; import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.openapi.util.text.StringUtil; import javax.swing.*; @@ -44,9 +45,7 @@ public class FormUtils { private static String getLabelText(JComponent field) { final JLabel label = (JLabel)field.getClientProperty("labeledBy"); String text = label.getText(); - if (text.endsWith(":")) { - text = text.substring(0, text.length() - 1); - } + text = StringUtil.trimEnd(text, ":"); return text; } diff --git a/plugins/cvs/javacvs-src/org/netbeans/lib/cvsclient/command/status/StatusMessageParser.java b/plugins/cvs/javacvs-src/org/netbeans/lib/cvsclient/command/status/StatusMessageParser.java index d095cbea6241..b1b765d0ac6e 100644 --- a/plugins/cvs/javacvs-src/org/netbeans/lib/cvsclient/command/status/StatusMessageParser.java +++ b/plugins/cvs/javacvs-src/org/netbeans/lib/cvsclient/command/status/StatusMessageParser.java @@ -12,6 +12,8 @@ */ package org.netbeans.lib.cvsclient.command.status; +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NonNls; import org.netbeans.lib.cvsclient.command.AbstractMessageParser; import org.netbeans.lib.cvsclient.event.IEventSender; import org.netbeans.lib.cvsclient.file.AbstractFileObject; @@ -19,7 +21,6 @@ import org.netbeans.lib.cvsclient.file.FileObject; import org.netbeans.lib.cvsclient.file.FileStatus; import org.netbeans.lib.cvsclient.file.ICvsFileSystem; import org.netbeans.lib.cvsclient.util.BugLog; -import org.jetbrains.annotations.NonNls; import java.io.File; import java.util.ArrayList; @@ -135,9 +136,7 @@ final class StatusMessageParser extends AbstractMessageParser { final String statusString = line.substring(statusIndex + STATUS.length()); final FileStatus status = FileStatus.getStatusForString(statusString); String fileName = line.substring(FILE.length(), statusIndex).trim(); - if (fileName.startsWith(NO_FILE)) { - fileName = fileName.substring(NO_FILE.length()); - } + fileName = StringUtil.trimStart(fileName, NO_FILE); outputDone(); diff --git a/plugins/devkit/src/dom/generator/Util.java b/plugins/devkit/src/dom/generator/Util.java index a393bb143602..4e87510ae813 100644 --- a/plugins/devkit/src/dom/generator/Util.java +++ b/plugins/devkit/src/dom/generator/Util.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -22,6 +22,7 @@ */ package org.jetbrains.idea.devkit.dom.generator; +import com.intellij.openapi.util.text.StringUtil; import org.apache.xerces.xs.XSObject; import java.util.HashMap; @@ -150,7 +151,7 @@ public class Util { public static String toDefXmlTagName(String tname) { String xmlName = tname; - if (xmlName.endsWith(TYPE_SUFFIX)) xmlName = xmlName.substring(0, xmlName.length() - TYPE_SUFFIX.length()); + xmlName = StringUtil.trimEnd(xmlName, TYPE_SUFFIX); return xmlName; } diff --git a/plugins/devkit/src/inspections/internal/UseJBColorInspection.java b/plugins/devkit/src/inspections/internal/UseJBColorInspection.java index 17f3405abfa3..6c378d56ba26 100644 --- a/plugins/devkit/src/inspections/internal/UseJBColorInspection.java +++ b/plugins/devkit/src/inspections/internal/UseJBColorInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.ui.JBColor; @@ -63,16 +64,16 @@ public class UseJBColorInspection extends InternalInspection { if (text.contains(".")) { text = text.substring(text.lastIndexOf('.')); } - if (text.startsWith(".")) { - text = text.substring(1); - } + text = StringUtil.trimStart(text, "."); if (text.equalsIgnoreCase("lightGray")) { text = "LIGHT_GRAY"; - } else if (text.equalsIgnoreCase("darkGray")) { + } + else if (text.equalsIgnoreCase("darkGray")) { text = "DARK_GRAY"; } final ProblemDescriptor descriptor = holder.getManager() - .createProblemDescriptor(expression, "Change to JBColor." + text.toUpperCase(), new ConvertToJBColorConstantQuickFix(text.toUpperCase()), + .createProblemDescriptor(expression, "Change to JBColor." + text.toUpperCase(), + new ConvertToJBColorConstantQuickFix(text.toUpperCase()), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly); holder.registerProblem(descriptor); } diff --git a/plugins/devkit/src/inspections/quickfix/AbstractRegisterFix.java b/plugins/devkit/src/inspections/quickfix/AbstractRegisterFix.java index 294332acec5d..7a3be851ce22 100644 --- a/plugins/devkit/src/inspections/quickfix/AbstractRegisterFix.java +++ b/plugins/devkit/src/inspections/quickfix/AbstractRegisterFix.java @@ -24,6 +24,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiFile; import com.intellij.psi.SmartPsiElementPointer; @@ -62,9 +63,7 @@ abstract class AbstractRegisterFix implements LocalQuickFix, DescriptorUtil.Patc protected static String filterMessage(String message) { if (message == null) return null; @NonNls String ioExceptionPrefix = "java.io.IOException:"; - if (message.startsWith(ioExceptionPrefix)) { - message = message.substring(ioExceptionPrefix.length()); - } + message = StringUtil.trimStart(message, ioExceptionPrefix); return message; } diff --git a/plugins/devkit/src/testAssistant/TestDataGuessByExistingFilesUtil.java b/plugins/devkit/src/testAssistant/TestDataGuessByExistingFilesUtil.java index fde03a6cd073..993ef3671e95 100644 --- a/plugins/devkit/src/testAssistant/TestDataGuessByExistingFilesUtil.java +++ b/plugins/devkit/src/testAssistant/TestDataGuessByExistingFilesUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -241,9 +241,7 @@ public class TestDataGuessByExistingFilesUtil { if (result == null) { return null; } - if (result.endsWith("Test")) { - result = result.substring(0, result.length() - "Test".length()); - } + result = StringUtil.trimEnd(result, "Test"); int i = result.lastIndexOf('.'); if (i >= 0) { result = result.substring(i + 1); diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/util/PathUtil.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/util/PathUtil.java index d99e9874419e..aa6b7ce7b8b0 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/util/PathUtil.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/util/PathUtil.java @@ -16,29 +16,24 @@ package org.jetbrains.idea.eclipse.util; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; public class PathUtil { public static String normalize(String path) { path = FileUtil.toSystemIndependentName(path); - if (path.endsWith("/")) { - path = path.substring(0, path.length() - 1); - } + path = StringUtil.trimEnd(path, "/"); while (path.contains("/./")) { path = path.replace("/./", "/"); } - if (path.startsWith("./")) { - path = path.substring(2); - } - if (path.endsWith("/.")) { - path = path.substring(0, path.length() - 2); - } + path = StringUtil.trimStart(path, "./"); + path = StringUtil.trimEnd(path, "/."); - while ( true ) { + while (true) { int index = path.indexOf("/.."); - if ( index < 0 ) break; - int slashIndex = path.substring(0,index).lastIndexOf("/"); - if ( slashIndex < 0 ) break; - path = path.substring(0, slashIndex ) + path.substring(index+3); + if (index < 0) break; + int slashIndex = path.substring(0, index).lastIndexOf("/"); + if (slashIndex < 0) break; + path = path.substring(0, slashIndex) + path.substring(index + 3); } return path; diff --git a/plugins/git4idea/src/git4idea/push/GitPushSpecParser.java b/plugins/git4idea/src/git4idea/push/GitPushSpecParser.java index 813e591eb6d8..ea124720a840 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushSpecParser.java +++ b/plugins/git4idea/src/git4idea/push/GitPushSpecParser.java @@ -16,6 +16,7 @@ package git4idea.push; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.text.StringUtil; import git4idea.branch.GitBranchUtil; import git4idea.repo.GitRepository; import org.jetbrains.annotations.NotNull; @@ -51,9 +52,7 @@ class GitPushSpecParser { } String source = parts[0].trim(); String target = parts[1].trim(); - if (source.startsWith("+")) { - source = source.substring(1); - } + source = StringUtil.trimStart(source, "+"); if (!isStarPositionValid(source, target)) { return null; diff --git a/plugins/git4idea/tests/git4idea/test/RefParser.java b/plugins/git4idea/tests/git4idea/test/RefParser.java index 31150e18c4ca..7f6ce6685a40 100644 --- a/plugins/git4idea/tests/git4idea/test/RefParser.java +++ b/plugins/git4idea/tests/git4idea/test/RefParser.java @@ -1,5 +1,21 @@ +/* + * Copyright 2000-2015 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 git4idea.test; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsLogObjectsFactory; @@ -46,9 +62,7 @@ class RefParser { @NotNull private static String getRefName(@NotNull String longRefPath) { String tagPrefix = "tag: "; - if (longRefPath.startsWith(tagPrefix)) { - longRefPath = longRefPath.substring(tagPrefix.length()); - } + longRefPath = StringUtil.trimStart(longRefPath, tagPrefix); return longRefPath; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/ConvertGStringToStringIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/ConvertGStringToStringIntention.java index 7ca2adc88193..224cb0b76ae2 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/ConvertGStringToStringIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/ConvertGStringToStringIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.intentions.conversions.strings; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.CommonClassNames; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiType; @@ -138,17 +139,13 @@ public class ConvertGStringToStringIntention extends Intention { if (text.startsWith("\"\"\"")) { text = text.substring(3); } - else if (text.startsWith("\"")) { - text = text.substring(1); - } + else text = StringUtil.trimStart(text, "\""); } if (isLast) { if (text.endsWith("\"\"\"")) { text = text.substring(0, text.length() - 3); } - else if (text.endsWith("\"")) { - text = text.substring(0, text.length() - 1); - } + else text = StringUtil.trimEnd(text, "\""); } if (isBeforeInjection) { text = text.substring(0, text.length() - 1); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.java index c56cee1583a9..2c4b98371cb6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.java @@ -159,9 +159,7 @@ public class MvcRunTargetDialog extends DialogWrapper { String text = getSelectedText(); text = text.trim(); - if (text.startsWith(GRAILS_PREFIX)) { - text = text.substring(GRAILS_PREFIX.length()); - } + text = StringUtil.trimStart(text, GRAILS_PREFIX); return text; } diff --git a/plugins/java-i18n/src/com/intellij/lang/properties/PrefixBasedPropertyReference.java b/plugins/java-i18n/src/com/intellij/lang/properties/PrefixBasedPropertyReference.java index 0638aa0497e2..cc0afcc4428f 100644 --- a/plugins/java-i18n/src/com/intellij/lang/properties/PrefixBasedPropertyReference.java +++ b/plugins/java-i18n/src/com/intellij/lang/properties/PrefixBasedPropertyReference.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -15,16 +15,16 @@ */ package com.intellij.lang.properties; +import com.intellij.lang.properties.references.PropertyReference; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.psi.xml.XmlTag; import com.intellij.util.IncorrectOperationException; import com.intellij.xml.util.XmlUtil; -import com.intellij.lang.properties.references.PropertyReference; -import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.Set; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenClassSearcher.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenClassSearcher.java index 4544de91a647..5f7f1275bfa6 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenClassSearcher.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenClassSearcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -94,7 +94,7 @@ public class MavenClassSearcher extends MavenSearcher { while (matcher.find()) { String classFQName = matcher.group(1); classFQName = classFQName.replace("/", "."); - if (classFQName.startsWith(".")) classFQName = classFQName.substring(1); + classFQName = StringUtil.trimStart(classFQName, "."); String key = makeKey(classFQName, each); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java index 2ee3ba6b34ae..a1fb331f3fb1 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -462,11 +462,9 @@ public class MavenProject { Element compilerArguments = compilerConfig.getChild("compilerArguments"); if (compilerArguments != null) { - for (Element e : compilerArguments.getChildren()){ + for (Element e : compilerArguments.getChildren()) { String name = e.getName(); - if (name.startsWith("-")) { - name = name.substring(1); - } + name = StringUtil.trimStart(name, "-"); if (name.length() > 1 && name.charAt(0) == 'A') { res.put(name.substring(1), e.getTextTrim()); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java index 8a986fc780ca..5f24e0a80e2c 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java @@ -330,7 +330,7 @@ public class MavenUtil { if (!Comparing.equal(modulePath.getParent(), parentModulePath)) { String relativePath = VfsUtil.getPath(file, parentModulePath, '/'); if (relativePath != null) { - if (relativePath.endsWith("/")) relativePath = relativePath.substring(0, relativePath.length() - 1); + relativePath = StringUtil.trimEnd(relativePath, "/"); conditions.setProperty("HAS_RELATIVE_PATH", "true"); properties.setProperty("PARENT_RELATIVE_PATH", relativePath); diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesImportingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesImportingTest.java index 4aea5a7795b3..c1d4a901c0e5 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesImportingTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesImportingTest.java @@ -26,6 +26,7 @@ import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.MavenCustomRepositoryHelper; @@ -1042,7 +1043,7 @@ public class DependenciesImportingTest extends MavenImportingTestCase { public void testDependencyWithEnvironmentENVProperty() throws Exception { String envDir = FileUtil.toSystemIndependentName(System.getenv(getEnvVar())); - if (envDir.endsWith("/")) envDir = envDir.substring(0, envDir.length() - 1); + envDir = StringUtil.trimEnd(envDir, "/"); importProject("test" + "project" + diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/PropertiesCopyHandler.java b/plugins/properties/src/com/intellij/lang/properties/editor/PropertiesCopyHandler.java index 7ab109527f72..41a0386e6726 100644 --- a/plugins/properties/src/com/intellij/lang/properties/editor/PropertiesCopyHandler.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/PropertiesCopyHandler.java @@ -38,7 +38,10 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFileSystemItem; +import com.intellij.psi.PsiManager; import com.intellij.psi.impl.SyntheticFileSystemItem; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.refactoring.copy.CopyHandlerDelegateBase; @@ -60,7 +63,6 @@ import java.awt.*; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.*; -import java.util.HashSet; import java.util.List; /** @@ -194,9 +196,7 @@ public class PropertiesCopyHandler extends CopyHandlerDelegateBase { @NotNull private static String getPropertiesFileSuffix(PropertiesFile searchFile, String baseName) { String suffix = FileUtil.getNameWithoutExtension(searchFile.getContainingFile().getName()); - if (suffix.startsWith(baseName)) { - suffix = suffix.substring(baseName.length()); - } + suffix = StringUtil.trimStart(suffix, baseName); return suffix; } diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/jql/psi/impl/JqlElementImpl.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/jql/psi/impl/JqlElementImpl.java index cfa99296a24c..b2247101467b 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/jql/psi/impl/JqlElementImpl.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/jql/psi/impl/JqlElementImpl.java @@ -1,7 +1,23 @@ +/* + * Copyright 2000-2015 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.tasks.jira.jql.psi.impl; import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElementVisitor; import com.intellij.tasks.jira.jql.psi.JqlElement; import com.intellij.tasks.jira.jql.psi.JqlElementVisitor; @@ -18,9 +34,7 @@ public abstract class JqlElementImpl extends ASTWrapperPsiElement implements Jql @Override public String toString() { String className = getClass().getSimpleName(); - if (className.endsWith("Impl")) { - className = className.substring(0, className.length() - 4); - } + className = StringUtil.trimEnd(className, "Impl"); return String.format("%s(%s)", className, getText()); } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/bugzilla/BugzillaTask.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/bugzilla/BugzillaTask.java index 3b1fe9706292..eb8a9db31ca1 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/bugzilla/BugzillaTask.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/bugzilla/BugzillaTask.java @@ -1,5 +1,21 @@ +/* + * Copyright 2000-2015 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.tasks.bugzilla; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.tasks.*; import icons.TasksIcons; import org.jetbrains.annotations.NotNull; @@ -104,9 +120,7 @@ public class BugzillaTask extends Task { @Override public String getIssueUrl() { String repositoryUrl = myRepository.getUrl(); - if (repositoryUrl.endsWith("xmlrpc.cgi")) { - repositoryUrl = repositoryUrl.substring(0, repositoryUrl.length() - "xmlrpc.cgi".length()); - } + repositoryUrl = StringUtil.trimEnd(repositoryUrl, "xmlrpc.cgi"); return repositoryUrl + "/show_bug.cgi?id=" + getId(); } diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java index 832c6cb62ac9..430a7fc0aefa 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -26,6 +26,7 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.ui.LabeledComponent; import com.intellij.openapi.ui.VerticalFlowLayout; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.platform.DirectoryProjectGenerator; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.HideableDecorator; @@ -255,9 +256,7 @@ public class ProjectSpecificSettingsStep extends ProjectSettingsStepBase impleme protected void textChanged(DocumentEvent e) { if (myProjectGenerator instanceof PythonProjectGenerator) { String path = myLocationField.getText().trim(); - if (path.endsWith(File.separator)) { - path = path.substring(0, path.length() - File.separator.length()); - } + path = StringUtil.trimEnd(path, File.separator); int ind = path.lastIndexOf(File.separator); if (ind != -1) { String projectName = path.substring(ind + 1, path.length()); diff --git a/python/openapi/src/com/jetbrains/python/packaging/PyRequirement.java b/python/openapi/src/com/jetbrains/python/packaging/PyRequirement.java index 19f90a586570..07493ac7a044 100644 --- a/python/openapi/src/com/jetbrains/python/packaging/PyRequirement.java +++ b/python/openapi/src/com/jetbrains/python/packaging/PyRequirement.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -384,9 +384,7 @@ public class PyRequirement { } egg = vcsPathMatcher.group(1); final String gitSuffix = ".git"; - if (egg.endsWith(gitSuffix)) { - egg = egg.substring(0, egg.length() - gitSuffix.length()); - } + egg = StringUtil.trimEnd(egg, gitSuffix); } } } diff --git a/python/psi-api/src/com/jetbrains/python/PythonStringUtil.java b/python/psi-api/src/com/jetbrains/python/PythonStringUtil.java index 7020f605e89d..9d39aceee2b4 100644 --- a/python/psi-api/src/com/jetbrains/python/PythonStringUtil.java +++ b/python/psi-api/src/com/jetbrains/python/PythonStringUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -22,11 +22,11 @@ import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; +import com.intellij.psi.util.QualifiedName; import com.intellij.util.ObjectUtils; import com.intellij.util.PathUtil; import com.jetbrains.python.psi.PyExpression; import com.jetbrains.python.psi.PyStringLiteralExpression; -import com.intellij.psi.util.QualifiedName; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -315,9 +315,7 @@ public class PythonStringUtil { public static boolean isRawString(String text) { text = text.toLowerCase(); - if (text.startsWith("u")) { - text = text.substring(1); - } + text = StringUtil.trimStart(text, "u"); return isStringPrefixedBy(text.toLowerCase(), "r"); } diff --git a/python/pydevSrc/com/jetbrains/python/console/pydev/AbstractPyCodeCompletion.java b/python/pydevSrc/com/jetbrains/python/console/pydev/AbstractPyCodeCompletion.java index f367069b8009..3452a1700a03 100644 --- a/python/pydevSrc/com/jetbrains/python/console/pydev/AbstractPyCodeCompletion.java +++ b/python/pydevSrc/com/jetbrains/python/console/pydev/AbstractPyCodeCompletion.java @@ -1,9 +1,7 @@ package com.jetbrains.python.console.pydev; - -import java.util.Iterator; -import java.util.List; +import com.intellij.openapi.util.text.StringUtil; public class AbstractPyCodeCompletion { public static final int LOOKING_FOR_INSTANCE_UNDEFINED=0; @@ -23,18 +21,18 @@ public class AbstractPyCodeCompletion { lookingFor==LOOKING_FOR_INSTANCED_VARIABLE || lookingFor==LOOKING_FOR_ASSIGN; String trimmed = argsReceived.trim(); - if(trimmed.length() > 0){ + if(trimmed.length() > 0) { FastStringBuffer buffer = new FastStringBuffer("(", 128); char c = trimmed.charAt(0); - if(c == '('){ + if (c == '(') { trimmed = trimmed.substring(1); } - if(trimmed.length() > 0){ - c = trimmed.charAt(trimmed.length()-1); - if(c == ')'){ - trimmed = trimmed.substring(0, trimmed.length()-1); + if (trimmed.length() > 0) { + c = trimmed.charAt(trimmed.length() - 1); + if (c == ')') { + trimmed = trimmed.substring(0, trimmed.length() - 1); } } trimmed = trimmed.trim(); @@ -42,30 +40,29 @@ public class AbstractPyCodeCompletion { //Now, if it starts with self or cls, we may have to remove it. String temp; - if(lookingForInstance && trimmed.startsWith("self")){ + if (lookingForInstance && trimmed.startsWith("self")) { temp = trimmed.substring(4); - - }else if(trimmed.startsWith("cls")){ + } + else if (trimmed.startsWith("cls")) { temp = trimmed.substring(3); - }else{ + } + else { temp = trimmed; } temp = temp.trim(); - if(temp.length()>0){ + if (temp.length() > 0) { //but only if it wasn't a self or cls followed by a valid identifier part. - if(!Character.isJavaIdentifierPart(temp.charAt(0))){ + if (!Character.isJavaIdentifierPart(temp.charAt(0))) { trimmed = temp; } - }else{ + } + else { trimmed = temp; } - trimmed = trimmed.trim(); - if(trimmed.startsWith(",")){ - trimmed = trimmed.substring(1); - } + trimmed = StringUtil.trimStart(trimmed, ","); trimmed = trimmed.trim(); buffer.append(trimmed); diff --git a/python/src/com/jetbrains/python/PythonHelpersLocator.java b/python/src/com/jetbrains/python/PythonHelpersLocator.java index ef81da6c944f..4ffb972655d0 100644 --- a/python/src/com/jetbrains/python/PythonHelpersLocator.java +++ b/python/src/com/jetbrains/python/PythonHelpersLocator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -17,6 +17,7 @@ package com.jetbrains.python; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.PathUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -43,9 +44,7 @@ public class PythonHelpersLocator { return new File(pluginBaseDir, "helpers"); } - if (jarPath.endsWith(COMMUNITY_SUFFIX)) { - jarPath = jarPath.substring(0, jarPath.length() - COMMUNITY_SUFFIX.length()); - } + jarPath = StringUtil.trimEnd(jarPath, COMMUNITY_SUFFIX); return new File(jarPath + "-helpers"); } diff --git a/python/src/com/jetbrains/python/buildout/BuildoutFacet.java b/python/src/com/jetbrains/python/buildout/BuildoutFacet.java index 5be81efe54ce..3b2c98347e26 100644 --- a/python/src/com/jetbrains/python/buildout/BuildoutFacet.java +++ b/python/src/com/jetbrains/python/buildout/BuildoutFacet.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -258,9 +258,7 @@ public class BuildoutFacet extends Facet implements index++; while (index < lines.length && !lines[index].trim().equals("]")) { String line = lines[index].trim(); - if (line.endsWith(",")) { - line = line.substring(0, line.length() - 1); - } + line = StringUtil.trimEnd(line, ","); if (line.startsWith("'") && line.endsWith("'")) { result.add(StringUtil.unescapeStringCharacters(line.substring(1, line.length() - 1))); } diff --git a/python/src/com/jetbrains/python/documentation/docstrings/DocStringTypeReference.java b/python/src/com/jetbrains/python/documentation/docstrings/DocStringTypeReference.java index 3b2096741016..3823f97b6302 100644 --- a/python/src/com/jetbrains/python/documentation/docstrings/DocStringTypeReference.java +++ b/python/src/com/jetbrains/python/documentation/docstrings/DocStringTypeReference.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -18,6 +18,7 @@ package com.jetbrains.python.documentation.docstrings; import com.google.common.collect.Lists; import com.intellij.codeInsight.completion.CompletionUtil; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.QualifiedName; import com.intellij.util.ArrayUtil; @@ -78,9 +79,7 @@ public class DocStringTypeReference extends PsiPolyVariantReferenceBase extends StubBasedPsiElemen if (pos >= 0) { className = className.substring(pos + 1); } - if (className.endsWith("Impl")) { - className = className.substring(0, className.length() - 4); - } + className = StringUtil.trimEnd(className, "Impl"); return className; } diff --git a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java index 2375662fafc0..bee30ef84990 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -25,6 +25,7 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.ResolveCache; import com.intellij.psi.util.PsiTreeUtil; @@ -394,9 +395,7 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference @Override public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { ASTNode nameElement = myElement.getNameElement(); - if (newElementName.endsWith(PyNames.DOT_PY)) { - newElementName = newElementName.substring(0, newElementName.length() - PyNames.DOT_PY.length()); - } + newElementName = StringUtil.trimEnd(newElementName, PyNames.DOT_PY); if (nameElement != null && PyNames.isIdentifier(newElementName)) { final ASTNode newNameElement = PyUtil.createNewName(myElement, newElementName); myElement.getNode().replaceChild(nameElement, newNameElement); diff --git a/python/src/com/jetbrains/python/refactoring/NameSuggesterUtil.java b/python/src/com/jetbrains/python/refactoring/NameSuggesterUtil.java index 5931c7ee2b10..4b03e43778c0 100644 --- a/python/src/com/jetbrains/python/refactoring/NameSuggesterUtil.java +++ b/python/src/com/jetbrains/python/refactoring/NameSuggesterUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -44,9 +44,7 @@ public class NameSuggesterUtil { if (name.startsWith("get")) { name = name.substring(3); } - else if (name.startsWith("is")) { - name = name.substring(2); - } + else name = StringUtil.trimStart(name, "is"); while (name.startsWith("_")) { name = name.substring(1); } diff --git a/python/src/com/jetbrains/python/remote/PyRemoteSourceItem.java b/python/src/com/jetbrains/python/remote/PyRemoteSourceItem.java index c7e5c478bd78..200f78a5c35e 100644 --- a/python/src/com/jetbrains/python/remote/PyRemoteSourceItem.java +++ b/python/src/com/jetbrains/python/remote/PyRemoteSourceItem.java @@ -15,6 +15,7 @@ */ package com.jetbrains.python.remote; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.remote.RemoteFile; import com.intellij.util.PathMappingSettings; import com.intellij.util.PathUtil; @@ -81,9 +82,7 @@ public class PyRemoteSourceItem { } public void setLocalPrefix(String localPrefix) { - if (localPrefix.endsWith("/")) { - localPrefix = localPrefix.substring(0, localPrefix.length() - 1); - } + localPrefix = StringUtil.trimEnd(localPrefix, "/"); myLocalPrefix = localPrefix; } diff --git a/python/src/com/jetbrains/python/testing/AbstractPythonTestRunConfiguration.java b/python/src/com/jetbrains/python/testing/AbstractPythonTestRunConfiguration.java index 175567e2e009..f79fbb400adb 100644 --- a/python/src/com/jetbrains/python/testing/AbstractPythonTestRunConfiguration.java +++ b/python/src/com/jetbrains/python/testing/AbstractPythonTestRunConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -241,9 +241,7 @@ public abstract class AbstractPythonTestRunConfiguration extends AbstractPythonR return getTitle() + " " + myClassName + "." + myMethodName; case TEST_SCRIPT: String name = new File(getScriptName()).getName(); - if (name.endsWith(".py")) { - name = name.substring(0, name.length() - 3); - } + name = StringUtil.trimEnd(name, ".py"); return getPluralTitle() + " in " + name; case TEST_FOLDER: String folderName = new File(myFolderName).getName(); diff --git a/xml/dom-openapi/src/com/intellij/util/xml/ui/BasicDomElementComponent.java b/xml/dom-openapi/src/com/intellij/util/xml/ui/BasicDomElementComponent.java index d2a17dd553c5..4acfbb48d936 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/ui/BasicDomElementComponent.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/ui/BasicDomElementComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -16,21 +16,21 @@ package com.intellij.util.xml.ui; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Factory; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.util.xml.DomElement; import com.intellij.util.xml.DomFileElement; import com.intellij.util.xml.DomUtil; import com.intellij.util.xml.GenericDomValue; import com.intellij.util.xml.highlighting.DomElementAnnotationsManager; +import com.intellij.util.xml.reflect.AbstractDomChildrenDescription; import com.intellij.util.xml.reflect.DomChildrenDescription; import com.intellij.util.xml.reflect.DomCollectionChildDescription; import com.intellij.util.xml.reflect.DomFixedChildDescription; -import com.intellij.util.xml.reflect.AbstractDomChildrenDescription; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -128,7 +128,7 @@ public abstract class BasicDomElementComponent extends Abs } private String convertFieldName(String propertyName, final DomChildrenDescription description) { - if (propertyName.startsWith("my")) propertyName = propertyName.substring(2); + propertyName = StringUtil.trimStart(propertyName, "my"); String convertedName = description.getDomNameStrategy(getDomElement()).convertName(propertyName); diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java index 4cb738387e6e..e1aa30f4a426 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -22,6 +22,7 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.editor.CaretModel; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.filters.*; import com.intellij.psi.filters.getters.XmlAttributeValueGetter; @@ -184,9 +185,7 @@ public class XmlCompletionData extends CompletionData { final int i = valueText.indexOf('#'); if (i > 0) { String s = valueText.substring(i + 1); - if (s.endsWith(";")) { - s = s.substring(0, s.length() - 1); - } + s = StringUtil.trimEnd(s, ";"); try { final int unicodeChar = Integer.valueOf(s).intValue(); diff --git a/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java b/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java index f224a68955fc..cd97e6ea7f05 100644 --- a/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java +++ b/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -508,9 +508,7 @@ public class XmlDocumentationProvider implements DocumentationProvider { withCData = true; } - if (result.endsWith(CDATA_SUFFIX)) { - result = result.substring(0, result.length() - CDATA_SUFFIX.length()); - } + result = StringUtil.trimEnd(result, CDATA_SUFFIX); result = result.trim(); if (withCData) { From 03c5d6182e90945ec9a013317388f64be1e0f0a5 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 8 Dec 2015 16:18:05 +0300 Subject: [PATCH 06/25] implemented all methods of ExecutorService; added cancelAll() and waitAllTasksExecuted(); made implementation implement ExecutorService instead of Executor to conform to the same pattern in JDK (TPE etc); shutdownXXX() methods should not mess the background executor; added tests. --- .../concurrency/BoundedTaskExecutorTest.java | 174 ++++++++++++++ .../util/concurrency/BoundedTaskExecutor.java | 226 ++++++++++++------ .../BoundedTaskExecutorService.java | 135 +---------- 3 files changed, 337 insertions(+), 198 deletions(-) create mode 100644 platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java diff --git a/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java b/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java new file mode 100644 index 000000000000..78074775f229 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java @@ -0,0 +1,174 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.concurrency; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; +import com.intellij.util.ConcurrencyUtil; +import com.intellij.util.TimeoutUtil; +import junit.framework.TestCase; + +import java.util.Random; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +public class BoundedTaskExecutorTest extends TestCase { + public void testReallyBound() throws InterruptedException, ExecutionException { + for (int maxTasks=1; maxTasks<5;maxTasks++) { + System.out.println("maxTasks = " + maxTasks); + ExecutorService backendExecutor = Executors.newCachedThreadPool(ConcurrencyUtil.newNamedThreadFactory("maxTasks = " + maxTasks)); + BoundedTaskExecutorService executor = new BoundedTaskExecutorService(backendExecutor, maxTasks); + AtomicInteger running = new AtomicInteger(); + AtomicInteger max = new AtomicInteger(); + AtomicInteger executed = new AtomicInteger(); + int N = 10000; + for (int i = 0; i < N; i++) { + executor.execute(() -> { + int r = running.incrementAndGet(); + try { + TimeoutUtil.sleep(1); + max.accumulateAndGet(r, Math::max); + executed.incrementAndGet(); + } + finally { + running.decrementAndGet(); + } + }); + } + executor.waitAllTasksExecuted(); + assertEquals(0, executor.shutdownNow().size()); + assertTrue(executor.awaitTermination(10, TimeUnit.SECONDS)); + backendExecutor.shutdownNow(); + assertTrue(backendExecutor.awaitTermination(100, TimeUnit.SECONDS)); + assertEquals(maxTasks, max.get()); + assertEquals(N, executed.get()); + } + } + + public void testCallableReallyReturnsValue() throws Exception{ + ExecutorService backendExecutor = Executors.newCachedThreadPool(ConcurrencyUtil.newNamedThreadFactory(getName())); + BoundedTaskExecutorService executor = new BoundedTaskExecutorService(backendExecutor, 1); + + Future f1 = executor.submit(() -> 42); + Integer result = f1.get(); + assertEquals(42, result.intValue()); + executor.shutdownNow(); + assertTrue(executor.awaitTermination(1, TimeUnit.SECONDS)); + backendExecutor.shutdownNow(); + assertTrue(backendExecutor.awaitTermination(100, TimeUnit.SECONDS)); + } + + public void testEarlyCancelPreventsRunning() throws ExecutionException, InterruptedException { + AtomicBoolean run = new AtomicBoolean(); + ExecutorService backendExecutor = Executors.newCachedThreadPool(ConcurrencyUtil.newNamedThreadFactory(getName())); + BoundedTaskExecutorService executor = new BoundedTaskExecutorService(backendExecutor, 1); + + int delay = 500; + Future s1 = executor.submit((Runnable)() -> TimeoutUtil.sleep(delay)); + Future f1 = executor.submit(() -> { + run.set(true); + return 42; + }); + f1.cancel(false); + TimeoutUtil.sleep(delay+200); + assertTrue(f1.isDone()); + assertTrue(f1.isCancelled()); + assertFalse(run.get()); + assertTrue(s1.isDone()); + executor.shutdownNow(); + assertTrue(executor.awaitTermination(1, TimeUnit.SECONDS)); + backendExecutor.shutdownNow(); + assertTrue(backendExecutor.awaitTermination(100, TimeUnit.SECONDS)); + } + + public void testStressWhenSomeTasksCallOtherTasksGet() throws ExecutionException, InterruptedException { + ExecutorService backendExecutor = Executors.newCachedThreadPool(ConcurrencyUtil.newNamedThreadFactory(getName())); + for (int maxSimultaneousTasks = 1; maxSimultaneousTasks<20;maxSimultaneousTasks++) { + final Disposable myDisposable = Disposer.newDisposable(); + BoundedTaskExecutorService executor = new BoundedTaskExecutorService(backendExecutor, maxSimultaneousTasks, myDisposable); + AtomicInteger running = new AtomicInteger(); + AtomicInteger maxThreads = new AtomicInteger(); + + try { + int N = 5000; + Future[] futures = new Future[N]; + Random random = new Random(); + for (int i = 0; i < N; i++) { + final int finalI = i; + final int finalMaxSimultaneousTasks = maxSimultaneousTasks; + futures[i] = executor.submit((Runnable)() -> { + maxThreads.accumulateAndGet(running.incrementAndGet(), Math::max); + + try { + int r = random.nextInt(finalMaxSimultaneousTasks); + int prev = finalI - r; + if (prev != finalI && prev >= 0) { + try { + futures[prev].get(); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + TimeoutUtil.sleep(r); + } + finally { + running.decrementAndGet(); + } + }); + } + executor.waitAllTasksExecuted(); + for (Future future : futures) { + assertTrue(future.isDone()); + } + } + finally { + Disposer.dispose(myDisposable); + assertTrue(executor.isShutdown()); + } + + assertTrue("Max threads was: "+maxThreads+" but bound was: "+maxSimultaneousTasks, maxThreads.get() <= maxSimultaneousTasks); + } + backendExecutor.shutdownNow(); + assertTrue(backendExecutor.awaitTermination(100, TimeUnit.SECONDS)); + } + + public void testSequentialSubmitsMustExecuteSequentially() throws ExecutionException, InterruptedException { + ExecutorService backendExecutor = Executors.newCachedThreadPool(ConcurrencyUtil.newNamedThreadFactory(getName())); + BoundedTaskExecutorService executor = new BoundedTaskExecutorService(backendExecutor, 1); + int N = 100000; + StringBuffer log = new StringBuffer(N*4); + StringBuffer expected = new StringBuffer(N*4); + + Future[] futures = new Future[N]; + for (int i = 0; i < N; i++) { + final int finalI = i; + futures[i] = executor.submit(() -> log.append(finalI).append(" ")); + } + for (int i = 0; i < N; i++) { + expected.append(i).append(" "); + futures[i].get(); + } + + String logs = log.toString(); + assertEquals(expected.toString(), logs); + executor.shutdownNow(); + assertTrue(executor.awaitTermination(1, TimeUnit.SECONDS)); + backendExecutor.shutdownNow(); + assertTrue(backendExecutor.awaitTermination(100, TimeUnit.SECONDS)); + } +} diff --git a/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java b/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java index 7e1c4372347d..167a607735f5 100644 --- a/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java +++ b/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -15,90 +15,180 @@ */ package com.intellij.util.concurrency; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; +import com.intellij.util.Function; +import com.intellij.util.ReflectionUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; -import java.util.Queue; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; -public class BoundedTaskExecutor implements Executor { - protected final Executor myBackendExecutor; +/** + * ExecutorService which limits the number of tasks running simultaneously. + * The number of submitted tasks is unrestricted. + */ +public class BoundedTaskExecutor extends AbstractExecutorService { + private volatile boolean myShutdown; + private final Executor myBackendExecutor; private final int myMaxTasks; - private final AtomicInteger myInProgress = new AtomicInteger(0); - private final Queue myTaskQueue = new LinkedBlockingQueue(); - - private final Runnable USER_TASK_RUNNER = new Runnable() { - @Override - public void run() { - final FutureTask task = myTaskQueue.poll(); - try { - if (task != null && !task.isCancelled()) { - task.run(); - } - } - finally { - myInProgress.decrementAndGet(); - if (!myTaskQueue.isEmpty()) { - processQueue(); - } - } - } - }; + // number of tasks running (or trying to run) + private final AtomicInteger myInProgress = new AtomicInteger(); + private final BlockingQueue myTaskQueue = new LinkedBlockingQueue(); public BoundedTaskExecutor(@NotNull Executor backendExecutor, int maxSimultaneousTasks) { myBackendExecutor = backendExecutor; - assert maxSimultaneousTasks >= 1 : maxSimultaneousTasks; - myMaxTasks = Math.max(maxSimultaneousTasks, 1); + if (maxSimultaneousTasks < 1) { + throw new IllegalArgumentException("maxSimultaneousTasks must be >=1 but got: "+maxSimultaneousTasks); + } + myMaxTasks = maxSimultaneousTasks; + } + + /** + * Constructor which automatically shuts down this executor when {@code parent} is disposed. + */ + public BoundedTaskExecutor(@NotNull Executor backendExecutor, int maxSimultaneousTasks, @NotNull Disposable parent) { + this(backendExecutor, maxSimultaneousTasks); + Disposer.register(parent, new Disposable() { + @Override + public void dispose() { + shutdownNow(); + } + }); + } + + // for diagnostics + public static Object info(Object task) { + if (task instanceof FutureTask) { + task = ReflectionUtil.getField(task.getClass(), task, Callable.class, "callable"); + } + if (task instanceof Callable && task.getClass().getName().equals("java.util.concurrent.Executors$RunnableAdapter")) { + task = ReflectionUtil.getField(task.getClass(), task, Runnable.class, "task"); + } + return task; + } + + @Override + public void shutdown() { + if (myShutdown) throw new IllegalStateException("Already shutdown"); + myShutdown = true; + } + + @NotNull + @Override + public List shutdownNow() { + shutdown(); + return clearAndCancelAll(); + } + + @Override + public boolean isShutdown() { + return myShutdown; + } + + @Override + public boolean isTerminated() { + return myShutdown; + } + + @Override + public boolean awaitTermination(long timeout, @NotNull TimeUnit unit) throws InterruptedException { + if (!isShutdown()) throw new IllegalStateException("you must call shutdown() first"); + return true; } @Override public void execute(@NotNull Runnable task) { - submit(task); + myTaskQueue.offer(task); + int inProgress = myInProgress.incrementAndGet(); + + tryToPollAndExecuteNext(inProgress); } - - public Future submit(@NotNull Runnable task) { - return this.submit(task, null); - } - - @NotNull - public Future submit(Runnable task, T result) { - final RunnableFuture future = queueTask(new FutureTask(task, result)); - if (future == null) { - throw new RuntimeException("Failed to queue task: " + task); - } - return future; - } - - @NotNull - public Future submit(@NotNull Callable task) { - final RunnableFuture future = queueTask(new FutureTask(task)); - if (future == null) { - throw new RuntimeException("Failed to queue task: " + task); - } - return future; - } - - @Nullable - private RunnableFuture queueTask(@NotNull FutureTask futureTask) { - if (myTaskQueue.offer(futureTask)) { - processQueue(); - return futureTask; - } - return null; - } - - protected void processQueue() { - while (true) { - final int count = myInProgress.get(); - if (count >= myMaxTasks) { - return; - } - if (myInProgress.compareAndSet(count, count + 1)) { + private void tryToPollAndExecuteNext(int inProgress) { + while (!isShutdown()) { + assert inProgress > 0 : inProgress; + Runnable next; + if (inProgress <= myMaxTasks && (next = myTaskQueue.poll()) != null) { + myBackendExecutor.execute(wrap(next)); break; } + if (myInProgress.compareAndSet(inProgress, inProgress-1)) { + break; + } + inProgress = myInProgress.get(); } - myBackendExecutor.execute(USER_TASK_RUNNER); + } + + @NotNull + private Runnable wrap(@NotNull final Runnable task) { + return new Runnable() { + @Override + public void run() { + try { + task.run(); + } + finally { + tryToPollAndExecuteNext(myInProgress.get()); + } + } + + @Override + public String toString() { + return String.valueOf(info(task)); + } + }; + } + + @TestOnly + public void waitAllTasksExecuted() throws ExecutionException, InterruptedException { + final CountDownLatch started = new CountDownLatch(myMaxTasks); + final CountDownLatch readyToFinish = new CountDownLatch(1); + // start myMaxTasks runnables which will spread to all available executor threads + // and wait for them all to finish + List futures = ContainerUtil.map(Collections.nCopies(myMaxTasks, null), new Function() { + @Override + public Future fun(Object o) { + return submit(new Runnable() { + @Override + public void run() { + try { + started.countDown(); + readyToFinish.await(); + } + catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + }); + } + }); + try { + started.await(); + } + catch (InterruptedException e) { + throw new RuntimeException(e); + } + readyToFinish.countDown(); + for (Future future : futures) { + future.get(); + } + } + + @NotNull + public List clearAndCancelAll() { + List queued = new ArrayList(); + myTaskQueue.drainTo(queued); + for (Runnable task : queued) { + if (task instanceof FutureTask) { + ((FutureTask) task).cancel(false); + } + } + return queued; } } diff --git a/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutorService.java b/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutorService.java index 7add9671d639..861cdaa83580 100644 --- a/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutorService.java +++ b/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutorService.java @@ -15,145 +15,20 @@ */ package com.intellij.util.concurrency; -import com.intellij.util.SmartList; +import com.intellij.openapi.Disposable; import org.jetbrains.annotations.NotNull; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.*; +import java.util.concurrent.ExecutorService; /** * @author Eugene Zhuravlev * Date: 16-Sep-15 */ -public class BoundedTaskExecutorService extends BoundedTaskExecutor implements ExecutorService{ - +public class BoundedTaskExecutorService extends BoundedTaskExecutor { public BoundedTaskExecutorService(@NotNull ExecutorService backendExecutor, int maxSimultaneousTasks) { super(backendExecutor, maxSimultaneousTasks); } - - @Override - public void shutdown() { - getBackendExecutor().shutdown(); + public BoundedTaskExecutorService(@NotNull ExecutorService backendExecutor, int maxSimultaneousTasks, @NotNull Disposable parent) { + super(backendExecutor, maxSimultaneousTasks, parent); } - - @NotNull - @Override - public List shutdownNow() { - return getBackendExecutor().shutdownNow(); - } - - @Override - public boolean isShutdown() { - return getBackendExecutor().isShutdown(); - } - - @Override - public boolean isTerminated() { - return getBackendExecutor().isTerminated(); - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { - return getBackendExecutor().awaitTermination(timeout, unit); - } - - @NotNull - @Override - public List> invokeAll(Collection> tasks) throws InterruptedException { - final List> futures = new SmartList>(); - for (Callable task : tasks) { - futures.add(submit(task)); - } - boolean done = false; - try { - for (Future future : futures) { - if (!future.isDone()) { - try { - future.get(); - } - catch (ExecutionException ignored) { - } - } - } - done = true; - return futures; - } - finally { - if (!done) { - for (Future future : futures) { - future.cancel(true); - } - } - } - } - - @NotNull - @Override - public List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException { - long nanos = unit.toNanos(timeout); - final List> futures = new SmartList>(); - - boolean done = false; - try { - long lastCheck = System.nanoTime(); - - for (Callable task : tasks) { - futures.add(submit(task)); - } - - long now = System.nanoTime(); - nanos -= now - lastCheck; - if (nanos <= 0) { - return futures; - } - lastCheck = now; - - for (Future future : futures) { - if (!future.isDone()) { - if (nanos <= 0) { - return futures; - } - try { - future.get(nanos, TimeUnit.NANOSECONDS); - } - catch (ExecutionException ignored) { - } - catch (TimeoutException e) { - return futures; - } - now = System.nanoTime(); - nanos -= now - lastCheck; - lastCheck = now; - } - } - done = true; - return futures; - } - finally { - if (!done) { - for (Future future : futures) { - future.cancel(true); - } - } - } - } - - @Override - public T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException { - throw new RuntimeException("invokeAny is not supported by this ExecutorService implementation"); - } - - - @Override - public T invokeAny(Collection> tasks, long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - throw new RuntimeException("invokeAny is not supported by this ExecutorService implementation"); - } - - @NotNull - private ExecutorService getBackendExecutor() { - return (ExecutorService)myBackendExecutor; - } - } From 978b5c8a887b10949d54c1055f3a5f9db2f8d072 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 8 Dec 2015 16:24:22 +0300 Subject: [PATCH 07/25] re-use app thread pool --- .../openapi/vfs/newvfs/RefreshQueueImpl.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java index 12765fedb7a7..bda8002b975c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -15,6 +15,7 @@ */ package com.intellij.openapi.vfs.newvfs; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; @@ -26,11 +27,12 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.vfs.VfsBundle; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; -import com.intellij.util.ConcurrencyUtil; +import com.intellij.util.concurrency.BoundedTaskExecutorService; import com.intellij.util.io.storage.HeavyProcessLatch; import gnu.trove.TLongObjectHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.ide.PooledThreadExecutor; import java.util.Collections; import java.util.concurrent.ExecutorService; @@ -38,10 +40,10 @@ import java.util.concurrent.ExecutorService; /** * @author max */ -public class RefreshQueueImpl extends RefreshQueue { +public class RefreshQueueImpl extends RefreshQueue implements Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.newvfs.RefreshQueueImpl"); - private final ExecutorService myQueue = ConcurrencyUtil.newSingleThreadExecutor("FS Synchronizer"); + private final ExecutorService myQueue = new BoundedTaskExecutorService(PooledThreadExecutor.INSTANCE, 1, this); private final ProgressIndicator myRefreshIndicator = RefreshProgress.create(VfsBundle.message("file.synchronize.progress")); private final TLongObjectHashMap mySessions = new TLongObjectHashMap(); private final FrequentEventDetector myEventCounter = new FrequentEventDetector(100, 100, FrequentEventDetector.Level.ERROR); @@ -149,4 +151,9 @@ public class RefreshQueueImpl extends RefreshQueue { return !refreshQueue.mySessions.isEmpty(); } } + + @Override + public void dispose() { + + } } \ No newline at end of file From 78e708ae8d2ebd744c9464323b7228147e209cb3 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 8 Dec 2015 16:30:04 +0300 Subject: [PATCH 08/25] re-use app thread pool --- .../vfs/encoding/EncodingManagerImpl.java | 62 +++++++++++-------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java index 78b297d68e57..f3b3af9d2fa4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java @@ -22,9 +22,9 @@ */ package com.intellij.openapi.vfs.encoding; +import com.intellij.concurrency.JobSchedulerImpl; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.impl.TransferToPooledThreadQueue; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; @@ -48,13 +48,14 @@ import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Alarm; import com.intellij.util.ObjectUtils; -import com.intellij.util.Processor; +import com.intellij.util.concurrency.BoundedTaskExecutorService; import com.intellij.util.xmlb.annotations.Attribute; import gnu.trove.Equality; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.ide.PooledThreadExecutor; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -99,19 +100,7 @@ public class EncodingManagerImpl extends EncodingManager implements PersistentSt private final Alarm updateEncodingFromContent = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, this); private static final Key CACHED_CHARSET_FROM_CONTENT = Key.create("CACHED_CHARSET_FROM_CONTENT"); - private final TransferToPooledThreadQueue> myChangedDocuments = new TransferToPooledThreadQueue>( - "Encoding detection thread", - ApplicationManager.getApplication().getDisposed(), - -1, // drain the whole queue, do not reschedule - new Processor>() { - @Override - public boolean process(Reference ref) { - Document document = ref.get(); - if (document == null) return true; // document gced, don't bother - handleDocument(document); - return true; - } - }); + private final BoundedTaskExecutorService changedDocumentExecutor = new BoundedTaskExecutorService(PooledThreadExecutor.INSTANCE, JobSchedulerImpl.CORES_COUNT, this); public EncodingManagerImpl(@NotNull EditorFactory editorFactory) { editorFactory.getEventMulticaster().addDocumentListener(new DocumentAdapter() { @@ -130,15 +119,22 @@ public class EncodingManagerImpl extends EncodingManager implements PersistentSt @NonNls public static final String PROP_CACHED_ENCODING_CHANGED = "cachedEncoding"; + private static final Key DETECTING_ENCODING_KEY = Key.create("DETECTING_ENCODING_KEY"); private void handleDocument(@NotNull final Document document) { - VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document); - if (virtualFile == null) return; - Project project = guessProject(virtualFile); - if (project != null && project.isDisposed()) return; - Charset charset = LoadTextUtil.charsetFromContentOrNull(project, virtualFile, document.getImmutableCharSequence()); - Charset oldCached = getCachedCharsetFromContent(document); - if (!Comparing.equal(charset, oldCached)) { - setCachedCharsetFromContent(charset, oldCached, document); + if (document.getUserData(DETECTING_ENCODING_KEY) == null) return; + try { + VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document); + if (virtualFile == null) return; + Project project = guessProject(virtualFile); + if (project != null && project.isDisposed()) return; + Charset charset = LoadTextUtil.charsetFromContentOrNull(project, virtualFile, document.getImmutableCharSequence()); + Charset oldCached = getCachedCharsetFromContent(document); + if (!Comparing.equal(charset, oldCached)) { + setCachedCharsetFromContent(charset, oldCached, document); + } + } + finally { + document.putUserData(DETECTING_ENCODING_KEY, null); } } @@ -178,7 +174,23 @@ public class EncodingManagerImpl extends EncodingManager implements PersistentSt } void queueUpdateEncodingFromContent(@NotNull Document document) { - myChangedDocuments.offerIfAbsent(new WeakReference(document), REFERENCE_EQUALITY); + document.putUserData(DETECTING_ENCODING_KEY, ""); + changedDocumentExecutor.execute(new DocumentEncodingDetectRequest(document)); + } + + private static class DocumentEncodingDetectRequest implements Runnable { + private final Reference ref; + + private DocumentEncodingDetectRequest(@NotNull Document document) { + ref = new WeakReference(document); + } + + @Override + public void run() { + Document document = ref.get(); + if (document == null) return; // document gced, don't bother + ((EncodingManagerImpl)getInstance()).handleDocument(document); + } } @Override @@ -220,7 +232,7 @@ public class EncodingManagerImpl extends EncodingManager implements PersistentSt } public void clearDocumentQueue() { - myChangedDocuments.stop(); + changedDocumentExecutor.clearAndCancelAll(); } @Nullable From d327fa9d828b93cdcd67ca081d9510d28491a8eb Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 8 Dec 2015 16:39:38 +0300 Subject: [PATCH 09/25] re-use app thread pool --- .../psi/impl/DocumentCommitThread.java | 79 ++++++++----------- 1 file changed, 31 insertions(+), 48 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java index 7ad7f86f4d48..a20e1d29b889 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java +++ b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java @@ -15,6 +15,7 @@ */ package com.intellij.psi.impl; +import com.intellij.concurrency.JobSchedulerImpl; import com.intellij.diagnostic.ThreadDumper; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationAdapter; @@ -35,28 +36,33 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.util.Processor; import com.intellij.util.SmartList; +import com.intellij.util.concurrency.BoundedTaskExecutorService; import com.intellij.util.containers.Queue; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; +import org.jetbrains.ide.PooledThreadExecutor; import javax.swing.*; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; public class DocumentCommitThread extends DocumentCommitProcessor implements Runnable, Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.DocumentCommitThread"); private static final String NAME = "Document commit thread"; + private final ExecutorService executor = new BoundedTaskExecutorService(PooledThreadExecutor.INSTANCE, JobSchedulerImpl.CORES_COUNT, this); + private final Queue documentsToCommit = new Queue(10); private final List documentsToApplyInEDT = new ArrayList(10); // guarded by documentsToCommit private final ApplicationEx myApplication; private volatile boolean isDisposed; private CommitTask currentTask; // guarded by documentsToCommit - private volatile boolean threadFinished; private volatile boolean myEnabled; // true if we can do commits. set to false temporarily during the write action. private int runningWriteActions; // accessed in EDT only @@ -108,9 +114,6 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run } }); log("Starting thread", null, false); - Thread thread = new Thread(this, NAME); - thread.setDaemon(true); - thread.start(); } @Override @@ -120,17 +123,6 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run documentsToCommit.clear(); } cancel("Stop thread"); - wakeUpQueue(); - while (!threadFinished) { - wakeUpQueue(); - synchronized (documentsToCommit) { - try { - documentsToCommit.wait(10); - } - catch (InterruptedException ignored) { - } - } - } } private void disable(@NonNls Object reason) { @@ -146,10 +138,8 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run log("Enabled", null, false, reason); } - private void wakeUpQueue() { - synchronized (documentsToCommit) { - documentsToCommit.notifyAll(); - } + private Future wakeUpQueue() { + return executor.submit(this); } private void cancel(@NonNls @NotNull Object reason) { @@ -220,8 +210,14 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run s += "; Uncommitted: " + task.document; } } + synchronized (documentsToCommit) { + int size = documentsToCommit.size(); + if (size != 0) { + s += " (" + size + " documents are still in queue)"; + } + } -// System.err.println(s); + //System.out.println(s); synchronized (log) { log.append(s).append("\n"); @@ -291,26 +287,19 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run @Override public void run() { - threadFinished = false; - try { - while (!isDisposed) { - try { - pollQueue(); - } - catch(Throwable e) { - LOG.error(e); - } + while (!isDisposed) { + try { + boolean polled = pollQueue(); + if (!polled) break; + } + catch(Throwable e) { + LOG.error(e); } } - finally { - threadFinished = true; - } - // ping the thread waiting for close - wakeUpQueue(); - log("Good bye", null, false); } - private void pollQueue() { + // returns true if queue changed + private boolean pollQueue() { boolean success = false; Document document = null; Project project = null; @@ -319,8 +308,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run ProgressIndicator indicator; synchronized (documentsToCommit) { if (!myEnabled || documentsToCommit.isEmpty()) { - documentsToCommit.wait(1000); - return; + return false; } task = documentsToCommit.pullFirst(); document = task.document; @@ -331,11 +319,11 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run if (project.isDisposed() || !((PsiDocumentManagerBase)PsiDocumentManager.getInstance(project)).isInUncommittedSet(document)) { log("Abandon and proceed to next",task, false); - return; + return true; } if (task.removed) { - return; // document has been marked as removed, e.g. by synchronous commit + return true; // document has been marked as removed, e.g. by synchronous commit } startNewTask(task, "Pulled new task"); @@ -373,11 +361,6 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run log("PCE", task, false, e); success = false; } - catch (InterruptedException e) { - // app must be closing - log("IE", task, false, e); - cancel(e); - } catch (Throwable e) { LOG.error(e); cancel(e); @@ -389,6 +372,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run } currentTask = null; // do not cancel, it's being invokeLatered } + return true; } @Override @@ -491,7 +475,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run return null; } - Runnable finishRunnable = new Runnable() { + return new Runnable() { @Override public void run() { myApplication.assertIsDispatchThread(); @@ -539,7 +523,6 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run } } }; - return finishRunnable; } @NotNull @@ -584,6 +567,6 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run @Override public String toString() { - return "Document commit thread; application: "+myApplication+"; isDisposed: "+isDisposed+"; threadFinished: "+threadFinished+"; myEnabled: "+myEnabled+"; runningWriteActions: "+runningWriteActions; + return "Document commit thread; application: "+myApplication+"; isDisposed: "+isDisposed+"; myEnabled: "+myEnabled+"; runningWriteActions: "+runningWriteActions; } } From ab40b48ddd2de4cc6055c1adfbfa154f567e91e0 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 8 Dec 2015 16:40:11 +0300 Subject: [PATCH 10/25] re-use app thread pool --- .../fileTypes/impl/FileTypeManagerImpl.java | 45 ++++++++++++++----- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java index 612cb57f74fc..b0d975512276 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java @@ -21,7 +21,6 @@ import com.intellij.ide.plugins.PluginManager; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.impl.TransferToPooledThreadQueue; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.State; @@ -51,6 +50,7 @@ import com.intellij.openapi.vfs.newvfs.impl.StubVirtualFile; import com.intellij.psi.SingleRootFileViewProvider; import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.*; +import com.intellij.util.concurrency.BoundedTaskExecutorService; import com.intellij.util.containers.ConcurrentPackedBitsArray; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.URLUtil; @@ -63,12 +63,15 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; +import org.jetbrains.ide.PooledThreadExecutor; import java.io.*; import java.net.URL; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.util.*; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -245,7 +248,10 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent if (toLog()) { log("F: after() queued to redetect: " + files); } - reDetectQueue.offerIfAbsent(files); + + if (filesToRedetect.addAll(files)) { + awakeReDetectExecutor(); + } } } }); @@ -340,23 +346,38 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent System.out.println(message + " - "+Thread.currentThread()); } - private final TransferToPooledThreadQueue> reDetectQueue = new TransferToPooledThreadQueue>("File type re-detect", Conditions.alwaysFalse(), -1, new Processor>() { - @Override - public boolean process(Collection files) { - reDetect(files); - return true; - } - }); + private final BoundedTaskExecutorService reDetectExecutor = new BoundedTaskExecutorService(PooledThreadExecutor.INSTANCE, 1, this); + private final BlockingQueue filesToRedetect = new LinkedBlockingDeque(); + + private void awakeReDetectExecutor() { + reDetectExecutor.submit(new Runnable() { + private static final int CHUNK = 10; + @Override + public void run() { + List files = new ArrayList(); + int drained = filesToRedetect.drainTo(files, CHUNK); + reDetect(files); + if (drained == CHUNK) { + awakeReDetectExecutor(); + } + } + }); + } @TestOnly public void drainReDetectQueue() { - reDetectQueue.waitFor(); + try { + reDetectExecutor.waitAllTasksExecuted(); + } + catch (Exception e) { + throw new RuntimeException(e); + } } @TestOnly @NotNull Collection dumpReDetectQueue() { - return ContainerUtil.flatten(reDetectQueue.dump()); + return new ArrayList(filesToRedetect); } @TestOnly @@ -603,6 +624,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent private volatile FileAttribute autoDetectedAttribute; // read auto-detection flags from the persistent FS file attributes. If file attributes are absent, return 0 for flags // returns three bits value for AUTO_DETECTED_AS_TEXT_MASK, AUTO_DETECTED_AS_BINARY_MASK and AUTO_DETECT_WAS_RUN_MASK bits + // protected for Upsource protected byte readFlagsFromCache(@NotNull VirtualFile file) { DataInputStream stream = autoDetectedAttribute.readAttribute(file); boolean wasAutoDetectRun = false; @@ -627,6 +649,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent // store auto-detection flags to the persistent FS file attributes // writes AUTO_DETECTED_AS_TEXT_MASK, AUTO_DETECTED_AS_BINARY_MASK bits only + // protected for Upsource protected void writeFlagsToCache(@NotNull VirtualFile file, int flags) { DataOutputStream stream = autoDetectedAttribute.writeAttribute(file); try { From 42f36cdb878c4d9884e888430b6a972b8f5ef234 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Tue, 8 Dec 2015 17:26:30 +0300 Subject: [PATCH 11/25] IDEA-141867 Form snapshot NullpointerException --- .../com/intellij/uiDesigner/radComponents/RadContainer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/radComponents/RadContainer.java b/plugins/ui-designer/src/com/intellij/uiDesigner/radComponents/RadContainer.java index 78e386ce49b1..869491d5f352 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/radComponents/RadContainer.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/radComponents/RadContainer.java @@ -653,7 +653,9 @@ public class RadContainer extends RadComponent implements IContainer { setBorderTitleJustification(titledBorder.getTitleJustification()); setBorderTitlePosition(titledBorder.getTitlePosition()); final Font titleFont = titledBorder.getTitleFont(); - setBorderTitleFont(new FontDescriptor(titleFont.getName(), titleFont.getStyle(), titleFont.getSize())); + if (titleFont != null) { + setBorderTitleFont(new FontDescriptor(titleFont.getName(), titleFont.getStyle(), titleFont.getSize())); + } setBorderTitleColor(new ColorDescriptor(titledBorder.getTitleColor())); border = titledBorder.getBorder(); } From f571cc3e5bf0a3ecbe4925907cf8a751296d1041 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 8 Dec 2015 17:30:36 +0300 Subject: [PATCH 12/25] moved to core-impl --- .../src/com/intellij/concurrency/JobSchedulerImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename platform/{platform-impl => core-impl}/src/com/intellij/concurrency/JobSchedulerImpl.java (88%) diff --git a/platform/platform-impl/src/com/intellij/concurrency/JobSchedulerImpl.java b/platform/core-impl/src/com/intellij/concurrency/JobSchedulerImpl.java similarity index 88% rename from platform/platform-impl/src/com/intellij/concurrency/JobSchedulerImpl.java rename to platform/core-impl/src/com/intellij/concurrency/JobSchedulerImpl.java index 7b252e9c16d0..4620657262bd 100644 --- a/platform/platform-impl/src/com/intellij/concurrency/JobSchedulerImpl.java +++ b/platform/core-impl/src/com/intellij/concurrency/JobSchedulerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,6 +19,6 @@ */ package com.intellij.concurrency; -public abstract class JobSchedulerImpl { +public class JobSchedulerImpl extends JobScheduler { public static final int CORES_COUNT = Runtime.getRuntime().availableProcessors(); } From ec1141bfb4c89010e514b1e1882307aebe5fbc08 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Tue, 8 Dec 2015 15:50:55 +0300 Subject: [PATCH 13/25] external system: expose ide module file directory path --- .../openapi/externalSystem/model/project/ModuleData.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ModuleData.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ModuleData.java index 8bb80bdb3037..0dd514a23718 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ModuleData.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ModuleData.java @@ -88,6 +88,11 @@ public class ModuleData extends AbstractNamedData implements Named, ExternalConf .toCanonicalPath(myModuleFileDirectoryPath + "/" + getInternalName() + ModuleFileType.DOT_DEFAULT_EXTENSION); } + @NotNull + public String getModuleFileDirectoryPath() { + return myModuleFileDirectoryPath; + } + public void setModuleFileDirectoryPath(@NotNull String path) { myModuleFileDirectoryPath = path; } From 69ae24d95d665a46fe320188fb4b508cdd7f0da3 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Tue, 8 Dec 2015 16:07:57 +0300 Subject: [PATCH 14/25] gradle: main module creation extracted; ProjectResolverContext can be used to store intermediate user data, e.g. for caching; --- .../BaseGradleProjectResolverExtension.java | 110 ++----------- .../DefaultProjectResolverContext.java | 150 ++++++++++++++++++ .../project/GradleProjectResolver.java | 56 +++---- .../project/GradleProjectResolverUtil.java | 105 ++++++++++++ .../project/ProjectResolverContext.java | 91 +++-------- .../plugins/gradle/model/ModelsHolder.java | 9 +- 6 files changed, 314 insertions(+), 207 deletions(-) create mode 100644 plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/DefaultProjectResolverContext.java diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java index 1d5e3270c647..4755463f1c8a 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java @@ -28,7 +28,6 @@ import com.intellij.openapi.externalSystem.model.ProjectKeys; import com.intellij.openapi.externalSystem.model.project.*; import com.intellij.openapi.externalSystem.model.task.TaskData; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; -import com.intellij.openapi.externalSystem.util.ExternalSystemDebugEnvironment; import com.intellij.openapi.externalSystem.util.Order; import com.intellij.openapi.module.EmptyModuleType; import com.intellij.openapi.module.JavaModuleType; @@ -47,7 +46,6 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.net.HttpConfigurable; import com.intellij.util.text.CharArrayUtil; -import gnu.trove.TObjectHashingStrategy; import groovy.lang.GroovyObject; import org.codehaus.groovy.runtime.typehandling.ShortTypeHandling; import org.gradle.tooling.ProjectConnection; @@ -55,14 +53,11 @@ import org.gradle.tooling.model.DomainObjectSet; import org.gradle.tooling.model.GradleModuleVersion; import org.gradle.tooling.model.GradleTask; import org.gradle.tooling.model.UnsupportedMethodException; -import org.gradle.tooling.model.gradle.BasicGradleProject; import org.gradle.tooling.model.gradle.GradleBuild; import org.gradle.tooling.model.idea.*; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.gradle.DefaultExternalDependencyId; -import org.jetbrains.plugins.gradle.ExternalDependencyId; import org.jetbrains.plugins.gradle.model.*; import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData; import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData; @@ -71,11 +66,9 @@ import org.jetbrains.plugins.gradle.tooling.builder.ModelBuildScriptClasspathBui import org.jetbrains.plugins.gradle.tooling.internal.init.Init; import org.jetbrains.plugins.gradle.util.GradleBundle; import org.jetbrains.plugins.gradle.util.GradleConstants; -import org.jetbrains.plugins.gradle.util.GradleUtil; import org.slf4j.impl.Log4jLoggerFactory; import java.io.File; -import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Proxy; @@ -94,7 +87,7 @@ import static org.jetbrains.plugins.gradle.service.project.GradleProjectResolver */ @Order(Integer.MAX_VALUE) public class BaseGradleProjectResolverExtension implements GradleProjectResolverExtension { - private static final Logger LOG = Logger.getInstance("#" + BaseGradleProjectResolverExtension.class.getName()); + private static final Logger LOG = Logger.getInstance(BaseGradleProjectResolverExtension.class); @NotNull @NonNls private static final String UNRESOLVED_DEPENDENCY_PREFIX = "unresolved dependency - "; @@ -164,47 +157,16 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver @NotNull @Override public DataNode createModule(@NotNull IdeaModule gradleModule, @NotNull DataNode projectDataNode) { - final String moduleName = gradleModule.getName(); - if (moduleName == null) { - throw new IllegalStateException("Module with undefined name detected: " + gradleModule); - } - - final ProjectData projectData = projectDataNode.getData(); - final String mainModuleConfigPath = getModuleConfigPath(gradleModule, projectData.getLinkedExternalProjectPath()); - final String ideProjectPath = resolverCtx.getIdeProjectPath(); - final String relativePath; - if (FileUtil.isAncestor(projectData.getLinkedExternalProjectPath(), mainModuleConfigPath, false)) { - relativePath = FileUtil.getRelativePath(projectData.getLinkedExternalProjectPath(), mainModuleConfigPath, '/'); - } - else { - relativePath = String.valueOf(FileUtil.pathHashCode(mainModuleConfigPath)); - } - final String mainModuleFileDirectoryPath = - ideProjectPath == null ? mainModuleConfigPath : ideProjectPath + "/.idea/modules/" + - (relativePath == null || relativePath.equals(".") ? "" : relativePath); - if (ExternalSystemDebugEnvironment.DEBUG_ORPHAN_MODULES_PROCESSING) { - LOG.info(String.format( - "Creating module data ('%s') with the external config path: '%s'", gradleModule.getGradleProject().getPath(), mainModuleConfigPath - )); - } - - String gradlePath = gradleModule.getGradleProject().getPath(); - final boolean isRootModule = StringUtil.isEmpty(gradlePath) || ":".equals(gradlePath); - String mainModuleId = isRootModule ? moduleName : gradlePath; - final ModuleData moduleData = - new ModuleData(mainModuleId, GradleConstants.SYSTEM_ID, StdModuleTypes.JAVA.getId(), moduleName, - mainModuleFileDirectoryPath, mainModuleConfigPath); - DataNode mainModuleNode = projectDataNode.createChild(ProjectKeys.MODULE, moduleData); + DataNode mainModuleNode = createMainModule(resolverCtx, gradleModule, projectDataNode); + final ModuleData mainModuleData = mainModuleNode.getData(); + final String mainModuleConfigPath = mainModuleData.getLinkedExternalProjectPath(); + final String mainModuleFileDirectoryPath = mainModuleData.getModuleFileDirectoryPath(); ExternalProject externalProject = resolverCtx.getExtraProject(gradleModule, ExternalProject.class); if (externalProject != null) { - final String[] moduleGroup = externalProject.getSourceSets().isEmpty() ? null : new String[]{moduleData.getInternalName() + " modules"}; - moduleData.setIdeModuleGroup(moduleGroup); - - moduleData.setGroup(externalProject.getGroup()); - moduleData.setVersion(externalProject.getVersion()); - moduleData.setDescription(externalProject.getDescription()); - moduleData.setArtifacts(externalProject.getArtifacts()); + final String[] moduleGroup = + externalProject.getSourceSets().isEmpty() ? null : new String[]{mainModuleData.getInternalName() + " modules"}; + mainModuleData.setIdeModuleGroup(moduleGroup); for (ExternalSourceSet sourceSet : externalProject.getSourceSets().values()) { final String moduleId = getModuleId(externalProject, sourceSet); @@ -247,9 +209,10 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver } } - if (StringUtil.equals(moduleData.getLinkedExternalProjectPath(), projectData.getLinkedExternalProjectPath())) { - projectData.setGroup(moduleData.getGroup()); - projectData.setVersion(moduleData.getVersion()); + final ProjectData projectData = projectDataNode.getData(); + if (StringUtil.equals(mainModuleData.getLinkedExternalProjectPath(), projectData.getLinkedExternalProjectPath())) { + projectData.setGroup(mainModuleData.getGroup()); + projectData.setVersion(mainModuleData.getVersion()); } return mainModuleNode; @@ -648,55 +611,6 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver public void enhanceLocalProcessing(@NotNull List urls) { } - @NotNull - private String getModuleConfigPath(@NotNull IdeaModule gradleModule, @NotNull String rootProjectPath) { - GradleBuild build = resolverCtx.getExtraProject(gradleModule, GradleBuild.class); - if (build != null) { - String gradlePath = gradleModule.getGradleProject().getPath(); - File moduleDirPath = getModuleDirPath(build, gradlePath); - if (moduleDirPath == null) { - throw new IllegalStateException(String.format("Unable to find root directory for module '%s'", gradleModule.getName())); - } - try { - return ExternalSystemApiUtil.toCanonicalPath(moduleDirPath.getCanonicalPath()); - } - catch (IOException e) { - LOG.warn("construction of the canonical path for the module fails", e); - } - } - - return GradleUtil.getConfigPath(gradleModule.getGradleProject(), rootProjectPath); - } - - /** - * Returns the physical path of the module's root directory (the path in the file system.) - *

- * It is important to note that Gradle has its own "logical" path that may or may not be equal to the physical path of a Gradle project. - * For example, the sub-project at ${projectRootDir}/apps/app will have the Gradle path :apps:app. Gradle also allows mapping physical - * paths to a different logical path. For example, in settings.gradle: - *

-   *   include ':app'
-   *   project(':app').projectDir = new File(rootDir, 'apps/app')
-   * 
- * In this example, sub-project at ${projectRootDir}/apps/app will have the Gradle path :app. - *

- * - * @param build contains information about the root Gradle project and its sub-projects. Such information includes the physical path of - * the root Gradle project and its sub-projects. - * @param path the Gradle "logical" path. This path uses colon as separator, and may or may not be equal to the physical path of a - * Gradle project. - * @return the physical path of the module's root directory. - */ - @Nullable - static File getModuleDirPath(@NotNull GradleBuild build, @NotNull String path) { - for (BasicGradleProject project : build.getProjects()) { - if (project.getPath().equals(path)) { - return project.getProjectDirectory(); - } - } - return null; - } - /** * Stores information about given directories at the given content root * diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/DefaultProjectResolverContext.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/DefaultProjectResolverContext.java new file mode 100644 index 000000000000..ffdab0cad888 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/DefaultProjectResolverContext.java @@ -0,0 +1,150 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.gradle.service.project; + +import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId; +import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener; +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.util.UserDataHolderBase; +import org.gradle.tooling.CancellationTokenSource; +import org.gradle.tooling.ProjectConnection; +import org.gradle.tooling.model.idea.IdeaModule; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.gradle.model.ProjectImportAction; +import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings; + +import java.util.Collection; + +/** + * @author Vladislav.Soroka + * @since 12/8/2015 + */ +public class DefaultProjectResolverContext extends UserDataHolderBase implements ProjectResolverContext { + @NotNull private final ExternalSystemTaskId myExternalSystemTaskId; + @NotNull private final String myProjectPath; + @Nullable private final GradleExecutionSettings mySettings; + @NotNull private final ExternalSystemTaskNotificationListener myListener; + private ProjectConnection myConnection; + @Nullable private CancellationTokenSource myCancellationTokenSource; + private final boolean myIsPreviewMode; + @NotNull + private ProjectImportAction.AllModels myModels; + + public DefaultProjectResolverContext(@NotNull final ExternalSystemTaskId externalSystemTaskId, + @NotNull final String projectPath, + @Nullable final GradleExecutionSettings settings, + @NotNull final ExternalSystemTaskNotificationListener listener, + final boolean isPreviewMode) { + this(externalSystemTaskId, projectPath, settings, null, listener, isPreviewMode); + } + + + public DefaultProjectResolverContext(@NotNull final ExternalSystemTaskId externalSystemTaskId, + @NotNull final String projectPath, + @Nullable final GradleExecutionSettings settings, + final ProjectConnection connection, + @NotNull final ExternalSystemTaskNotificationListener listener, + final boolean isPreviewMode) { + myExternalSystemTaskId = externalSystemTaskId; + myProjectPath = projectPath; + mySettings = settings; + myConnection = connection; + myListener = listener; + myIsPreviewMode = isPreviewMode; + } + + @NotNull + public ExternalSystemTaskId getExternalSystemTaskId() { + return myExternalSystemTaskId; + } + + @Nullable + public String getIdeProjectPath() { + return mySettings != null ? mySettings.getIdeProjectPath() : null; + } + + @NotNull + public String getProjectPath() { + return myProjectPath; + } + + @Nullable + public GradleExecutionSettings getSettings() { + return mySettings; + } + + @NotNull + public ProjectConnection getConnection() { + return myConnection; + } + + public void setConnection(@NotNull ProjectConnection connection) { + myConnection = connection; + } + + @Nullable + public CancellationTokenSource getCancellationTokenSource() { + return myCancellationTokenSource; + } + + public void setCancellationTokenSource(@Nullable CancellationTokenSource cancellationTokenSource) { + myCancellationTokenSource = cancellationTokenSource; + } + + @NotNull + public ExternalSystemTaskNotificationListener getListener() { + return myListener; + } + + public boolean isPreviewMode() { + return myIsPreviewMode; + } + + @NotNull + public ProjectImportAction.AllModels getModels() { + return myModels; + } + + public void setModels(@NotNull ProjectImportAction.AllModels models) { + myModels = models; + } + + @Nullable + public T getExtraProject(Class modelClazz) { + return myModels.getExtraProject(null, modelClazz); + } + + @Nullable + public T getExtraProject(@Nullable IdeaModule module, Class modelClazz) { + return myModels.getExtraProject(module, modelClazz); + } + + @NotNull + public Collection findModulesWithModel(@NotNull Class modelClazz) { + return myModels.findModulesWithModel(modelClazz); + } + + public boolean hasModulesWithModel(@NotNull Class modelClazz) { + return myModels.hasModulesWithModel(modelClazz); + } + + public void checkCancelled() { + if (myCancellationTokenSource != null && myCancellationTokenSource.token().isCancellationRequested()) { + throw new ProcessCanceledException(); + } + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java index 5f7cf97109d6..f10eb2a2eedb 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java @@ -105,18 +105,17 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver resultProjectDataNode = myHelper.execute( - projectPath, settings, - new ProjectConnectionDataNodeFunction( - id, projectPath, settings, listener, isPreviewMode, projectResolverChain, false) + projectPath, settings, new ProjectConnectionDataNodeFunction(resolverContext, projectResolverChain, false) ); // auto-discover buildSrc project if needed final String buildSrcProjectPath = projectPath + "/buildSrc"; - handleBuildSrcProject( - resultProjectDataNode, - new ProjectConnectionDataNodeFunction(id, buildSrcProjectPath, settings, listener, isPreviewMode, projectResolverChain, true) - ); + DefaultProjectResolverContext buildSrcResolverCtx = + new DefaultProjectResolverContext(id, buildSrcProjectPath, settings, listener, isPreviewMode); + resolverContext.copyUserDataTo(buildSrcResolverCtx); + handleBuildSrcProject(resultProjectDataNode, new ProjectConnectionDataNodeFunction(buildSrcResolverCtx, projectResolverChain, true)); return resultProjectDataNode; } @@ -131,7 +130,7 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver doResolveProjectInfo(@NotNull final ProjectResolverContext resolverCtx, + private DataNode doResolveProjectInfo(@NotNull final DefaultProjectResolverContext resolverCtx, @NotNull final GradleProjectResolverExtension projectResolverChain, boolean isBuildSrcProject) throws IllegalArgumentException, IllegalStateException { @@ -200,6 +199,7 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver resultProjectDataNode, @NotNull final ProjectConnectionDataNodeFunction projectConnectionDataNodeFunction) { - if (!new File(projectConnectionDataNodeFunction.myProjectPath).isDirectory()) { + final String projectPath = projectConnectionDataNodeFunction.myResolverContext.getProjectPath(); + if (!new File(projectPath).isDirectory()) { return; } - if (projectConnectionDataNodeFunction.myIsPreviewMode) { + if (projectConnectionDataNodeFunction.myResolverContext.isPreviewMode()) { ModuleData buildSrcModuleData = - new ModuleData(":buildSrc", GradleConstants.SYSTEM_ID, StdModuleTypes.JAVA.getId(), "buildSrc", - projectConnectionDataNodeFunction.myProjectPath, projectConnectionDataNodeFunction.myProjectPath); + new ModuleData(":buildSrc", GradleConstants.SYSTEM_ID, StdModuleTypes.JAVA.getId(), "buildSrc", projectPath, projectPath); resultProjectDataNode.createChild(ProjectKeys.MODULE, buildSrcModuleData); return; } final DataNode buildSrcModuleDataNode = - GradleProjectResolverUtil.findModule(resultProjectDataNode, projectConnectionDataNodeFunction.myProjectPath); + GradleProjectResolverUtil.findModule(resultProjectDataNode, projectPath); // check if buildSrc project was already exposed in settings.gradle file if (buildSrcModuleDataNode != null) return; final DataNode buildSrcProjectDataDataNode = myHelper.execute( - projectConnectionDataNodeFunction.myProjectPath, projectConnectionDataNodeFunction.mySettings, projectConnectionDataNodeFunction); + projectPath, projectConnectionDataNodeFunction.myResolverContext.getSettings(), projectConnectionDataNodeFunction); if (buildSrcProjectDataDataNode != null) { for (DataNode moduleNode : ExternalSystemApiUtil.getChildren(buildSrcProjectDataDataNode, ProjectKeys.MODULE)) { @@ -658,26 +658,13 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver> { - @NotNull private final ExternalSystemTaskId myId; - @NotNull private final String myProjectPath; - @Nullable private final GradleExecutionSettings mySettings; - @NotNull private final ExternalSystemTaskNotificationListener myListener; - private final boolean myIsPreviewMode; @NotNull private final GradleProjectResolverExtension myProjectResolverChain; private final boolean myIsBuildSrcProject; + private DefaultProjectResolverContext myResolverContext; - public ProjectConnectionDataNodeFunction(@NotNull ExternalSystemTaskId id, - @NotNull String projectPath, - @Nullable GradleExecutionSettings settings, - @NotNull ExternalSystemTaskNotificationListener listener, - boolean isPreviewMode, - @NotNull GradleProjectResolverExtension projectResolverChain, - boolean isBuildSrcProject) { - myId = id; - myProjectPath = projectPath; - mySettings = settings; - myListener = listener; - myIsPreviewMode = isPreviewMode; + public ProjectConnectionDataNodeFunction(@NotNull DefaultProjectResolverContext resolverContext, + @NotNull GradleProjectResolverExtension projectResolverChain, boolean isBuildSrcProject) { + myResolverContext = resolverContext; myProjectResolverChain = projectResolverChain; myIsBuildSrcProject = isBuildSrcProject; } @@ -685,13 +672,12 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver fun(ProjectConnection connection) { try { - return doResolveProjectInfo( - new ProjectResolverContext(myId, myProjectPath, mySettings, connection, myListener, myIsPreviewMode), - myProjectResolverChain, myIsBuildSrcProject); + myResolverContext.setConnection(connection); + return doResolveProjectInfo(myResolverContext, myProjectResolverChain, myIsBuildSrcProject); } catch (RuntimeException e) { LOG.info("Gradle project resolve error", e); - throw myProjectResolverChain.getUserFriendlyError(e, myProjectPath, null); + throw myProjectResolverChain.getUserFriendlyError(e, myResolverContext.getProjectPath(), null); } } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverUtil.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverUtil.java index c53def95c073..3b0188a3fea7 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverUtil.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverUtil.java @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.gradle.service.project; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.externalSystem.model.DataNode; import com.intellij.openapi.externalSystem.model.Key; import com.intellij.openapi.externalSystem.model.ProjectKeys; @@ -22,6 +23,8 @@ import com.intellij.openapi.externalSystem.model.project.*; import com.intellij.openapi.externalSystem.model.task.TaskData; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemConstants; +import com.intellij.openapi.externalSystem.util.ExternalSystemDebugEnvironment; +import com.intellij.openapi.module.StdModuleTypes; import com.intellij.openapi.roots.DependencyScope; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; @@ -30,6 +33,8 @@ import com.intellij.util.BooleanFunction; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.gradle.tooling.model.GradleProject; +import org.gradle.tooling.model.gradle.BasicGradleProject; +import org.gradle.tooling.model.gradle.GradleBuild; import org.gradle.tooling.model.idea.IdeaModule; import org.gradle.util.GradleVersion; import org.jetbrains.annotations.NotNull; @@ -39,8 +44,10 @@ import org.jetbrains.plugins.gradle.ExternalDependencyId; import org.jetbrains.plugins.gradle.model.*; import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData; import org.jetbrains.plugins.gradle.util.GradleConstants; +import org.jetbrains.plugins.gradle.util.GradleUtil; import java.io.File; +import java.io.IOException; import java.util.Collection; import java.util.Map; import java.util.Queue; @@ -50,9 +57,107 @@ import java.util.Queue; * @since 10/6/2015 */ public class GradleProjectResolverUtil { + private static final Logger LOG = Logger.getInstance(GradleProjectResolverUtil.class); @NotNull private static final Key CONTAINER_KEY = Key.create(Object.class, ExternalSystemConstants.UNORDERED); + @NotNull + public static DataNode createMainModule(@NotNull ProjectResolverContext resolverCtx, + @NotNull IdeaModule gradleModule, + @NotNull DataNode projectDataNode) { + final String moduleName = gradleModule.getName(); + if (moduleName == null) { + throw new IllegalStateException("Module with undefined name detected: " + gradleModule); + } + + final ProjectData projectData = projectDataNode.getData(); + final String mainModuleConfigPath = getModuleConfigPath(resolverCtx, gradleModule, projectData.getLinkedExternalProjectPath()); + final String ideProjectPath = resolverCtx.getIdeProjectPath(); + final String relativePath; + if (FileUtil.isAncestor(projectData.getLinkedExternalProjectPath(), mainModuleConfigPath, false)) { + relativePath = FileUtil.getRelativePath(projectData.getLinkedExternalProjectPath(), mainModuleConfigPath, '/'); + } + else { + relativePath = String.valueOf(FileUtil.pathHashCode(mainModuleConfigPath)); + } + final String mainModuleFileDirectoryPath = + ideProjectPath == null ? mainModuleConfigPath : ideProjectPath + "/.idea/modules/" + + (relativePath == null || relativePath.equals(".") ? "" : relativePath); + if (ExternalSystemDebugEnvironment.DEBUG_ORPHAN_MODULES_PROCESSING) { + LOG.info(String.format( + "Creating module data ('%s') with the external config path: '%s'", gradleModule.getGradleProject().getPath(), mainModuleConfigPath + )); + } + + String gradlePath = gradleModule.getGradleProject().getPath(); + final boolean isRootModule = StringUtil.isEmpty(gradlePath) || ":".equals(gradlePath); + String mainModuleId = isRootModule ? moduleName : gradlePath; + final ModuleData moduleData = + new ModuleData(mainModuleId, GradleConstants.SYSTEM_ID, StdModuleTypes.JAVA.getId(), moduleName, + mainModuleFileDirectoryPath, mainModuleConfigPath); + + ExternalProject externalProject = resolverCtx.getExtraProject(gradleModule, ExternalProject.class); + if (externalProject != null) { + moduleData.setGroup(externalProject.getGroup()); + moduleData.setVersion(externalProject.getVersion()); + moduleData.setDescription(externalProject.getDescription()); + moduleData.setArtifacts(externalProject.getArtifacts()); + } + + return projectDataNode.createChild(ProjectKeys.MODULE, moduleData); + } + + @NotNull + public static String getModuleConfigPath(@NotNull ProjectResolverContext resolverCtx, + @NotNull IdeaModule gradleModule, + @NotNull String rootProjectPath) { + GradleBuild build = resolverCtx.getExtraProject(gradleModule, GradleBuild.class); + if (build != null) { + String gradlePath = gradleModule.getGradleProject().getPath(); + File moduleDirPath = getModuleDirPath(build, gradlePath); + if (moduleDirPath == null) { + throw new IllegalStateException(String.format("Unable to find root directory for module '%s'", gradleModule.getName())); + } + try { + return ExternalSystemApiUtil.toCanonicalPath(moduleDirPath.getCanonicalPath()); + } + catch (IOException e) { + LOG.warn("construction of the canonical path for the module fails", e); + } + } + + return GradleUtil.getConfigPath(gradleModule.getGradleProject(), rootProjectPath); + } + + /** + * Returns the physical path of the module's root directory (the path in the file system.) + *

+ * It is important to note that Gradle has its own "logical" path that may or may not be equal to the physical path of a Gradle project. + * For example, the sub-project at ${projectRootDir}/apps/app will have the Gradle path :apps:app. Gradle also allows mapping physical + * paths to a different logical path. For example, in settings.gradle: + *

+   *   include ':app'
+   *   project(':app').projectDir = new File(rootDir, 'apps/app')
+   * 
+ * In this example, sub-project at ${projectRootDir}/apps/app will have the Gradle path :app. + *

+ * + * @param build contains information about the root Gradle project and its sub-projects. Such information includes the physical path of + * the root Gradle project and its sub-projects. + * @param path the Gradle "logical" path. This path uses colon as separator, and may or may not be equal to the physical path of a + * Gradle project. + * @return the physical path of the module's root directory. + */ + @Nullable + public static File getModuleDirPath(@NotNull GradleBuild build, @NotNull String path) { + for (BasicGradleProject project : build.getProjects()) { + if (project.getPath().equals(path)) { + return project.getProjectDirectory(); + } + } + return null; + } + @NotNull public static String getModuleId(@NotNull IdeaModule gradleModule) { GradleProject gradleProject = gradleModule.getGradleProject(); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java index a42352251703..621f790f58f2 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java @@ -18,6 +18,7 @@ package org.jetbrains.plugins.gradle.service.project; import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId; import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener; import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.util.UserDataHolderEx; import org.gradle.tooling.CancellationTokenSource; import org.gradle.tooling.ProjectConnection; import org.gradle.tooling.model.idea.IdeaModule; @@ -32,101 +33,45 @@ import java.util.Collection; * @author Vladislav.Soroka * @since 10/15/13 */ -public class ProjectResolverContext { - @NotNull private final ExternalSystemTaskId myExternalSystemTaskId; - @NotNull private final String myProjectPath; - @Nullable private final GradleExecutionSettings mySettings; - @NotNull private final ProjectConnection myConnection; - @Nullable private CancellationTokenSource myCancellationTokenSource; - @NotNull private final ExternalSystemTaskNotificationListener myListener; - private final boolean myIsPreviewMode; +public interface ProjectResolverContext extends UserDataHolderEx { @NotNull - private ProjectImportAction.AllModels myModels; - - public ProjectResolverContext(@NotNull final ExternalSystemTaskId externalSystemTaskId, - @NotNull final String projectPath, - @Nullable final GradleExecutionSettings settings, - @NotNull final ProjectConnection connection, - @NotNull final ExternalSystemTaskNotificationListener listener, - final boolean isPreviewMode) { - myExternalSystemTaskId = externalSystemTaskId; - myProjectPath = projectPath; - mySettings = settings; - myConnection = connection; - myListener = listener; - myIsPreviewMode = isPreviewMode; - } - - @NotNull - public ExternalSystemTaskId getExternalSystemTaskId() { - return myExternalSystemTaskId; - } + ExternalSystemTaskId getExternalSystemTaskId(); @Nullable - public String getIdeProjectPath() { - return mySettings != null ? mySettings.getIdeProjectPath() : null; - } + String getIdeProjectPath(); @NotNull - public String getProjectPath() { - return myProjectPath; - } + String getProjectPath(); @Nullable - public GradleExecutionSettings getSettings() { - return mySettings; - } + GradleExecutionSettings getSettings(); @NotNull - public ProjectConnection getConnection() { - return myConnection; - } + ProjectConnection getConnection(); @Nullable - public CancellationTokenSource getCancellationTokenSource() { - return myCancellationTokenSource; - } - - public void setCancellationTokenSource(@Nullable CancellationTokenSource cancellationTokenSource) { - myCancellationTokenSource = cancellationTokenSource; - } + CancellationTokenSource getCancellationTokenSource(); @NotNull - public ExternalSystemTaskNotificationListener getListener() { - return myListener; - } + ExternalSystemTaskNotificationListener getListener(); - public boolean isPreviewMode() { - return myIsPreviewMode; - } + boolean isPreviewMode(); @NotNull - public ProjectImportAction.AllModels getModels() { - return myModels; - } + ProjectImportAction.AllModels getModels(); - public void setModels(@NotNull ProjectImportAction.AllModels models) { - myModels = models; - } + public void setModels(@NotNull ProjectImportAction.AllModels models) ; @Nullable - public T getExtraProject(Class modelClazz) { - return myModels.getExtraProject(null, modelClazz); - } + T getExtraProject(Class modelClazz); @Nullable - public T getExtraProject(@Nullable IdeaModule module, Class modelClazz) { - return myModels.getExtraProject(module, modelClazz); - } + T getExtraProject(@Nullable IdeaModule module, Class modelClazz); @NotNull - public Collection findModulesWithModel(@NotNull Class modelClazz) { - return myModels.findModulesWithModel(modelClazz); - } + Collection findModulesWithModel(@NotNull Class modelClazz); - public void checkCancelled() { - if (myCancellationTokenSource != null && myCancellationTokenSource.token().isCancellationRequested()) { - throw new ProcessCanceledException(); - } - } + boolean hasModulesWithModel(@NotNull Class modelClazz); + + void checkCancelled() throws ProcessCanceledException; } diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModelsHolder.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModelsHolder.java index 593d04cd69d3..77c4e68e9e87 100644 --- a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModelsHolder.java +++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModelsHolder.java @@ -72,6 +72,13 @@ public abstract class ModelsHolder implements Serializable { return modules; } + public boolean hasModulesWithModel(@NotNull Class modelClazz) { + for (Map.Entry set : myModelsById.entrySet()) { + if (modelClazz.isInstance(set.getValue())) return true; + } + return false; + } + public void addExtraProject(@NotNull Object project, @NotNull Class modelClazz) { myModelsById.put(extractMapKey(modelClazz, null), project); } @@ -81,7 +88,7 @@ public abstract class ModelsHolder implements Serializable { } @NotNull - protected abstract String extractMapKey(Class modelClazz, @Nullable V module) ; + protected abstract String extractMapKey(Class modelClazz, @Nullable V module); @NotNull private static String extractModulePath(Class modelClazz, String key) { From e05de62b4017cf57978574126c67262a69c62ca3 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Tue, 8 Dec 2015 17:29:33 +0300 Subject: [PATCH 15/25] gradle: fix module groups configuration --- .../project/manage/AbstractModuleDataService.java | 7 +++++-- .../project/BaseGradleProjectResolverExtension.java | 13 ++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractModuleDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractModuleDataService.java index c63b86c46f4f..21e6325651a6 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractModuleDataService.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractModuleDataService.java @@ -95,11 +95,14 @@ public abstract class AbstractModuleDataService extends Ab final ModifiableModuleModel modifiableModel = modelsProvider.getModifiableModuleModel(); final String[] groupPath; - if (isOneToOneMapping || node.getData().getIdeModuleGroup() == null || projectData == null) { + if (isOneToOneMapping || projectData == null) { groupPath = node.getData().getIdeModuleGroup(); } else { - groupPath = ArrayUtil.prepend(projectData.getInternalName() + " modules", node.getData().getIdeModuleGroup()); + final String externalProjectGroup = projectData.getInternalName() + " modules"; + groupPath = node.getData().getIdeModuleGroup() == null + ? new String[]{externalProjectGroup} + : ArrayUtil.prepend(externalProjectGroup, node.getData().getIdeModuleGroup()); } modifiableModel.setModuleGroupPath(module, groupPath); ModifiableRootModel modifiableRootModel = modelsProvider.getModifiableRootModel(module); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java index 4755463f1c8a..eb71ef36f31c 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java @@ -164,9 +164,16 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver ExternalProject externalProject = resolverCtx.getExtraProject(gradleModule, ExternalProject.class); if (externalProject != null) { - final String[] moduleGroup = - externalProject.getSourceSets().isEmpty() ? null : new String[]{mainModuleData.getInternalName() + " modules"}; - mainModuleData.setIdeModuleGroup(moduleGroup); + String gradlePath = gradleModule.getGradleProject().getPath(); + final boolean isRootModule = StringUtil.isEmpty(gradlePath) || ":".equals(gradlePath); + final String[] moduleGroup; + if (isRootModule) { + moduleGroup = new String[]{mainModuleData.getInternalName()}; + } + else { + moduleGroup = ArrayUtil.remove(gradlePath.split(":"), 0); + } + mainModuleData.setIdeModuleGroup(isRootModule ? null : moduleGroup); for (ExternalSourceSet sourceSet : externalProject.getSourceSets().values()) { final String moduleId = getModuleId(externalProject, sourceSet); From bb1129067a918a5c820f9f82171e650ea81ffafd Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 8 Dec 2015 17:46:24 +0300 Subject: [PATCH 16/25] investigate test blinking --- .../openapi/editor/impl/CaretImpl.java | 30 ++++++++++++++++++- .../openapi/editor/impl/CaretModelImpl.java | 22 ++++++++++++-- .../openapi/editor/impl/EditorImpl.java | 1 + .../editor/impl/view/EditorSizeManager.java | 4 ++- .../openapi/editor/impl/view/EditorView.java | 10 ++++++- .../openapi/editor/EditorPaintingTest.java | 2 ++ 6 files changed, 64 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java index ff2b6a12f776..b22f109a841f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.editor.impl; +import com.intellij.diagnostic.Dumpable; import com.intellij.diagnostic.LogMessageEx; import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.application.ApplicationManager; @@ -47,7 +48,7 @@ import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; import java.util.List; -public class CaretImpl extends UserDataHolderBase implements Caret { +public class CaretImpl extends UserDataHolderBase implements Caret, Dumpable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.CaretImpl"); private final EditorImpl myEditor; @@ -1484,6 +1485,33 @@ public class CaretImpl extends UserDataHolderBase implements Caret { return myEditor.myUseNewRendering && myEditor.myView.isAtBidiRunBoundary(myVisibleCaret); } + @NotNull + @Override + public String dumpState() { + return "{valid: " + isValid + + ", offset: " + myOffset + + ", logical pos: " + myLogicalCaret + + ", visual pos: " + myVisibleCaret + + ", visual line start: " + myVisualLineStart + + ", visual line end: " + myVisualLineEnd + + ", savedBeforeBulkCaretMarker: " + savedBeforeBulkCaretMarker + + ", skip change requests: " + mySkipChangeRequests + + ", desired selection start column: " + myDesiredSelectionStartColumn + + ", desired selection end column: " + myDesiredSelectionEndColumn + + ", report caret moves: " + myReportCaretMoves + + ", desired x: " + myDesiredX + + ", selection marker: " + mySelectionMarker + + ", rangeMarker start position: " + myRangeMarkerStartPosition + + ", rangeMarker end position: " + myRangeMarkerEndPosition + + ", rangeMarker end position is lead: " + myRangeMarkerEndPositionIsLead + + ", selection start before change: " + startBefore + + ", selection end after change: " + endBefore + + ", unknown direction: " + myUnknownDirection + + ", virtual space offset: " + myVirtualSpaceOffset + + ", virtual selection start offset: " + myStartVirtualOffset + + ", virtual selection end offset: " + myEndVirtualOffset + '}'; + } + /** * Encapsulates information about target vertical range info - its 'y' coordinate and height in pixels. */ diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java index 81f1d2ec873a..dde8d538cfcc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -24,6 +24,7 @@ */ package com.intellij.openapi.editor.impl; +import com.intellij.diagnostic.Dumpable; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.*; @@ -36,12 +37,14 @@ import com.intellij.openapi.editor.impl.event.DocumentEventImpl; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.Disposer; import com.intellij.util.EventDispatcher; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; -public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, Disposable { +public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, Disposable, Dumpable { private final EditorImpl myEditor; private final EventDispatcher myCaretListeners = EventDispatcher.create(CaretListener.class); @@ -512,6 +515,21 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, myCaretListeners.getMulticaster().caretRemoved(new CaretEvent(myEditor, caret, caret.getLogicalPosition(), caret.getLogicalPosition())); } + @NotNull + @Override + public String dumpState() { + return "[in update: " + myIsInUpdate + + ", document changed: " + isDocumentChanged + + ", perform caret merging: " + myPerformCaretMergingAfterCurrentOperation + + ", current caret: " + myCurrentCaret + + ", all carets: " + ContainerUtil.map(myCarets, new Function() { + @Override + public String fun(CaretImpl caret) { + return caret.dumpState(); + } + }) + "]"; + } + private static class VisualPositionComparator implements Comparator { private static final VisualPositionComparator INSTANCE = new VisualPositionComparator(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index e1eceabefaf2..49353230a96c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -3149,6 +3149,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi + "', allow caret inside tab: " + mySettings.isCaretInsideTabs() + ", allow caret after line end: " + mySettings.isVirtualSpace() + ", soft wraps: " + (mySoftWrapModel.isSoftWrappingEnabled() ? "on" : "off") + + ", caret model: " + getCaretModel().dumpState() + ", soft wraps data: " + getSoftWrapModel().dumpState() + "\n\nfolding data: " + getFoldingModel().dumpState() + (myDocument instanceof DocumentImpl ? "\n\ndocument info: " + ((DocumentImpl)myDocument).dumpState() : "") diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorSizeManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorSizeManager.java index 44d5cefa4ee8..fa1414aa0f75 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorSizeManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorSizeManager.java @@ -362,6 +362,8 @@ class EditorSizeManager implements PrioritizedDocumentListener, Disposable, Fold @NotNull @Override public String dumpState() { - return "[line widths: " + myLineWidths + "]"; + return "[cached width: " + myWidthInPixels + + ", max line with extension width: " + myMaxLineWithExtensionWidth + + ", line widths: " + myLineWidths + "]"; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorView.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorView.java index fdcefe798d64..c54f04754089 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorView.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorView.java @@ -469,6 +469,14 @@ public class EditorView implements TextDrawingCallback, Disposable, Dumpable { @NotNull @Override public String dumpState() { - return "[Size manager: " + mySizeManager.dumpState() + "]"; + return "[prefix text: " + myPrefixText + + ", prefix attributes: " + myPrefixAttributes + + ", space width: " + myPlainSpaceWidth + + ", line height: " + myLineHeight + + ", descent: " + myDescent + + ", char height: " + myCharHeight + + ", max char width: " + myMaxCharWidth + + ", tab size: " + myTabSize + + " ,size manager: " + mySizeManager.dumpState() + "]"; } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorPaintingTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorPaintingTest.java index 7cb58d98b896..22460eaaeb95 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorPaintingTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorPaintingTest.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.editor; +import com.intellij.diagnostic.Dumpable; import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.event.DocumentEvent; @@ -52,6 +53,7 @@ public class EditorPaintingTest extends AbstractEditorTest { public void testWholeLineHighlighterAtDocumentEnd() throws Exception { initText("foo"); addLineHighlighter(0, 3, HighlighterLayer.WARNING, null, Color.red); + System.out.println(((Dumpable)myEditor).dumpState()); // temporary code to find the cause of blinking checkResult(); } From a852c05b9b8fde88daf2f52c103084d5eeb1f337 Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 8 Dec 2015 18:23:12 +0300 Subject: [PATCH 17/25] part of external-system-api module which is used in gradle-tooling process classpath extracted to a separate module (external-system-rt) --- .idea/modules.xml | 1 + build/conf/classVersions.txt | 2 ++ build/scripts/layouts.gant | 2 ++ platform/external-system-api/external-system-api.iml | 3 ++- platform/external-system-rt/external-system-rt.iml | 12 ++++++++++++ .../model/ExternalSystemException.java | 0 .../model/project/ExternalSystemSourceType.java | 0 .../model/project/IExternalSystemSourceType.java | 0 .../project/BaseGradleProjectResolverExtension.java | 2 +- .../gradle-tooling-extension-api.iml | 2 +- .../gradle-tooling-extension-impl.iml | 2 +- 11 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 platform/external-system-rt/external-system-rt.iml rename platform/{external-system-api => external-system-rt}/src/com/intellij/openapi/externalSystem/model/ExternalSystemException.java (100%) rename platform/{external-system-api => external-system-rt}/src/com/intellij/openapi/externalSystem/model/project/ExternalSystemSourceType.java (100%) rename platform/{external-system-api => external-system-rt}/src/com/intellij/openapi/externalSystem/model/project/IExternalSystemSourceType.java (100%) diff --git a/.idea/modules.xml b/.idea/modules.xml index 77fc541298b1..d7412724d55b 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -88,6 +88,7 @@ + diff --git a/build/conf/classVersions.txt b/build/conf/classVersions.txt index b42573e0be0a..639a4e8503c7 100644 --- a/build/conf/classVersions.txt +++ b/build/conf/classVersions.txt @@ -44,6 +44,8 @@ 1.8 => redist/annotations-java8.jar 1.3 => plugins/junit/lib/junit-rt.jar +1.6 => lib/external-system-rt.jar + 1.6 => plugins/gradle/lib/gradle-tooling-extension-api.jar 1.6 => plugins/gradle/lib/gradle-tooling-extension-impl.jar diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index da1fbd1fd875..22b39bcc16de 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -181,6 +181,8 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir jar("extensions.jar") { module("extensions")} + jar("external-system-rt.jar") { module("external-system-rt")} + jar([name: "idea.jar", duplicate: "preserve"]) { implementationModules.each { module it} } diff --git a/platform/external-system-api/external-system-api.iml b/platform/external-system-api/external-system-api.iml index 560cd417f4ad..e04ae61c2ae1 100644 --- a/platform/external-system-api/external-system-api.iml +++ b/platform/external-system-api/external-system-api.iml @@ -1,6 +1,6 @@ - + @@ -14,5 +14,6 @@ + \ No newline at end of file diff --git a/platform/external-system-rt/external-system-rt.iml b/platform/external-system-rt/external-system-rt.iml new file mode 100644 index 000000000000..a58c68919b9f --- /dev/null +++ b/platform/external-system-rt/external-system-rt.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSystemException.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/ExternalSystemException.java similarity index 100% rename from platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSystemException.java rename to platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/ExternalSystemException.java diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalSystemSourceType.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/ExternalSystemSourceType.java similarity index 100% rename from platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalSystemSourceType.java rename to platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/ExternalSystemSourceType.java diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/IExternalSystemSourceType.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/IExternalSystemSourceType.java similarity index 100% rename from platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/IExternalSystemSourceType.java rename to platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/IExternalSystemSourceType.java diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java index eb71ef36f31c..54b3feec7d86 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java @@ -495,7 +495,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver @Override public Set getToolingExtensionsClasses() { return ContainerUtil.set( - // externalSystem api jar + // external-system-rt.jar ExternalSystemSourceType.class, // gradle-tooling-extension-api jar ProjectImportAction.class, diff --git a/plugins/gradle/tooling-extension-api/gradle-tooling-extension-api.iml b/plugins/gradle/tooling-extension-api/gradle-tooling-extension-api.iml index d895123cae94..23012e7dd3ed 100644 --- a/plugins/gradle/tooling-extension-api/gradle-tooling-extension-api.iml +++ b/plugins/gradle/tooling-extension-api/gradle-tooling-extension-api.iml @@ -7,7 +7,7 @@ - + diff --git a/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml b/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml index 48ad9ab658b3..c8fb1acce762 100644 --- a/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml +++ b/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml @@ -10,7 +10,7 @@ - + From 29689de2e335908010e6836713823072f8dcc582 Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 8 Dec 2015 18:45:23 +0300 Subject: [PATCH 18/25] preparing to migrate to Java 8: use default project language level for Gradle plugin --- plugins/gradle/gradle.iml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/gradle/gradle.iml b/plugins/gradle/gradle.iml index 0322c3993670..1b2ece6f5207 100644 --- a/plugins/gradle/gradle.iml +++ b/plugins/gradle/gradle.iml @@ -1,6 +1,6 @@ - + From 400ae5d9eadd6cc6d21963eaf313f209eb9cf2ee Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 8 Dec 2015 18:51:43 +0300 Subject: [PATCH 19/25] trying to make test pass on agent - increasing timeout and adding diagnostic thread dump --- .../daemon/impl/DaemonRespondToChangesTest.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java index 60f56a4a96c5..5b68a03f362b 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java @@ -40,6 +40,7 @@ import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; import com.intellij.codeInspection.htmlInspections.RequiredAttributesInspectionBase; import com.intellij.codeInspection.varScopeCanBeNarrowed.FieldCanBeLocalInspection; import com.intellij.diagnostic.PerformanceWatcher; +import com.intellij.diagnostic.ThreadDumper; import com.intellij.execution.filters.TextConsoleBuilderFactory; import com.intellij.execution.ui.ConsoleView; import com.intellij.execution.ui.ConsoleViewContentType; @@ -2118,13 +2119,19 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase { } private void waitForDaemon() { - long deadline = System.currentTimeMillis() + 10000; + long deadline = System.currentTimeMillis() + 60_000; while (!myDaemonCodeAnalyzer.isRunning()) { - if (System.currentTimeMillis() > deadline) fail("Too long waiting for daemon to start"); + if (System.currentTimeMillis() > deadline) { + System.out.println(ThreadDumper.dumpThreadsToString()); + fail("Too long waiting for daemon to start"); + } UIUtil.dispatchAllInvocationEvents(); } while (myDaemonCodeAnalyzer.isRunning()) { - if (System.currentTimeMillis() > deadline) fail("Too long waiting for daemon to finish"); + if (System.currentTimeMillis() > deadline) { + System.out.println(ThreadDumper.dumpThreadsToString()); + fail("Too long waiting for daemon to finish"); + } UIUtil.dispatchAllInvocationEvents(); } } From ae5acf521d68859c8c2d01ca8ce6f7591d36c3de Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 8 Dec 2015 19:02:36 +0300 Subject: [PATCH 20/25] IDEA-148739 [follow-up] Enable gutter icons scaling by default --- .../util/src/com/intellij/openapi/util/IconLoader.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/util/IconLoader.java b/platform/util/src/com/intellij/openapi/util/IconLoader.java index bf68ba3cc773..1bb7082fd170 100644 --- a/platform/util/src/com/intellij/openapi/util/IconLoader.java +++ b/platform/util/src/com/intellij/openapi/util/IconLoader.java @@ -433,18 +433,19 @@ public final class IconLoader { scaledIcons = new HashMap(1); } - Icon result = scaledIcons.get(scaleFactor); + // TODO: consider clearing the cache on SCALE change + Icon result = scaledIcons.get(scaleFactor * SCALE); if (result != null) { return result; } - final Image image = ImageLoader.loadFromUrl(myUrl, UIUtil.isUnderDarcula(), scaleFactor >= 1.5f, filter); + final Image image = ImageLoader.loadFromUrl(myUrl, UIUtil.isUnderDarcula(), (scaleFactor * SCALE) >= 1.5f, filter); if (image != null) { int width = (int)(getIconWidth() * scaleFactor); int height = (int)(getIconHeight() * scaleFactor); final BufferedImage resizedImage = Scalr.resize(ImageUtil.toBufferedImage(image), Scalr.Method.ULTRA_QUALITY, width, height); result = getIcon(resizedImage); - scaledIcons.put(scaleFactor, result); + scaledIcons.put(scaleFactor * SCALE, result); return result; } From eba09ad7b22dae7235129a0a03e5a623eec936eb Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 8 Dec 2015 19:23:56 +0300 Subject: [PATCH 21/25] avoid less than 10% gutter icons scaling --- .../openapi/editor/impl/EditorGutterComponentImpl.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index 90bd1862449b..95e8a4c95782 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -57,10 +57,7 @@ import com.intellij.openapi.wm.impl.IdeGlassPaneImpl; import com.intellij.ui.HintHint; import com.intellij.ui.JBColor; import com.intellij.ui.awt.RelativePoint; -import com.intellij.util.Function; -import com.intellij.util.IconUtil; -import com.intellij.util.NullableFunction; -import com.intellij.util.SmartList; +import com.intellij.util.*; import com.intellij.util.containers.HashMap; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; @@ -875,7 +872,10 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse private Icon scaleIcon(Icon icon) { if (Registry.is("editor.scale.gutter.icons") && icon instanceof ScalableIcon) { - return ((ScalableIcon)icon).scale((float)myEditor.getLineHeight() / JBUI.scale(17f)); + float scale = myEditor.getLineHeight() / JBUI.scale(16f); + if (Math.abs(1f - scale) > 0.10f) { + return ((ScalableIcon)icon).scale(scale); + } } return icon; } From 017237070cc339c04a20c3f647101a5cdb9495e3 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 8 Dec 2015 19:46:30 +0300 Subject: [PATCH 22/25] fixing blinking debugger tests --- .../src/com/intellij/testFramework/ThreadTracker.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/testFramework/src/com/intellij/testFramework/ThreadTracker.java b/platform/testFramework/src/com/intellij/testFramework/ThreadTracker.java index f84cb57e7807..58c82ae05dad 100644 --- a/platform/testFramework/src/com/intellij/testFramework/ThreadTracker.java +++ b/platform/testFramework/src/com/intellij/testFramework/ThreadTracker.java @@ -79,6 +79,7 @@ public class ThreadTracker { wellKnownOffenders.add("IDEA Test Case Thread"); wellKnownOffenders.add("Image Fetcher "); wellKnownOffenders.add("Java2D Disposer"); + wellKnownOffenders.add("JDI Target VM Interface"); wellKnownOffenders.add("JobScheduler FJ pool "); wellKnownOffenders.add("JPS thread pool"); wellKnownOffenders.add("Keep-Alive-Timer"); From bda455fc845f247c582f35309c9afae500a41428 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 8 Dec 2015 20:44:52 +0300 Subject: [PATCH 23/25] show breakpoint popup in the middle of the breakpoint gutter icon (even with scaling) --- .../openapi/editor/ex/EditorGutterComponentEx.java | 2 +- .../editor/impl/EditorGutterComponentImpl.java | 5 +++-- .../impl/actions/EditBreakpointActionHandler.java | 11 +++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorGutterComponentEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorGutterComponentEx.java index 367cb823fca9..fa8359127337 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorGutterComponentEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorGutterComponentEx.java @@ -61,7 +61,7 @@ public abstract class EditorGutterComponentEx extends JComponent implements Edit public abstract int getAnnotationsAreaWidth(); @Nullable - public abstract Point getPoint(GutterIconRenderer renderer); + public abstract Point getCenterPoint(GutterIconRenderer renderer); public abstract void setLineNumberConvertor(@NotNull TIntFunction lineNumberConvertor); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index 95e8a4c95782..d88ee62d5741 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -1579,14 +1579,15 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse @Override @Nullable - public Point getPoint(final GutterIconRenderer renderer) { + public Point getCenterPoint(final GutterIconRenderer renderer) { final Ref result = Ref.create(); for (int line : myLineToGutterRenderers.keys()) { processIconsRow(line, myLineToGutterRenderers.get(line), new LineGutterIconRendererProcessor() { @Override public void process(int x, int y, GutterMark r) { if (result.isNull() && r.equals(renderer)) { - result.set(new Point(x, y)); + Icon icon = scaleIcon(r.getIcon()); + result.set(new Point(x + icon.getIconWidth() / 2, y + icon.getIconHeight() / 2)); } } }, true); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointActionHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointActionHandler.java index dac828ecb22f..36c53e389398 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointActionHandler.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointActionHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -54,11 +54,10 @@ public abstract class EditBreakpointActionHandler extends DebuggerActionHandler public void editBreakpoint(@NotNull Project project, @NotNull Editor editor, @NotNull Object breakpoint, @NotNull GutterIconRenderer breakpointGutterRenderer) { if (BreakpointsDialogFactory.getInstance(project).isBreakpointPopupShowing()) return; EditorGutterComponentEx gutterComponent = ((EditorEx)editor).getGutterComponentEx(); - Point point = gutterComponent.getPoint(breakpointGutterRenderer); - if (point == null) return; - final Icon icon = breakpointGutterRenderer.getIcon(); - Point whereToShow = new Point(point.x + icon.getIconWidth() / 2, point.y + icon.getIconHeight() / 2); - doShowPopup(project, gutterComponent, whereToShow, breakpoint); + Point point = gutterComponent.getCenterPoint(breakpointGutterRenderer); + if (point != null) { + doShowPopup(project, gutterComponent, point, breakpoint); + } } public void editBreakpoint(@NotNull Project project, @NotNull JComponent parent, @NotNull Point whereToShow, @NotNull BreakpointItem breakpoint) { From 829d49648e2ee31040c9201f9089a2e75e34bea3 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 8 Dec 2015 21:17:49 +0300 Subject: [PATCH 24/25] minor optimization (create less AffineTransform objects and less setTransform calls) --- .../impl/EditorGutterComponentImpl.java | 39 ++++++++----------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index d88ee62d5741..184e52b4d3a3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -239,14 +239,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse if (clip.height < 0) return; Graphics2D g = IdeBackgroundUtil.withEditorBackground(g_, this); - AffineTransform old = g.getTransform(); - - if (isMirrored()) { - final AffineTransform transform = new AffineTransform(old); - transform.scale(-1, 1); - transform.translate(-getWidth(), 0); - g.setTransform(transform); - } + AffineTransform old = setMirrorTransformIfNeeded(g, 0, getWidth()); EditorUIUtil.setupAntialiasing(g); Color backgroundColor = getBackground(); @@ -274,7 +267,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, hint); } - g.setTransform(old); + if (old != null) g.setTransform(old); } finally { ((ApplicationImpl)ApplicationManager.getApplication()).editorPaintFinish(); @@ -376,8 +369,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse if (w == 0) return; - AffineTransform old = g.getTransform(); - g.setTransform(getMirrorTransform(old, x, w)); + AffineTransform old = setMirrorTransformIfNeeded(g, x, w); try { Color color = myEditor.getColorsScheme().getColor(EditorColors.ANNOTATIONS_COLOR); g.setColor(color != null ? color : JBColor.blue); @@ -419,7 +411,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } finally { - g.setTransform(old); + if (old != null) g.setTransform(old); } } @@ -495,8 +487,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse g.setColor(color != null ? color : JBColor.blue); g.setFont(myEditor.getColorsScheme().getFont(EditorFontType.PLAIN)); - AffineTransform old = g.getTransform(); - g.setTransform(getMirrorTransform(old, getLineNumberAreaOffset(), getLineNumberAreaWidth())); + AffineTransform old = setMirrorTransformIfNeeded(g, getLineNumberAreaOffset(), getLineNumberAreaWidth()); try { for (int i = startLineNumber; i < endLineNumber; i++) { LogicalPosition logicalPosition = myEditor.visualToLogicalPosition(new VisualPosition(i, 0)); @@ -523,7 +514,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } finally { - g.setTransform(old); + if (old != null) g.setTransform(old); } } @@ -807,13 +798,12 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse public void process(int x, int y, GutterMark renderer) { Icon icon = scaleIcon(renderer.getIcon()); - AffineTransform old = g.getTransform(); - g.setTransform(getMirrorTransform(old, x, icon.getIconWidth())); + AffineTransform old = setMirrorTransformIfNeeded(g, x, icon.getIconWidth()); try { icon.paintIcon(EditorGutterComponentImpl.this, g, x, y); } finally { - g.setTransform(old); + if (old != null) g.setTransform(old); } } }); @@ -1261,10 +1251,11 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse return myEditor.getVerticalScrollbarOrientation() != EditorEx.VERTICAL_SCROLLBAR_RIGHT; } - @NotNull - private AffineTransform getMirrorTransform(@NotNull AffineTransform old, int offset, int width) { - final AffineTransform transform = new AffineTransform(old); + @Nullable + private AffineTransform setMirrorTransformIfNeeded(Graphics2D g, int offset, int width) { if (isMirrored()) { + AffineTransform old = g.getTransform(); + AffineTransform transform = new AffineTransform(old); //transform.translate(getWidth(), 0); // revert mirroring transform //transform.scale(-1, 1); // revert mirroring transform //transform.translate(getWidth() - offset - width, 0); // move range start to the X==0 @@ -1272,8 +1263,12 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse transform.scale(-1, 1); transform.translate(-offset * 2 - width, 0); + g.setTransform(transform); + return old; + } + else { + return null; } - return transform; } @Nullable From 591bcd565976df5d399058c3ff749c9a7e4e18c1 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Sun, 6 Dec 2015 22:03:26 +0300 Subject: [PATCH 25/25] [groovy] remove unnecessary output from tests --- .../plugins/groovy/completion/GroovyCompletionTest.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index 486521644a5b..38f263e42021 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -968,7 +968,7 @@ class Fopppp { myFixture.configureByText "a.groovy", text final LookupElement[] completion = myFixture.completeBasic() - return completion.find { println it.lookupString; itemToCheck == it.lookupString } + return completion.find { itemToCheck == it.lookupString } } public void testWordCompletionInLiterals() {