From 2c85e90196138af064250e7359b7a434ce78466a Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 5 Aug 2013 16:58:27 +0400 Subject: [PATCH 01/62] cleanup --- .../openapi/progress/NonCancelableSection.java | 10 ++++++++++ .../openapi/progress/ProgressIndicatorProvider.java | 11 +++-------- .../com/intellij/core/CoreApplicationEnvironment.java | 6 +----- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/platform/core-api/src/com/intellij/openapi/progress/NonCancelableSection.java b/platform/core-api/src/com/intellij/openapi/progress/NonCancelableSection.java index 78e3f3593f68..a168fdaec779 100644 --- a/platform/core-api/src/com/intellij/openapi/progress/NonCancelableSection.java +++ b/platform/core-api/src/com/intellij/openapi/progress/NonCancelableSection.java @@ -19,6 +19,16 @@ */ package com.intellij.openapi.progress; +import org.jetbrains.annotations.NotNull; + public interface NonCancelableSection { void done(); + + @NotNull + NonCancelableSection EMPTY = new NonCancelableSection() { + @Override + public void done() { + // do nothing + } + }; } diff --git a/platform/core-api/src/com/intellij/openapi/progress/ProgressIndicatorProvider.java b/platform/core-api/src/com/intellij/openapi/progress/ProgressIndicatorProvider.java index c275d689aa9a..0f50f8d05ecf 100644 --- a/platform/core-api/src/com/intellij/openapi/progress/ProgressIndicatorProvider.java +++ b/platform/core-api/src/com/intellij/openapi/progress/ProgressIndicatorProvider.java @@ -24,12 +24,12 @@ import org.jetbrains.annotations.Nullable; public abstract class ProgressIndicatorProvider { @Nullable public static ProgressIndicatorProvider ourInstance; - + @Nullable public static ProgressIndicatorProvider getInstance() { return ourInstance; } - + public abstract ProgressIndicator getProgressIndicator(); protected abstract void doCheckCanceled() throws ProcessCanceledException; @@ -43,12 +43,7 @@ public abstract class ProgressIndicatorProvider { @NotNull public static NonCancelableSection startNonCancelableSectionIfSupported() { - return ourInstance != null ? ourInstance.startNonCancelableSection() : new NonCancelableSection() { - @Override - public void done() { - // do nothing - } - }; + return ourInstance != null ? ourInstance.startNonCancelableSection() : NonCancelableSection.EMPTY; } public static volatile boolean ourNeedToCheckCancel = false; diff --git a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java index 71eff2aa9026..3a2839c71937 100644 --- a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java +++ b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java @@ -215,11 +215,7 @@ public class CoreApplicationEnvironment { @Override public NonCancelableSection startNonCancelableSection() { - return new NonCancelableSection() { - @Override - public void done() { - } - }; + return NonCancelableSection.EMPTY; } }; } From a1e849491fd7533de41d6ef75b2ed8878f52e97e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 5 Aug 2013 17:23:24 +0400 Subject: [PATCH 02/62] performance: do not call .notify() after processWithProgress() terminates, rely on Future.get() instead --- .../daemon/DaemonAnalyzerTestCase.java | 2 +- .../daemon/LightDaemonAnalyzerTestCase.java | 2 +- .../openapi/progress/ProgressManager.java | 8 +-- .../daemon/impl/DaemonCodeAnalyzerImpl.java | 13 +--- .../daemon/impl/DaemonProgressIndicator.java | 12 ---- .../progress/impl/ProgressManagerImpl.java | 62 ++++++------------- 6 files changed, 24 insertions(+), 75 deletions(-) diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java index ccaa2cbde227..b3230893f501 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java @@ -188,7 +188,7 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { @Override protected void tearDown() throws Exception { ((StartupManagerImpl)StartupManager.getInstance(getProject())).checkCleared(); - ((DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(getProject())).cleanupAfterTest(!LightPlatformTestCase.isLight(getProject())); + ((DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(getProject())).cleanupAfterTest(); super.tearDown(); //((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).assertPointersDisposed(); } diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java index 1416e81ec9e4..60bf96c5bb39 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java @@ -52,7 +52,7 @@ public abstract class LightDaemonAnalyzerTestCase extends LightCodeInsightTestCa @Override protected void tearDown() throws Exception { - ((DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(getProject())).cleanupAfterTest(!isLight(getProject())); + ((DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(getProject())).cleanupAfterTest(); super.tearDown(); } diff --git a/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java b/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java index d1c186fa3e9d..5acb079f22a8 100644 --- a/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java +++ b/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java @@ -40,6 +40,7 @@ public abstract class ProgressManager { ProgressManager.ourInstance.doCheckCanceled(); } + @Override public NonCancelableSection startNonCancelableSection() { return ProgressManager.ourInstance.startNonCancelableSection(); @@ -209,13 +210,6 @@ public abstract class ProgressManager { if (set) { myThreadIndicator.set(oldIndicator); } - - if (progress != null) { - synchronized (progress) { - progress.notifyAll(); - } - } } } - } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java index 94cba5493be4..42179acb6124 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java @@ -261,7 +261,6 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx if (callbackWhileWaiting != null) { callbackWhileWaiting.run(); } - progress.waitFor(50); UIUtil.dispatchAllInvocationEvents(); Throwable savedException = PassExecutorService.getSavedException(progress); if (savedException != null) throw savedException; @@ -270,11 +269,9 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx throw e; } catch (Error e) { - e.printStackTrace(); throw e; } catch (Throwable e) { - e.printStackTrace(); throw new RuntimeException(e); } } @@ -299,16 +296,8 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx } @TestOnly - public void cleanupAfterTest(boolean dispose) { + public void cleanupAfterTest() { if (!myProject.isOpen()) return; - //stopProcess(false); - //if (dispose) { - // projectClosed(); - // Disposer.dispose(myStatusBarUpdater); - // myStatusBarUpdater = null; - // Disposer.dispose(myDaemonListeners); - // myDaemonListeners = null; - //} setUpdateByTimerEnabled(false); waitForTermination(); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonProgressIndicator.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonProgressIndicator.java index 023aa2352eeb..2941115f80de 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonProgressIndicator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonProgressIndicator.java @@ -61,18 +61,6 @@ public class DaemonProgressIndicator extends AbstractProgressIndicatorBase { super.start(); } - public boolean waitFor(int millisTimeout) { - synchronized (this) { - try { - // we count on ProgressManagerImpl doing progress.notifyAll() on finish - wait(millisTimeout); - } - catch (InterruptedException ignored) { - } - } - return isCanceled(); - } - @TestOnly public static void setDebug(boolean debug) { DaemonProgressIndicator.debug = debug; diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java index 0dbafad650db..4dfa3a860d64 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java @@ -40,18 +40,17 @@ import javax.swing.*; import java.awt.*; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.concurrent.Future; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class ProgressManagerImpl extends ProgressManager implements Disposable{ - @NonNls private static final String PROCESS_CANCELED_EXCEPTION = "idea.ProcessCanceledException"; - private final AtomicInteger myCurrentUnsafeProgressCount = new AtomicInteger(0); private final AtomicInteger myCurrentModalProgressCount = new AtomicInteger(0); private static volatile int ourLockedCheckCounter = 0; - private static final boolean DISABLED = "disabled".equals(System.getProperty(PROCESS_CANCELED_EXCEPTION)); + private static final boolean DISABLED = "disabled".equals(System.getProperty("idea.ProcessCanceledException")); private final ScheduledFuture myCheckCancelledFuture; public ProgressManagerImpl(Application application) { @@ -63,7 +62,8 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ ProgressIndicatorProvider.ourNeedToCheckCancel = true; } }, 0, 10, TimeUnit.MILLISECONDS); - } else { + } + else { myCheckCancelledFuture = null; } } @@ -123,7 +123,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ } @Override - public NonCancelableSection startNonCancelableSection() { + public final NonCancelableSection startNonCancelableSection() { NonCancelableIndicator nonCancelor = new NonCancelableIndicator(myThreadIndicator.get()); myThreadIndicator.set(nonCancelor); return nonCancelor; @@ -131,13 +131,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ @Override public void executeNonCancelableSection(@NotNull Runnable runnable) { - NonCancelableSection nonCancelor = startNonCancelableSection(); - try { - runnable.run(); - } - finally { - nonCancelor.done(); - } + executeProcessUnderProgress(runnable, new NonCancelableIndicator(getProgressIndicator())); } @Override @@ -174,9 +168,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ executeProcessUnderProgress(new Runnable(){ @Override public void run() { - synchronized (process) { - process.notifyAll(); - } try { if (progress != null && !progress.isRunning()) { progress.start(); @@ -190,9 +181,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ if (progress instanceof ProgressIndicatorEx) { ((ProgressIndicatorEx)progress).processFinish(); } - synchronized (process) { - process.notifyAll(); - } } } } @@ -281,7 +269,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ private static boolean runProcessWithProgressSynchronously(final Task task, @Nullable final JComponent parentComponent) { final long start = System.currentTimeMillis(); - long time = 0; final boolean result = ((ApplicationEx)ApplicationManager.getApplication()) .runProcessWithProgressSynchronously(new TaskContainer(task) { @Override @@ -292,7 +279,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ if (result) { final long end = System.currentTimeMillis(); final Task.NotificationInfo notificationInfo = task.notifyFinished(); - time = end - start; + long time = end - start; if (notificationInfo != null && time > 5000) { // show notification only if process took more than 5 secs final JFrame frame = WindowManager.getInstance().getFrame(task.getProject()); if (!frame.hasFocus()) { @@ -353,7 +340,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ }); } - public static void runProcessWithProgressAsynchronously(@NotNull Task.Backgroundable task) { + private static void runProcessWithProgressAsynchronously(@NotNull Task.Backgroundable task) { final ProgressIndicator progressIndicator; if (ApplicationManager.getApplication().isHeadlessEnvironment()) { progressIndicator = new EmptyProgressIndicator(); @@ -364,13 +351,15 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ runProcessWithProgressAsynchronously(task, progressIndicator, null); } + @Override public void runProcessWithProgressAsynchronously(@NotNull Task.Backgroundable task, @NotNull ProgressIndicator progressIndicator) { runProcessWithProgressAsynchronously(task, progressIndicator, null); } - public static void runProcessWithProgressAsynchronously(@NotNull final Task.Backgroundable task, - @NotNull final ProgressIndicator progressIndicator, - @Nullable final Runnable continuation) { + @NotNull + public static Future runProcessWithProgressAsynchronously(@NotNull final Task.Backgroundable task, + @NotNull final ProgressIndicator progressIndicator, + @Nullable final Runnable continuation) { if (progressIndicator instanceof Disposable) { Disposer.register(ApplicationManager.getApplication(), (Disposable)progressIndicator); } @@ -417,15 +406,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ } }; - synchronized (process) { - ApplicationManager.getApplication().executeOnPooledThread(action); - try { - process.wait(); - } - catch (InterruptedException e) { - throw new RuntimeException(e); - } - } + return ApplicationManager.getApplication().executeOnPooledThread(action); } @Override @@ -500,19 +481,16 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ @Override public void dispose() { + stopCheckCanceled(); + } + + private void stopCheckCanceled() { if (myCheckCancelledFuture != null) myCheckCancelledFuture.cancel(false); } - //for debugging @TestOnly @SuppressWarnings({"UnusedDeclaration"}) - private static void stopCheckCanceled() { - ((ProgressManagerImpl)getInstance()).dispose(); - } - - @TestOnly - @SuppressWarnings({"UnusedDeclaration"}) - public static String isCanceledThread(Thread thread) { + public static String isCanceledThread(@NotNull Thread thread) { try { Field th = Thread.class.getDeclaredField("threadLocals"); th.setAccessible(true); @@ -537,7 +515,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ final int debugProgressTime = Registry.intValue("ide.debug.minProgressTime"); if (debugProgressTime > 0) { try { - Thread.currentThread().sleep(debugProgressTime); + Thread.sleep(debugProgressTime); } catch (InterruptedException e) { //ignore From 76016cd7dcedade1444f51614d585bb01ca03499 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 5 Aug 2013 17:23:40 +0400 Subject: [PATCH 03/62] cleanup --- .../daemon/impl/PassExecutorService.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java index eae3cd4269a0..a7222151a6a8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java @@ -34,7 +34,6 @@ import com.intellij.openapi.fileEditor.TextEditor; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.progress.impl.ProgressManagerImpl; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; @@ -95,7 +94,7 @@ public abstract class PassExecutorService implements Disposable { mySubmittedPasses.clear(); } - public void submitPasses(Map passesMap, DaemonProgressIndicator updateProgress, final int jobPriority) { + public void submitPasses(@NotNull Map passesMap, @NotNull DaemonProgressIndicator updateProgress, final int jobPriority) { if (isDisposed()) return; int id = 1; @@ -197,6 +196,7 @@ public abstract class PassExecutorService implements Disposable { } } + @NotNull private ScheduledPass createScheduledPass(@NotNull List fileEditors, @NotNull TextEditorHighlightingPass pass, @NotNull Map, ScheduledPass> toBeSubmitted, @@ -238,14 +238,14 @@ public abstract class PassExecutorService implements Disposable { return scheduledPass; } - private ScheduledPass findOrCreatePredecessorPass(final List fileEditors, - final Document document, - final Map, ScheduledPass> toBeSubmitted, - final List textEditorHighlightingPasses, - final List freePasses, - List dependentPasses, - final DaemonProgressIndicator updateProgress, - final AtomicInteger myThreadsToStartCountdown, + private ScheduledPass findOrCreatePredecessorPass(@NotNull List fileEditors, + Document document, + @NotNull Map, ScheduledPass> toBeSubmitted, + @NotNull List textEditorHighlightingPasses, + @NotNull List freePasses, + @NotNull List dependentPasses, + @NotNull DaemonProgressIndicator updateProgress, + @NotNull AtomicInteger myThreadsToStartCountdown, final int jobPriority, final int predecessorId) { Pair predKey = Pair.create(document, predecessorId); @@ -258,7 +258,7 @@ public abstract class PassExecutorService implements Disposable { return predecessor; } - private static TextEditorHighlightingPass findPassById(final int id, final List textEditorHighlightingPasses) { + private static TextEditorHighlightingPass findPassById(final int id, @NotNull List textEditorHighlightingPasses) { TextEditorHighlightingPass textEditorPass = null; for (TextEditorHighlightingPass found : textEditorHighlightingPasses) { if (found.getId() == id) { @@ -269,7 +269,7 @@ public abstract class PassExecutorService implements Disposable { return textEditorPass; } - private void submit(final ScheduledPass pass) { + private void submit(@NotNull ScheduledPass pass) { if (!pass.myUpdateProgress.isCanceled()) { Job job = JobLauncher.getInstance().submitToJobThread(pass.myJobPriority, pass, new Consumer() { @Override @@ -342,7 +342,7 @@ public abstract class PassExecutorService implements Disposable { } } - ((ProgressManagerImpl)ProgressManager.getInstance()).executeProcessUnderProgress(new Runnable(){ + ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() { @Override public void run() { boolean success = ApplicationManagerEx.getApplicationEx().tryRunReadAction(new Runnable() { @@ -379,7 +379,7 @@ public abstract class PassExecutorService implements Disposable { myUpdateProgress.cancel(); } } - },myUpdateProgress); + }, myUpdateProgress); log(myUpdateProgress, myPass, "Finished. "); @@ -468,6 +468,7 @@ public abstract class PassExecutorService implements Disposable { protected abstract void afterApplyInformationToEditor(TextEditorHighlightingPass pass, FileEditor fileEditor, ProgressIndicator updateProgress); + @NotNull public List getAllSubmittedPasses() { List result = new ArrayList(mySubmittedPasses.size()); for (ScheduledPass scheduledPass : mySubmittedPasses.keySet()) { From ccab8010a9c79b54fa2b4983fc00b2754b513c1e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 5 Aug 2013 17:29:13 +0400 Subject: [PATCH 04/62] locator test and some other cases of mysteriously disappearing directories --- .../openapi/application/impl/ApplicationImpl.java | 6 +++++- .../testSrc/com/intellij/ide/LocatorTest.java | 2 -- .../com/intellij/testFramework/vcs/DirectoryData.java | 9 +++++---- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index 7aa71ef698d6..eec201a44892 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -532,12 +532,16 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application } myLoaded = true; + createLocatorFile(); + } + + private static void createLocatorFile() { File locatorFile = new File(PathManager.getSystemPath() + "/" + ApplicationEx.LOCATOR_FILE_NAME); try { byte[] data = PathManager.getHomePath().getBytes("UTF-8"); FileUtil.writeToFile(locatorFile, data); } - catch (Exception e) { + catch (IOException e) { LOG.warn("can't store a location in '" + locatorFile + "'", e); } } diff --git a/platform/platform-tests/testSrc/com/intellij/ide/LocatorTest.java b/platform/platform-tests/testSrc/com/intellij/ide/LocatorTest.java index ecb0d2d05e42..09c94c5ef174 100644 --- a/platform/platform-tests/testSrc/com/intellij/ide/LocatorTest.java +++ b/platform/platform-tests/testSrc/com/intellij/ide/LocatorTest.java @@ -15,7 +15,6 @@ */ package com.intellij.ide; -import com.intellij.idea.IdeaTestApplication; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.ex.ApplicationEx; import com.intellij.openapi.util.io.FileUtil; @@ -26,7 +25,6 @@ import java.io.File; public class LocatorTest extends PlatformLangTestCase { public void test() throws Exception { - IdeaTestApplication.getInstance(null); File locatorFile = new File(PathManager.getSystemPath() + "/" + ApplicationEx.LOCATOR_FILE_NAME); assertTrue("doesn't exist: " + locatorFile.getPath(), locatorFile.exists()); assertTrue("can't read: " + locatorFile.getPath(), locatorFile.canRead()); diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/DirectoryData.java b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/DirectoryData.java index 973f68167b6b..51581d21050c 100644 --- a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/DirectoryData.java +++ b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/DirectoryData.java @@ -51,11 +51,11 @@ public class DirectoryData { } public VirtualFile getBase() { - return myBase; + return myBase.findChild("dirData"); } public void clear() { - final File ioFile = new File(myBase.getPath()); + final File ioFile = new File(getBase().getPath()); final File[] files = ioFile.listFiles(); for (File file : files) { FileUtil.delete(file); @@ -70,7 +70,7 @@ public class DirectoryData { final List currentLevel = new ArrayList(); final List nextLevel = new ArrayList(); - currentLevel.add(myBase); + currentLevel.add(myBase.createChildDirectory(this, "dirData")); for (int i = 0; i < myLevels; i++) { for (VirtualFile file : currentLevel) { String numberInRow; @@ -101,7 +101,8 @@ public class DirectoryData { currentLevel.addAll(nextLevel); nextLevel.clear(); } - } catch (IOException e) { + } + catch (IOException e) { myException = e; } } From d9d95cf7dd7267776513c7fcfda15f03cd623bfd Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 5 Aug 2013 17:47:41 +0400 Subject: [PATCH 05/62] performance --- .../UncheckedWarningLocalInspection.java | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java index c20c81f3ca35..b740fcf9e7f6 100644 --- a/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java @@ -169,7 +169,10 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly, @NotNull LocalInspectionToolSession session) { - return new UncheckedWarningsVisitor(isOnTheFly, PsiUtil.getLanguageLevel(session.getFile())){ + LanguageLevel languageLevel = PsiUtil.getLanguageLevel(session.getFile()); + if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_5)) return super.buildVisitor(holder, isOnTheFly, session); + + return new UncheckedWarningsVisitor(isOnTheFly, languageLevel){ @Override protected void registerProblem(@NotNull String message, @NotNull PsiElement psiElement, @NotNull LocalQuickFix[] quickFixes) { holder.registerProblem(psiElement, message, quickFixes); @@ -194,9 +197,8 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool @Override public void visitReferenceExpression(PsiReferenceExpression expression) { if (IGNORE_UNCHECKED_GENERICS_ARRAY_CREATION) return; - if (!myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_5)) return; final JavaResolveResult result = expression.advancedResolve(false); - if (JavaGenericsUtil.isUncheckedWarning(expression, result, PsiUtil.getLanguageLevel(expression))) { + if (JavaGenericsUtil.isUncheckedWarning(expression, result, myLanguageLevel)) { registerProblem("Unchecked generics array creation for varargs parameter", expression, LocalQuickFix.EMPTY_ARRAY); } } @@ -205,7 +207,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool public void visitNewExpression(PsiNewExpression expression) { super.visitNewExpression(expression); if (IGNORE_UNCHECKED_GENERICS_ARRAY_CREATION) return; - if (!myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_5)) return; final PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference(); if (classReference != null && JavaGenericsUtil.isUncheckedWarning(classReference, expression.resolveMethodGenerics(), myLanguageLevel)) { registerProblem("Unchecked generics array creation for varargs parameter", classReference, LocalQuickFix.EMPTY_ARRAY); @@ -216,7 +217,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool public void visitTypeCastExpression(PsiTypeCastExpression expression) { super.visitTypeCastExpression(expression); if (IGNORE_UNCHECKED_CAST) return; - if (!PsiUtil.isLanguageLevel5OrHigher(expression)) return; final PsiTypeElement typeElement = expression.getCastType(); if (typeElement == null) return; final PsiType castType = typeElement.getType(); @@ -236,7 +236,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool @Override public void visitCallExpression(PsiCallExpression callExpression) { super.visitCallExpression(callExpression); - if (!PsiUtil.isLanguageLevel5OrHigher(callExpression)) return; final JavaResolveResult result = callExpression.resolveMethodGenerics(); final String description = getUncheckedCallDescription(result); if (description != null) { @@ -275,7 +274,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool public void visitVariable(PsiVariable variable) { super.visitVariable(variable); if (IGNORE_UNCHECKED_ASSIGNMENT) return; - if (!PsiUtil.isLanguageLevel5OrHigher(variable)) return; PsiExpression initializer = variable.getInitializer(); if (initializer == null || initializer instanceof PsiArrayInitializerExpression) return; final PsiType initializerType = initializer.getType(); @@ -287,13 +285,11 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool public void visitForeachStatement(PsiForeachStatement statement) { super.visitForeachStatement(statement); if (IGNORE_UNCHECKED_ASSIGNMENT) return; - if (!PsiUtil.isLanguageLevel5OrHigher(statement)) return; final PsiParameter parameter = statement.getIterationParameter(); final PsiType parameterType = parameter.getType(); final PsiExpression iteratedValue = statement.getIteratedValue(); if (iteratedValue == null) return; final PsiType itemType = JavaGenericsUtil.getCollectionItemType(iteratedValue); - if (!PsiUtil.isLanguageLevel5OrHigher(statement)) return; checkRawToGenericsAssignment(parameter, parameterType, itemType, true, myOnTheFly ? getChangeVariableTypeFixes(parameter, itemType) : LocalQuickFix.EMPTY_ARRAY); } @@ -301,7 +297,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool public void visitAssignmentExpression(PsiAssignmentExpression expression) { super.visitAssignmentExpression(expression); if (IGNORE_UNCHECKED_ASSIGNMENT) return; - if (!PsiUtil.isLanguageLevel5OrHigher(expression)) return; if (!"=".equals(expression.getOperationSign().getText())) return; PsiExpression lExpr = expression.getLExpression(); PsiExpression rExpr = expression.getRExpression(); @@ -323,7 +318,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool public void visitArrayInitializerExpression(PsiArrayInitializerExpression arrayInitializer) { super.visitArrayInitializerExpression(arrayInitializer); if (IGNORE_UNCHECKED_ASSIGNMENT) return; - if (!PsiUtil.isLanguageLevel5OrHigher(arrayInitializer)) return; final PsiType type = arrayInitializer.getType(); if (!(type instanceof PsiArrayType)) return; final PsiType componentType = ((PsiArrayType)type).getComponentType(); @@ -374,7 +368,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool public void visitMethod(PsiMethod method) { super.visitMethod(method); if (IGNORE_UNCHECKED_OVERRIDING) return; - if (!PsiUtil.isLanguageLevel5OrHigher(method)) return; if (!method.isConstructor()) { List superMethodSignatures = method.getHierarchicalMethodSignature().getSuperSignatures(); if (!superMethodSignatures.isEmpty() && !method.hasModifierProperty(PsiModifier.STATIC)) { @@ -405,7 +398,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool public void visitReturnStatement(PsiReturnStatement statement) { super.visitReturnStatement(statement); if (IGNORE_UNCHECKED_ASSIGNMENT) return; - if (!PsiUtil.isLanguageLevel5OrHigher(statement)) return; final PsiMethod method = PsiTreeUtil.getParentOfType(statement, PsiMethod.class); if (method != null) { final PsiType returnType = method.getReturnType(); From 6522762da1b732df128d70170e6c0e9f415def0a Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 5 Aug 2013 18:20:39 +0400 Subject: [PATCH 06/62] cleanup --- .../progress/util/ProgressWrapper.java | 1 + .../com/intellij/openapi/editor/Editor.java | 69 ++++++++++++------- .../concurrency/JobSchedulerImpl.java | 6 +- .../concurrency/PrioritizedFutureTask.java | 5 +- 4 files changed, 56 insertions(+), 25 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/progress/util/ProgressWrapper.java b/platform/core-impl/src/com/intellij/openapi/progress/util/ProgressWrapper.java index 9aa9fb1b5198..f8520610ffda 100644 --- a/platform/core-impl/src/com/intellij/openapi/progress/util/ProgressWrapper.java +++ b/platform/core-impl/src/com/intellij/openapi/progress/util/ProgressWrapper.java @@ -33,6 +33,7 @@ public class ProgressWrapper extends AbstractProgressIndicatorBase { myOriginal = original; } + @Override public boolean isCanceled() { return myOriginal.isCanceled(); } diff --git a/platform/platform-api/src/com/intellij/openapi/editor/Editor.java b/platform/platform-api/src/com/intellij/openapi/editor/Editor.java index 27f45aa5c223..3ac00e644d86 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/Editor.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/Editor.java @@ -38,12 +38,14 @@ import java.awt.event.MouseEvent; */ public interface Editor extends UserDataHolder { Editor[] EMPTY_ARRAY = new Editor[0]; + /** * Returns the document edited or viewed in the editor. * * @return the document instance. */ - @NotNull Document getDocument(); + @NotNull + Document getDocument(); /** * Returns the value indicating whether the editor operates in viewer mode, with @@ -60,7 +62,8 @@ public interface Editor extends UserDataHolder { * * @return the component instance. */ - @NotNull JComponent getComponent(); + @NotNull + JComponent getComponent(); /** * Returns the component for the content area of the editor (the area displaying the document text). @@ -69,7 +72,8 @@ public interface Editor extends UserDataHolder { * * @return the component instance. */ - @NotNull JComponent getContentComponent(); + @NotNull + JComponent getContentComponent(); void setBorder(@Nullable Border border); @@ -81,7 +85,8 @@ public interface Editor extends UserDataHolder { * * @return the selection model instance. */ - @NotNull SelectionModel getSelectionModel(); + @NotNull + SelectionModel getSelectionModel(); /** * Returns the markup model for the editor. This model contains editor-specific highlighters @@ -91,7 +96,8 @@ public interface Editor extends UserDataHolder { * @return the markup model instance. * @see com.intellij.openapi.editor.impl.DocumentMarkupModel#forDocument(com.intellij.openapi.editor.Document, com.intellij.openapi.project.Project, boolean) */ - @NotNull MarkupModel getMarkupModel(); + @NotNull + MarkupModel getMarkupModel(); /** * Returns the folding model for the document, which can be used to add, remove, expand @@ -99,7 +105,8 @@ public interface Editor extends UserDataHolder { * * @return the folding model instance. */ - @NotNull FoldingModel getFoldingModel(); + @NotNull + FoldingModel getFoldingModel(); /** * Returns the scrolling model for the document, which can be used to scroll the document @@ -107,7 +114,8 @@ public interface Editor extends UserDataHolder { * * @return the scrolling model instance. */ - @NotNull ScrollingModel getScrollingModel(); + @NotNull + ScrollingModel getScrollingModel(); /** * Returns the caret model for the document, which can be used to move the caret and @@ -115,7 +123,8 @@ public interface Editor extends UserDataHolder { * * @return the caret model instance. */ - @NotNull CaretModel getCaretModel(); + @NotNull + CaretModel getCaretModel(); /** * Returns the soft wrap model for the document, which can be used to get information about soft wraps registered @@ -123,7 +132,8 @@ public interface Editor extends UserDataHolder { * * @return the soft wrap model instance */ - @NotNull SoftWrapModel getSoftWrapModel(); + @NotNull + SoftWrapModel getSoftWrapModel(); /** * Returns the editor settings for this editor instance. Changes to these settings affect @@ -131,7 +141,8 @@ public interface Editor extends UserDataHolder { * * @return the settings instance. */ - @NotNull EditorSettings getSettings(); + @NotNull + EditorSettings getSettings(); /** * Returns the editor color scheme for this editor instance. Changes to the scheme affect @@ -139,7 +150,8 @@ public interface Editor extends UserDataHolder { * * @return the color scheme instance. */ - @NotNull EditorColorsScheme getColorsScheme(); + @NotNull + EditorColorsScheme getColorsScheme(); /** * Returns the height of a single line of text in the current editor font. @@ -154,7 +166,8 @@ public interface Editor extends UserDataHolder { * @param pos the logical position. * @return the coordinates relative to the top left corner of the {@link #getContentComponent() content component}. */ - @NotNull Point logicalPositionToXY(@NotNull LogicalPosition pos); + @NotNull + Point logicalPositionToXY(@NotNull LogicalPosition pos); /** * Maps a logical position in the editor to the offset in the document. @@ -171,7 +184,8 @@ public interface Editor extends UserDataHolder { * @param logicalPos the logical position. * @return the corresponding visual position. */ - @NotNull VisualPosition logicalToVisualPosition(@NotNull LogicalPosition logicalPos); + @NotNull + VisualPosition logicalToVisualPosition(@NotNull LogicalPosition logicalPos); /** * Maps a visual position in the editor to pixel coordinates. @@ -179,7 +193,8 @@ public interface Editor extends UserDataHolder { * @param visible the visual position. * @return the coordinates relative to the top left corner of the {@link #getContentComponent() content component}. */ - @NotNull Point visualPositionToXY(@NotNull VisualPosition visible); + @NotNull + Point visualPositionToXY(@NotNull VisualPosition visible); /** * Maps a visual position in the editor (with folded lines and columns not included in the line and column count) to @@ -188,7 +203,8 @@ public interface Editor extends UserDataHolder { * @param visiblePos the visual position. * @return the corresponding logical position. */ - @NotNull LogicalPosition visualToLogicalPosition(@NotNull VisualPosition visiblePos); + @NotNull + LogicalPosition visualToLogicalPosition(@NotNull VisualPosition visiblePos); /** * Maps an offset in the document to a logical position. @@ -196,7 +212,8 @@ public interface Editor extends UserDataHolder { * @param offset the offset in the document. * @return the corresponding logical position. */ - @NotNull LogicalPosition offsetToLogicalPosition(int offset); + @NotNull + LogicalPosition offsetToLogicalPosition(int offset); /** * Maps an offset in the document to a visual position. @@ -204,7 +221,8 @@ public interface Editor extends UserDataHolder { * @param offset the offset in the document. * @return the corresponding visual position. */ - @NotNull VisualPosition offsetToVisualPosition(int offset); + @NotNull + VisualPosition offsetToVisualPosition(int offset); /** * Maps the pixel coordinates in the editor to a logical position. @@ -212,7 +230,8 @@ public interface Editor extends UserDataHolder { * @param p the coordinates relative to the top left corner of the {@link #getContentComponent() content component}. * @return the corresponding logical position. */ - @NotNull LogicalPosition xyToLogicalPosition(@NotNull Point p); + @NotNull + LogicalPosition xyToLogicalPosition(@NotNull Point p); /** * Maps the pixel coordinates in the editor to a visual position. @@ -220,7 +239,8 @@ public interface Editor extends UserDataHolder { * @param p the coordinates relative to the top left corner of the {@link #getContentComponent() content component}. * @return the corresponding visual position. */ - @NotNull VisualPosition xyToVisualPosition(@NotNull Point p); + @NotNull + VisualPosition xyToVisualPosition(@NotNull Point p); /** * Adds a listener for receiving notifications about mouse clicks in the editor and @@ -264,7 +284,8 @@ public interface Editor extends UserDataHolder { * * @return the project instance, or null if the editor is not related to any project. */ - @Nullable Project getProject(); + @Nullable + Project getProject(); /** * Returns the insert/overwrite mode for the editor. @@ -293,7 +314,8 @@ public interface Editor extends UserDataHolder { * * @return the gutter instance. */ - @NotNull EditorGutter getGutter(); + @NotNull + EditorGutter getGutter(); /** * Returns the editor area (text, gutter, folding outline and so on) in which the specified @@ -302,17 +324,18 @@ public interface Editor extends UserDataHolder { * @param e the mouse event for which the area is requested. * @return the editor area, or null if the event occurred over an unknown area. */ - @Nullable EditorMouseEventArea getMouseEventArea(@NotNull MouseEvent e); + @Nullable + EditorMouseEventArea getMouseEventArea(@NotNull MouseEvent e); /** * Set up a header component for this text editor. Please note this is used for textual find feature so your component will most * probably will be reset once the user presses Ctrl+F. + * * @param header a component to setup as header for this text editor or null to remove one. */ void setHeaderComponent(@Nullable JComponent header); /** - * * @return true if this editor has active header component set up by {@link #setHeaderComponent(javax.swing.JComponent)} */ boolean hasHeaderComponent(); diff --git a/platform/platform-impl/src/com/intellij/concurrency/JobSchedulerImpl.java b/platform/platform-impl/src/com/intellij/concurrency/JobSchedulerImpl.java index c0fa94634cef..ff2270325cab 100644 --- a/platform/platform-impl/src/com/intellij/concurrency/JobSchedulerImpl.java +++ b/platform/platform-impl/src/com/intellij/concurrency/JobSchedulerImpl.java @@ -21,6 +21,7 @@ package com.intellij.concurrency; import com.intellij.openapi.Disposable; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.ThreadFactory; @@ -34,7 +35,9 @@ public class JobSchedulerImpl extends JobScheduler implements Disposable { private static final ThreadFactory WORKERS_FACTORY = new ThreadFactory() { private int threadSeq; - public synchronized Thread newThread(final Runnable r) { + @NotNull + @Override + public synchronized Thread newThread(@NotNull final Runnable r) { @NonNls String name = "JobScheduler pool " + threadSeq + "/" + CORES_COUNT; final Thread thread = new Thread(r, name); thread.setPriority(Thread.NORM_PRIORITY); @@ -50,6 +53,7 @@ public class JobSchedulerImpl extends JobScheduler implements Disposable { return ourQueue.size(); } + @Override public void dispose() { ((ThreadPoolExecutor)getScheduler()).getQueue().clear(); } diff --git a/platform/platform-impl/src/com/intellij/concurrency/PrioritizedFutureTask.java b/platform/platform-impl/src/com/intellij/concurrency/PrioritizedFutureTask.java index 1a7882189a97..0b6646fedd86 100644 --- a/platform/platform-impl/src/com/intellij/concurrency/PrioritizedFutureTask.java +++ b/platform/platform-impl/src/com/intellij/concurrency/PrioritizedFutureTask.java @@ -22,6 +22,7 @@ package com.intellij.concurrency; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.application.impl.ApplicationImpl; import com.intellij.openapi.diagnostic.Logger; +import org.jetbrains.annotations.NotNull; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; @@ -60,6 +61,7 @@ class PrioritizedFutureTask extends FutureTask implements Comparable extends FutureTask implements Comparable Date: Mon, 5 Aug 2013 18:26:09 +0400 Subject: [PATCH 07/62] cleanup --- .../src/com/intellij/concurrency/JobSchedulerImpl.java | 8 ++++---- .../com/intellij/concurrency/PrioritizedFutureTask.java | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/concurrency/JobSchedulerImpl.java b/platform/platform-impl/src/com/intellij/concurrency/JobSchedulerImpl.java index ff2270325cab..366615108899 100644 --- a/platform/platform-impl/src/com/intellij/concurrency/JobSchedulerImpl.java +++ b/platform/platform-impl/src/com/intellij/concurrency/JobSchedulerImpl.java @@ -62,8 +62,8 @@ public class JobSchedulerImpl extends JobScheduler implements Disposable { return ourQueue.poll(); } - static void submitTask(PrioritizedFutureTask future, boolean callerHasReadAccess, boolean reportExceptions) { - future.beforeRun(callerHasReadAccess, reportExceptions); + static void submitTask(@NotNull PrioritizedFutureTask future, boolean runInReadAction, boolean reportExceptions) { + future.beforeRun(runInReadAction, reportExceptions); ourExecutor.executeTask(future); } @@ -72,12 +72,12 @@ public class JobSchedulerImpl extends JobScheduler implements Disposable { super(CORES_COUNT, Integer.MAX_VALUE, 60 * 10, TimeUnit.SECONDS, ourQueue, WORKERS_FACTORY); } - private void executeTask(final PrioritizedFutureTask task) { + private void executeTask(@NotNull PrioritizedFutureTask task) { super.execute(task); } @Override - public void execute(Runnable command) { + public void execute(@NotNull Runnable command) { throw new IllegalStateException("Use executeTask() to submit PrioritizedFutureTasks only"); } } diff --git a/platform/platform-impl/src/com/intellij/concurrency/PrioritizedFutureTask.java b/platform/platform-impl/src/com/intellij/concurrency/PrioritizedFutureTask.java index 0b6646fedd86..799750ed5339 100644 --- a/platform/platform-impl/src/com/intellij/concurrency/PrioritizedFutureTask.java +++ b/platform/platform-impl/src/com/intellij/concurrency/PrioritizedFutureTask.java @@ -36,7 +36,7 @@ class PrioritizedFutureTask extends FutureTask implements Comparable callable, @@ -53,8 +53,8 @@ class PrioritizedFutureTask extends FutureTask implements Comparable extends FutureTask implements Comparable Date: Tue, 6 Aug 2013 13:55:45 +0400 Subject: [PATCH 08/62] test --- .../testFramework/vcs/DirectoryData.java | 24 +++++++++++++------ .../testFramework/vcs/DirectoryDataTest.java | 5 ++-- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/DirectoryData.java b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/DirectoryData.java index 51581d21050c..ddf8a91d443e 100644 --- a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/DirectoryData.java +++ b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/DirectoryData.java @@ -16,11 +16,10 @@ package com.intellij.testFramework.vcs; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ui.UIUtil; -import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -55,10 +54,14 @@ public class DirectoryData { } public void clear() { - final File ioFile = new File(getBase().getPath()); - final File[] files = ioFile.listFiles(); - for (File file : files) { - FileUtil.delete(file); + final VirtualFile base = getBase(); + if (base != null) { + new WriteCommandAction.Simple(null) { + @Override + protected void run() throws Throwable { + base.delete(this); + } + }.execute().throwException(); } } @@ -70,7 +73,14 @@ public class DirectoryData { final List currentLevel = new ArrayList(); final List nextLevel = new ArrayList(); - currentLevel.add(myBase.createChildDirectory(this, "dirData")); + try { + myBase.createChildDirectory(this, "dirData"); + } + catch (IOException ignored) { + } + VirtualFile newBase = getBase(); + assert newBase != null; + currentLevel.add(newBase); for (int i = 0; i < myLevels; i++) { for (VirtualFile file : currentLevel) { String numberInRow; diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/DirectoryDataTest.java b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/DirectoryDataTest.java index 188c14309501..eefb67dbe920 100644 --- a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/DirectoryDataTest.java +++ b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/DirectoryDataTest.java @@ -31,8 +31,8 @@ public class DirectoryDataTest extends FileBasedTest { @Test public void testQuadro() throws Exception { final DirectoryData data = new DirectoryData(myProject.getBaseDir(), 2, 2, ".txt"); + data.clear(); try { - data.clear(); data.create(); final String[] dirs = {"DL0N0", "DL0N1"}; @@ -51,7 +51,8 @@ public class DirectoryDataTest extends FileBasedTest { Assert.assertTrue(vFile.exists()); Assert.assertTrue(! vFile.isDirectory()); } - } finally { + } + finally { data.clear(); } } From f08f87094b2195dc079cbd999f97687c718f73a5 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 6 Aug 2013 13:57:57 +0400 Subject: [PATCH 09/62] performance: run one progress per chunk, tune jobs --- .../src/com/intellij/concurrency/Job.java | 57 +++++++++++++++- .../com/intellij/concurrency/JobLauncher.java | 9 +++ .../core/CoreApplicationEnvironment.java | 16 ++++- .../daemon/impl/PassExecutorService.java | 2 +- .../src/com/intellij/concurrency/JobImpl.java | 35 ++++------ .../intellij/concurrency/JobLauncherImpl.java | 68 +++++++++++-------- 6 files changed, 129 insertions(+), 58 deletions(-) diff --git a/platform/core-api/src/com/intellij/concurrency/Job.java b/platform/core-api/src/com/intellij/concurrency/Job.java index 6c3bd3cd505e..488ec8aa6947 100644 --- a/platform/core-api/src/com/intellij/concurrency/Job.java +++ b/platform/core-api/src/com/intellij/concurrency/Job.java @@ -19,6 +19,8 @@ */ package com.intellij.concurrency; +import org.jetbrains.annotations.NotNull; + import java.util.List; import java.util.concurrent.Callable; @@ -28,11 +30,11 @@ public interface Job { String getTitle(); - void addTask(Callable task); + void addTask(@NotNull Callable task); - void addTask(Runnable task, T result); + void addTask(@NotNull Runnable task, T result); - void addTask(Runnable task); + void addTask(@NotNull Runnable task); List scheduleAndWaitForResults() throws Throwable; @@ -43,4 +45,53 @@ public interface Job { void schedule(); boolean isDone(); + + + @NotNull + Job NULL_JOB = new Job() { + @Override + public boolean isDone() { + return true; + } + + @Override + public void cancel() { + } + + @Override + public String getTitle() { + return null; + } + + @Override + public void addTask(@NotNull Callable task) { + + } + + @Override + public void addTask(@NotNull Runnable task, Object result) { + + } + + @Override + public void addTask(@NotNull Runnable task) { + + } + + @Override + public List scheduleAndWaitForResults() throws Throwable { + return null; + } + + @Override + public boolean isCanceled() { + return false; + } + + @Override + public void schedule() { + + } + }; + } \ No newline at end of file diff --git a/platform/core-api/src/com/intellij/concurrency/JobLauncher.java b/platform/core-api/src/com/intellij/concurrency/JobLauncher.java index d517356deb67..461e57fbb05b 100644 --- a/platform/core-api/src/com/intellij/concurrency/JobLauncher.java +++ b/platform/core-api/src/com/intellij/concurrency/JobLauncher.java @@ -50,14 +50,23 @@ public abstract class JobLauncher { boolean failFastOnAcquireReadAction, @NotNull Processor thingProcessor) throws ProcessCanceledException; + public abstract boolean invokeConcurrentlyUnderProgress(@NotNull List things, + ProgressIndicator progress, + boolean runInReadAction, + boolean failFastOnAcquireReadAction, + @NotNull Processor thingProcessor); + + @NotNull public abstract AsyncFuture invokeConcurrentlyUnderProgressAsync(@NotNull List things, ProgressIndicator progress, boolean failFastOnAcquireReadAction, @NotNull Processor thingProcessor); + @NotNull public abstract Job submitToJobThread(int priority, @NotNull final Runnable action, @Nullable Consumer onDoneCallback); + @NotNull public Job submitToJobThread(int priority, @NotNull final Runnable action) { return submitToJobThread(priority, action, null); } diff --git a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java index 3a2839c71937..fed68c5688bc 100644 --- a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java +++ b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java @@ -152,6 +152,16 @@ public class CoreApplicationEnvironment { return true; } + @Override + public boolean invokeConcurrentlyUnderProgress(@NotNull List things, + ProgressIndicator progress, + boolean runInReadAction, + boolean failFastOnAcquireReadAction, + @NotNull Processor thingProcessor) { + return invokeConcurrentlyUnderProgress(things, progress, failFastOnAcquireReadAction, thingProcessor); + } + + @NotNull @Override public AsyncFuture invokeConcurrentlyUnderProgressAsync(@NotNull List things, ProgressIndicator progress, @@ -161,12 +171,14 @@ public class CoreApplicationEnvironment { try { final boolean result = invokeConcurrentlyUnderProgress(things, progress, failFastOnAcquireReadAction, thingProcessor); asyncFutureResult.set(result); - } catch (Throwable t) { + } + catch (Throwable t) { asyncFutureResult.setException(t); } return asyncFutureResult; } + @NotNull @Override public Job submitToJobThread(int priority, @NotNull Runnable action, Consumer onDoneCallback) { action.run(); @@ -197,7 +209,7 @@ public class CoreApplicationEnvironment { return null; } }); - return null; + return Job.NULL_JOB; } }; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java index a7222151a6a8..dba116f66eaf 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java @@ -189,7 +189,7 @@ public abstract class PassExecutorService implements Disposable { log(updateProgress, null, "---------------------starting------------------------ " + threadsToStartCountdown.get(), freePasses); for (ScheduledPass dependentPass : dependentPasses) { - mySubmittedPasses.put(dependentPass, JobImpl.NULL_JOB); + mySubmittedPasses.put(dependentPass, Job.NULL_JOB); } for (ScheduledPass freePass : freePasses) { submit(freePass); diff --git a/platform/platform-impl/src/com/intellij/concurrency/JobImpl.java b/platform/platform-impl/src/com/intellij/concurrency/JobImpl.java index eb2a165a5d97..9a7541c11187 100644 --- a/platform/platform-impl/src/com/intellij/concurrency/JobImpl.java +++ b/platform/platform-impl/src/com/intellij/concurrency/JobImpl.java @@ -39,21 +39,6 @@ public class JobImpl implements Job { private volatile boolean scheduled; private final boolean myFailFastOnAcquireReadAction; - public static final Job NULL_JOB = new JobImpl(0,false) { - @Override - public boolean isDone() { - return true; - } - - @Override - public void waitForTermination() throws Throwable { - } - - @Override - public void cancel() { - } - }; - JobImpl(int priority, boolean failFastOnAcquireReadAction) { myPriority = priority; myFailFastOnAcquireReadAction = failFastOnAcquireReadAction; @@ -65,17 +50,17 @@ public class JobImpl implements Job { } @Override - public void addTask(Callable task) { + public void addTask(@NotNull Callable task) { addTask(task, null); } @Override - public void addTask(Runnable task, T result) { + public void addTask(@NotNull Runnable task, T result) { addTask(Executors.callable(task, result)); } @Override - public void addTask(Runnable task) { + public void addTask(@NotNull Runnable task) { addTask(Executors.callable(task, (T)null)); } @@ -105,7 +90,11 @@ public class JobImpl implements Job { checkCanSchedule(); final Application application = ApplicationManager.getApplication(); boolean callerHasReadAccess = application != null && application.isReadAccessAllowed(); + scheduleAndWaitForResults(callerHasReadAccess); + return null; + } + public void scheduleAndWaitForResults(boolean runInReadAction) throws Throwable { // Don't bother scheduling if we only have one processor or only one task boolean reallySchedule; PrioritizedFutureTask[] tasks = getTasks(); @@ -118,10 +107,10 @@ public class JobImpl implements Job { for (PrioritizedFutureTask future : tasks) { future.run(); } - return null; + return; } - submitTasks(tasks, callerHasReadAccess, false); + submitTasks(tasks, runInReadAction, false); // in case of imbalanced tasks one huge task can stuck running and we would fall to waitForTermination instead of doing useful work //// http://gafter.blogspot.com/2006/11/thread-pool-puzzler.html @@ -137,7 +126,6 @@ public class JobImpl implements Job { } waitForTermination(); - return null; } public void waitForTermination() throws Throwable { @@ -208,6 +196,7 @@ public class JobImpl implements Job { submitTasks(tasks, false, true); } + @NotNull public PrioritizedFutureTask[] getTasks() { PrioritizedFutureTask[] tasks; synchronized (myFutures) { @@ -244,9 +233,9 @@ public class JobImpl implements Job { } } - private static void submitTasks(PrioritizedFutureTask[] tasks, boolean callerHasReadAccess, boolean reportExceptions) { + private static void submitTasks(@NotNull PrioritizedFutureTask[] tasks, boolean runInReadAction, boolean reportExceptions) { for (final PrioritizedFutureTask future : tasks) { - JobSchedulerImpl.submitTask(future, callerHasReadAccess, reportExceptions); + JobSchedulerImpl.submitTask(future, runInReadAction, reportExceptions); } } diff --git a/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java b/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java index 8a0d01c8b5dd..ee5379e4b794 100644 --- a/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java +++ b/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java @@ -15,7 +15,7 @@ */ package com.intellij.concurrency; -import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; @@ -32,37 +32,44 @@ import java.util.concurrent.Future; * @author cdr */ public class JobLauncherImpl extends JobLauncher { - private static final Logger LOG = Logger.getInstance("#com.intellij.concurrency.JobLauncher"); - private static boolean invokeConcurrentlyForAll(@NotNull final List things, + boolean runInReadAction, boolean failFastOnAcquireReadAction, - @NotNull final Processor thingProcessor) throws ProcessCanceledException { - final Job job = new JobImpl(Job.DEFAULT_PRIORITY, failFastOnAcquireReadAction); + @NotNull final Processor thingProcessor, + final ProgressWrapper wrapper) throws ProcessCanceledException { + final JobImpl job = new JobImpl(Job.DEFAULT_PRIORITY, failFastOnAcquireReadAction); - final int chunkSize = Math.max(1, things.size() / JobSchedulerImpl.CORES_COUNT / 20); + final int chunkSize = Math.max(1, things.size() / Math.max(1, JobSchedulerImpl.CORES_COUNT / 2)); for (int i = 0; i < things.size(); i += chunkSize) { // this job chunk is i..i+chunkSize-1 final int finalI = i; job.addTask(new Runnable() { + @Override public void run() { - try { - for (int k = finalI; k < finalI + chunkSize && k < things.size(); k++) { - T thing = things.get(k); - if (!thingProcessor.process(thing)) { - job.cancel(); - break; + ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() { + @Override + public void run() { + try { + for (int k = finalI; k < finalI + chunkSize && k < things.size(); k++) { + T thing = things.get(k); + if (!thingProcessor.process(thing)) { + job.cancel(); + break; + } + } } + catch (ProcessCanceledException e) { + job.cancel(); + throw e; + } + } - } - catch (ProcessCanceledException e) { - job.cancel(); - throw e; - } + }, wrapper); } }); } try { - job.scheduleAndWaitForResults(); + job.scheduleAndWaitForResults(runInReadAction); } catch (RuntimeException e) { job.cancel(); @@ -80,6 +87,16 @@ public class JobLauncherImpl extends JobLauncher { ProgressIndicator progress, boolean failFastOnAcquireReadAction, @NotNull final Processor thingProcessor) throws ProcessCanceledException { + return invokeConcurrentlyUnderProgress(things, progress, ApplicationManager.getApplication().isReadAccessAllowed(), + failFastOnAcquireReadAction, thingProcessor); + } + + @Override + public boolean invokeConcurrentlyUnderProgress(@NotNull List things, + ProgressIndicator progress, + boolean runInReadAction, + boolean failFastOnAcquireReadAction, + @NotNull Processor thingProcessor) { if (things.isEmpty()) { return true; } @@ -90,20 +107,11 @@ public class JobLauncherImpl extends JobLauncher { // can be already wrapped final ProgressWrapper wrapper = progress instanceof ProgressWrapper ? (ProgressWrapper)progress : ProgressWrapper.wrap(progress); - return invokeConcurrentlyForAll(things, failFastOnAcquireReadAction, new Processor() { - public boolean process(final T t) { - final boolean[] result = new boolean[1]; - ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() { - public void run() { - result[0] = thingProcessor.process(t); - } - }, wrapper); - return result[0]; - } - }); + return invokeConcurrentlyForAll(things, runInReadAction, failFastOnAcquireReadAction, thingProcessor, wrapper); } // This implementation is not really async + @NotNull @Override public AsyncFutureResult invokeConcurrentlyUnderProgressAsync(@NotNull List things, ProgressIndicator progress, @@ -120,10 +128,12 @@ public class JobLauncherImpl extends JobLauncher { return asyncFutureResult; } + @NotNull @Override public Job submitToJobThread(int priority, @NotNull final Runnable action, Consumer onDoneCallback) { final JobImpl job = new JobImpl(priority, false); Callable callable = new Callable() { + @Override public Void call() throws Exception { try { action.run(); From 07f25cb92e892a97c06200f265d9f06c171061fa Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 6 Aug 2013 13:58:58 +0400 Subject: [PATCH 10/62] introduced core-dependent interface --- .../util/AbstractProgressIndicatorBase.java | 33 ++++++++++++----- .../util/ProgressIndicatorStacked.java | 36 +++++++++++++++++++ .../progress/util/ProgressIndicatorBase.java | 16 +++------ .../openapi/wm/ex/ProgressIndicatorEx.java | 19 ++-------- 4 files changed, 69 insertions(+), 35 deletions(-) create mode 100644 platform/core-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorStacked.java diff --git a/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java b/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java index f8b660c7c60e..d548fd2412b2 100644 --- a/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java +++ b/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java @@ -28,7 +28,7 @@ import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -public class AbstractProgressIndicatorBase extends UserDataHolderBase implements ProgressIndicator { +public class AbstractProgressIndicatorBase extends UserDataHolderBase implements ProgressIndicatorStacked { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.progress.util.ProgressIndicatorBase"); private volatile String myText; @@ -41,10 +41,10 @@ public class AbstractProgressIndicatorBase extends UserDataHolderBase implements private volatile boolean myIndeterminate; - protected Stack myTextStack; - protected DoubleArrayList myFractionStack; - protected Stack myText2Stack; - protected volatile int myNonCancelableCount; + private Stack myTextStack; + private DoubleArrayList myFractionStack; + private Stack myText2Stack; + private volatile int myNonCancelableCount; protected ProgressIndicator myModalityProgress; private volatile ModalityState myModalityState = ModalityState.NON_MODAL; @@ -214,6 +214,7 @@ public class AbstractProgressIndicatorBase extends UserDataHolderBase implements return isModal(); } + @Override public synchronized void initStateFrom(@NotNull final ProgressIndicator indicator) { myRunning = indicator.isRunning(); myCanceled = indicator.isCanceled(); @@ -224,26 +225,42 @@ public class AbstractProgressIndicatorBase extends UserDataHolderBase implements myText2 = indicator.getText2(); myFraction = indicator.getFraction(); + + if (indicator instanceof ProgressIndicatorStacked) { + ProgressIndicatorStacked stacked = (ProgressIndicatorStacked)indicator; + + myNonCancelableCount = stacked.getNonCancelableCount(); + + myTextStack = new Stack(stacked.getTextStack()); + + myText2Stack = new Stack(stacked.getText2Stack()); + + myFractionStack = new DoubleArrayList(stacked.getFractionStack()); + } } + @Override @NotNull - public Stack getTextStack() { + public synchronized Stack getTextStack() { if (myTextStack == null) myTextStack = new Stack(2); return myTextStack; } + @Override @NotNull - public DoubleArrayList getFractionStack() { + public synchronized DoubleArrayList getFractionStack() { if (myFractionStack == null) myFractionStack = new DoubleArrayList(2); return myFractionStack; } + @Override @NotNull - public Stack getText2Stack() { + public synchronized Stack getText2Stack() { if (myText2Stack == null) myText2Stack = new Stack(2); return myText2Stack; } + @Override public int getNonCancelableCount() { return myNonCancelableCount; } diff --git a/platform/core-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorStacked.java b/platform/core-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorStacked.java new file mode 100644 index 000000000000..09f21405bba4 --- /dev/null +++ b/platform/core-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorStacked.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.progress.util; + +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.util.containers.DoubleArrayList; +import com.intellij.util.containers.Stack; +import org.jetbrains.annotations.NotNull; + +public interface ProgressIndicatorStacked extends ProgressIndicator { + void initStateFrom(@NotNull ProgressIndicator indicator); + + @NotNull + Stack getTextStack(); + + @NotNull + DoubleArrayList getFractionStack(); + + @NotNull + Stack getText2Stack(); + + int getNonCancelableCount(); +} diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java index 99987ccaa0de..4ebb496bbc12 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java @@ -17,12 +17,11 @@ package com.intellij.openapi.progress.util; import com.intellij.openapi.application.impl.LaterInvocator; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.TaskInfo; import com.intellij.openapi.progress.impl.ProgressManagerImpl; import com.intellij.openapi.wm.ex.ProgressIndicatorEx; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.DoubleArrayList; -import com.intellij.util.containers.Stack; import com.intellij.util.containers.WeakList; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -330,16 +329,11 @@ public class ProgressIndicatorBase extends AbstractProgressIndicatorBase impleme } @Override - public synchronized void initStateFrom(@NotNull final ProgressIndicatorEx indicator) { + public synchronized void initStateFrom(@NotNull final ProgressIndicator indicator) { super.initStateFrom(indicator); - myModalityEntered = indicator.isModalityEntered(); - myNonCancelableCount = indicator.getNonCancelableCount(); - - myTextStack = new Stack(indicator.getTextStack()); - - myText2Stack = new Stack(indicator.getText2Stack()); - - myFractionStack = new DoubleArrayList(indicator.getFractionStack()); + if (indicator instanceof ProgressIndicatorEx) { + myModalityEntered = ((ProgressIndicatorEx)indicator).isModalityEntered(); + } } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/ProgressIndicatorEx.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/ProgressIndicatorEx.java index d3a687e4d105..9c05fd1a6da3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/ProgressIndicatorEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/ProgressIndicatorEx.java @@ -15,30 +15,17 @@ */ package com.intellij.openapi.wm.ex; -import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.TaskInfo; -import com.intellij.util.containers.DoubleArrayList; -import com.intellij.util.containers.Stack; +import com.intellij.openapi.progress.util.ProgressIndicatorStacked; import org.jetbrains.annotations.NotNull; -public interface ProgressIndicatorEx extends ProgressIndicator { - +public interface ProgressIndicatorEx extends ProgressIndicatorStacked { void addStateDelegate(@NotNull ProgressIndicatorEx delegate); - void initStateFrom(@NotNull ProgressIndicatorEx indicator); - - @NotNull Stack getTextStack(); - - @NotNull DoubleArrayList getFractionStack(); - - @NotNull Stack getText2Stack(); - - int getNonCancelableCount(); - boolean isModalityEntered(); void finish(@NotNull TaskInfo task); - + boolean isFinished(@NotNull TaskInfo task); boolean wasStarted(); From 3ceecbed75a7636635f39b26f46188985e5706a7 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 6 Aug 2013 14:00:11 +0400 Subject: [PATCH 11/62] commit injected doc during formatting --- .../psi/impl/PsiDocumentManagerBase.java | 19 ++++++++++++------- .../psi/impl/PsiToDocumentSynchronizer.java | 16 ++++++++-------- .../psi/impl/DocumentCommitThread.java | 13 ++++++------- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java index 41768cf6f706..cbe001745488 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java @@ -45,6 +45,7 @@ import com.intellij.util.SystemProperties; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBus; +import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -61,7 +62,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen protected final Project myProject; protected final PsiManager myPsiManager; protected final DocumentCommitProcessor myDocumentCommitProcessor; - protected final Set myUncommittedDocuments = Collections.synchronizedSet(new HashSet()); + protected final Set myUncommittedDocuments = Collections.synchronizedSet(new THashSet()); protected volatile boolean myIsCommitInProgress; protected final PsiToDocumentSynchronizer mySynchronizer; @@ -361,7 +362,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen finally { myIsCommitInProgress = false; } - assert !myUncommittedDocuments.contains(document) : "Document :" + document; + assert !isInUncommittedSet(document) : "Document :" + document; } }); } @@ -540,8 +541,9 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen return myUncommittedDocuments.toArray(new Document[myUncommittedDocuments.size()]); } - public Collection getUncommittedDocumentsUnsafe() { - return myUncommittedDocuments; + boolean isInUncommittedSet(@NotNull Document document) { + if (document instanceof DocumentWindow) return isInUncommittedSet(((DocumentWindow)document).getDelegate()); + return myUncommittedDocuments.contains(document); } @Override @@ -551,8 +553,9 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen @Override public boolean isCommitted(@NotNull Document document) { + if (document instanceof DocumentWindow) return isCommitted(((DocumentWindow)document).getDelegate()); if (getSynchronizer().isInSynchronization(document)) return true; - return !((DocumentEx)document).isInEventsHandling() && !myUncommittedDocuments.contains(document); + return !((DocumentEx)document).isInEventsHandling() && !isInUncommittedSet(document); } @Override @@ -603,7 +606,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen boolean commitNecessary = true; for (PsiFile file : files) { mySmartPointerManager.unfastenBelts(file, event.getOffset()); - + final TextBlock textBlock = TextBlock.get(file); if (textBlock.isLocked()) { commitNecessary = false; @@ -634,10 +637,12 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen } if (commitNecessary) { + assert !(document instanceof DocumentWindow); myUncommittedDocuments.add(document); if (forceCommit) { commitDocument(document); - } else if (!((DocumentEx)document).isInBulkUpdate()) { + } + else if (!((DocumentEx)document).isInBulkUpdate()) { myDocumentCommitProcessor.commitAsynchronously(myProject, document, event); } } diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java b/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java index 0d7e1dde2697..05dc16fbca56 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java @@ -53,7 +53,7 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter { return pair != null ? pair.getFirst() : null; } - public boolean isInSynchronization(final Document document) { + public boolean isInSynchronization(@NotNull Document document) { return mySyncDocument == document; } @@ -64,7 +64,7 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter { } private interface DocSyncAction { - void syncDocument(Document document, PsiTreeChangeEventImpl event); + void syncDocument(@NotNull Document document, @NotNull PsiTreeChangeEventImpl event); } private void doSync(@NotNull final PsiTreeChangeEvent event, boolean force, @NotNull final DocSyncAction syncAction) { @@ -107,7 +107,7 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter { if (!(event.getChild() instanceof ForeignLeafPsiElement)) { doSync(event, false, new DocSyncAction() { @Override - public void syncDocument(Document document, PsiTreeChangeEventImpl event) { + public void syncDocument(@NotNull Document document, @NotNull PsiTreeChangeEventImpl event) { insertString(document, event.getOffset(), event.getChild().getText()); } }); @@ -119,7 +119,7 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter { if (!(event.getChild() instanceof ForeignLeafPsiElement)) { doSync(event, false, new DocSyncAction() { @Override - public void syncDocument(Document document, PsiTreeChangeEventImpl event) { + public void syncDocument(@NotNull Document document, @NotNull PsiTreeChangeEventImpl event) { deleteString(document, event.getOffset(), event.getOffset() + event.getOldLength()); } }); @@ -130,7 +130,7 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter { public void childReplaced(@NotNull final PsiTreeChangeEvent event) { doSync(event, false, new DocSyncAction() { @Override - public void syncDocument(Document document, PsiTreeChangeEventImpl event) { + public void syncDocument(@NotNull Document document, @NotNull PsiTreeChangeEventImpl event) { int oldLength = event.getOldChild() instanceof ForeignLeafPsiElement ? 0 : event.getOldLength(); String newText = event.getNewChild() instanceof ForeignLeafPsiElement ? "" : event.getNewChild().getText(); replaceString(document, event.getOffset(), event.getOffset() + oldLength, newText); @@ -142,7 +142,7 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter { public void childrenChanged(@NotNull final PsiTreeChangeEvent event) { doSync(event, false, new DocSyncAction() { @Override - public void syncDocument(Document document, PsiTreeChangeEventImpl event) { + public void syncDocument(@NotNull Document document, @NotNull PsiTreeChangeEventImpl event) { replaceString(document, event.getOffset(), event.getOffset() + event.getOldLength(), event.getParent().getText()); } }); @@ -209,7 +209,7 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter { fakeEvent.setFile(changeScope.getContainingFile()); doSync(fakeEvent, true, new DocSyncAction() { @Override - public void syncDocument(Document document, PsiTreeChangeEventImpl event) { + public void syncDocument(@NotNull Document document, @NotNull PsiTreeChangeEventImpl event) { doCommitTransaction(document, documentChangeTransaction); } }); @@ -220,7 +220,7 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter { } return true; } - + @TestOnly public void doCommitTransaction(@NotNull Document document){ doCommitTransaction(document, getTransaction(document)); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java index ccd637d91d76..174903be0b0d 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java @@ -159,10 +159,10 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run } } if (task != null) { - Collection unc = task.project.isDisposed() ? Collections.emptyList() : - ((PsiDocumentManagerImpl)PsiDocumentManager.getInstance(task.project)).getUncommittedDocumentsUnsafe(); - if (!unc.isEmpty()) { - s += "; Uncommitted: " + unc; + boolean stillUncommitted = !task.project.isDisposed() && + ((PsiDocumentManagerImpl)PsiDocumentManager.getInstance(task.project)).isInUncommittedSet(task.document); + if (stillUncommitted) { + s += "; Uncommitted: " + task.document; } } @@ -267,7 +267,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run log("Pulled", task, false, indicator); - if (project.isDisposed() || !((PsiDocumentManagerImpl)PsiDocumentManager.getInstance(project)).getUncommittedDocumentsUnsafe().contains(document)) { + if (project.isDisposed() || !((PsiDocumentManagerImpl)PsiDocumentManager.getInstance(project)).isInUncommittedSet(document)) { log("Abandon and proceed to next",task, false); return; } @@ -469,10 +469,9 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run if (synchronously) { assert success; } - Collection unc = documentManager.getUncommittedDocumentsUnsafe(); log("after call finishCommit",task, synchronously, success); if (synchronously || success) { - assert !unc.contains(document) : unc; + assert !documentManager.isInUncommittedSet(document); } if (!success) { // add document back to the queue From 9614979b8ca3194d4f87c5b344e4bc8e3a7854c6 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 6 Aug 2013 14:07:32 +0400 Subject: [PATCH 12/62] fix: compute real namespace by namespace key --- .../xml/impl/dom/DomAttributeXmlDescriptor.java | 10 ++++++++-- .../XmlAttributeReferenceCompletionProvider.java | 2 +- .../xml/NamespaceAwareXmlAttributeDescriptor.java | 4 +++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/xml/dom-impl/src/com/intellij/xml/impl/dom/DomAttributeXmlDescriptor.java b/xml/dom-impl/src/com/intellij/xml/impl/dom/DomAttributeXmlDescriptor.java index 8751f8ac8114..eee6ed52e305 100644 --- a/xml/dom-impl/src/com/intellij/xml/impl/dom/DomAttributeXmlDescriptor.java +++ b/xml/dom-impl/src/com/intellij/xml/impl/dom/DomAttributeXmlDescriptor.java @@ -27,6 +27,7 @@ import com.intellij.util.xml.reflect.DomAttributeChildDescription; import com.intellij.xml.NamespaceAwareXmlAttributeDescriptor; import com.intellij.xml.util.XmlUtil; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -115,8 +116,13 @@ public class DomAttributeXmlDescriptor implements NamespaceAwareXmlAttributeDesc } @Nullable - public String getNamespace() { - return myDescription.getXmlName().getNamespaceKey(); + public String getNamespace(@NotNull XmlTag context) { + final DomInvocationHandler handler = DomManagerImpl.getDomManager(myProject).getDomHandler(context); + + if (handler == null) { + return null; + } + return handler.createEvaluatedXmlName(myDescription.getXmlName()).getNamespace(context, handler.getFile()); } public void init(final PsiElement element) { diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeReferenceCompletionProvider.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeReferenceCompletionProvider.java index c195d412b026..b4b629afccdb 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeReferenceCompletionProvider.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeReferenceCompletionProvider.java @@ -91,7 +91,7 @@ public class XmlAttributeReferenceCompletionProvider extends CompletionProvider< insertHandler = replacementInsertHandler; } else if (descriptor instanceof NamespaceAwareXmlAttributeDescriptor) { - final String namespace = ((NamespaceAwareXmlAttributeDescriptor)descriptor).getNamespace(); + final String namespace = ((NamespaceAwareXmlAttributeDescriptor)descriptor).getNamespace(tag); if (file instanceof XmlFile && namespace != null && diff --git a/xml/xml-psi-impl/src/com/intellij/xml/NamespaceAwareXmlAttributeDescriptor.java b/xml/xml-psi-impl/src/com/intellij/xml/NamespaceAwareXmlAttributeDescriptor.java index d0e00517186d..6ef32524fe8b 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/NamespaceAwareXmlAttributeDescriptor.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/NamespaceAwareXmlAttributeDescriptor.java @@ -1,5 +1,7 @@ package com.intellij.xml; +import com.intellij.psi.xml.XmlTag; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -7,5 +9,5 @@ import org.jetbrains.annotations.Nullable; */ public interface NamespaceAwareXmlAttributeDescriptor extends XmlAttributeDescriptor { @Nullable - String getNamespace(); + String getNamespace(@NotNull XmlTag context); } From ce19f3866183ff6a8dd4a4761895f0feae6ab6f6 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 6 Aug 2013 15:00:30 +0400 Subject: [PATCH 13/62] optimization: ExtendedTagInsertHandler.suggestPrefix may be expensive, so move its invocation to insert handler --- .../completion/XmlAttributeInsertHandler.java | 74 ++++++++++++++++--- ...lAttributeReferenceCompletionProvider.java | 21 +----- 2 files changed, 64 insertions(+), 31 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeInsertHandler.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeInsertHandler.java index 296c4160c187..af533a782bdb 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeInsertHandler.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeInsertHandler.java @@ -18,16 +18,24 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.AutoPopupController; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.lang.html.HTMLLanguage; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; +import com.intellij.util.IncorrectOperationException; import com.intellij.util.text.CharArrayUtil; import com.intellij.xml.XmlNamespaceHelper; import com.intellij.xml.util.HtmlUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collections; @@ -36,26 +44,26 @@ import java.util.Collections; * @author peter */ public class XmlAttributeInsertHandler implements InsertHandler { + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.XmlAttributeInsertHandler"); + public static final XmlAttributeInsertHandler INSTANCE = new XmlAttributeInsertHandler(); - private final String myNamespacePrefixToInsert; private final String myNamespaceToInsert; public XmlAttributeInsertHandler() { - this(null, null); + this(null); } - public XmlAttributeInsertHandler(@Nullable String namespaceToInsert, @Nullable String namespacePrefixToInsert) { + public XmlAttributeInsertHandler(@Nullable String namespaceToInsert) { myNamespaceToInsert = namespaceToInsert; - myNamespacePrefixToInsert = namespacePrefixToInsert; } - public void handleInsert(InsertionContext context, LookupElement item) { + public void handleInsert(final InsertionContext context, final LookupElement item) { final Editor editor = context.getEditor(); final Document document = editor.getDocument(); final int caretOffset = editor.getCaretModel().getOffset(); - PsiFile file = context.getFile(); + final PsiFile file = context.getFile(); if (file.getLanguage() == HTMLLanguage.INSTANCE && HtmlUtil.isSingleHtmlAttribute((String)item.getObject())) { return; @@ -88,13 +96,57 @@ public class XmlAttributeInsertHandler implements InsertHandler { AutoPopupController.getInstance(editor.getProject()).scheduleAutoPopup(editor); if (myNamespaceToInsert != null && file instanceof XmlFile) { - final XmlNamespaceHelper helper = XmlNamespaceHelper.getHelper(context.getFile()); + final PsiElement element = file.findElementAt(context.getStartOffset()); + final XmlTag tag = element != null ? PsiTreeUtil.getParentOfType(element, XmlTag.class) : null; - if (helper != null) { - PsiDocumentManager.getInstance(context.getProject()).commitDocument(document); - helper.insertNamespaceDeclaration((XmlFile)file, editor, Collections.singleton(myNamespaceToInsert), - myNamespacePrefixToInsert, null); + if (tag != null) { + String prefix = ExtendedTagInsertHandler.suggestPrefix((XmlFile)file, myNamespaceToInsert); + + if (prefix != null) { + prefix = makePrefixUnique(prefix, tag); + final XmlNamespaceHelper helper = XmlNamespaceHelper.getHelper(context.getFile()); + + if (helper != null) { + final Project project = context.getProject(); + PsiDocumentManager.getInstance(project).commitDocument(document); + qualifyWithPrefix(prefix, element); + helper.insertNamespaceDeclaration((XmlFile)file, editor, Collections.singleton( + myNamespaceToInsert), prefix, null); + } + } } } } + + private static void qualifyWithPrefix(@NotNull String namespacePrefix, @NotNull PsiElement context) { + final PsiElement parent = context.getParent(); + + if (parent instanceof XmlAttribute) { + final XmlAttribute attribute = (XmlAttribute)parent; + final String prefix = attribute.getNamespacePrefix(); + + if (!prefix.equals(namespacePrefix) && StringUtil.isNotEmpty(namespacePrefix)) { + final String name = namespacePrefix + ":" + attribute.getLocalName(); + try { + attribute.setName(name); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } + } + } + + @NotNull + private static String makePrefixUnique(@NotNull String basePrefix, @NotNull XmlTag context) { + if (context.getNamespaceByPrefix(basePrefix).isEmpty()) { + return basePrefix; + } + int i = 1; + + while (!context.getNamespaceByPrefix(basePrefix + i).isEmpty()) { + i++; + } + return basePrefix + i; + } } diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeReferenceCompletionProvider.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeReferenceCompletionProvider.java index b4b629afccdb..6b0debbb8896 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeReferenceCompletionProvider.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlAttributeReferenceCompletionProvider.java @@ -98,13 +98,7 @@ public class XmlAttributeReferenceCompletionProvider extends CompletionProvider< namespace.length() > 0 && !name.contains(":") && tag.getPrefixByNamespace(namespace) == null) { - String suggestedPrefix = ExtendedTagInsertHandler.suggestPrefix((XmlFile)file, namespace); - - if (suggestedPrefix != null) { - suggestedPrefix = makePrefixUnique(suggestedPrefix, tag); - name = suggestedPrefix + ":" + name; - insertHandler = new XmlAttributeInsertHandler(namespace, suggestedPrefix); - } + insertHandler = new XmlAttributeInsertHandler(namespace); } } if (prefix == null || name.startsWith(prefix)) { @@ -129,19 +123,6 @@ public class XmlAttributeReferenceCompletionProvider extends CompletionProvider< } } - @NotNull - private static String makePrefixUnique(@NotNull String basePrefix, @NotNull XmlTag context) { - if (context.getNamespaceByPrefix(basePrefix).isEmpty()) { - return basePrefix; - } - int i = 1; - - while (!context.getNamespaceByPrefix(basePrefix + i).isEmpty()) { - i++; - } - return basePrefix + i; - } - private static boolean isValidVariant(XmlAttribute attribute, @NotNull XmlAttributeDescriptor descriptor, final XmlAttribute[] attributes, From 8744e8b2d33e4804ae180f316f441f8fdb073b59 Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Tue, 6 Aug 2013 15:19:05 +0400 Subject: [PATCH 14/62] WEB-8334 Wrong caret position using Emmet inside JS string --- .../emmet/filters/SingleLineEmmetFilter.java | 8 +++ .../template/emmet/nodes/GenerationNode.java | 60 ++++++++++++------- 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/SingleLineEmmetFilter.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/SingleLineEmmetFilter.java index c3556448ecfd..acd047a26d1f 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/SingleLineEmmetFilter.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/SingleLineEmmetFilter.java @@ -16,8 +16,10 @@ package com.intellij.codeInsight.template.emmet.filters; import com.intellij.codeInsight.template.emmet.nodes.GenerationNode; +import com.intellij.codeInsight.template.emmet.tokens.TemplateToken; import com.intellij.codeInsight.template.impl.TemplateImpl; import com.intellij.lang.xml.XMLLanguage; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; @@ -32,6 +34,12 @@ public class SingleLineEmmetFilter extends ZenCodingFilter { return "s"; } + @NotNull + @Override + public String filterText(@NotNull String text, @NotNull TemplateToken token) { + return StringUtil.replace(text, "\n", ""); + } + @NotNull @Override public GenerationNode filterNode(@NotNull GenerationNode node) { diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java index e31b36ccb00b..c7ff99fac640 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java @@ -26,8 +26,11 @@ import com.intellij.codeInsight.template.emmet.generators.XmlZenCodingGeneratorI import com.intellij.codeInsight.template.emmet.generators.ZenCodingGenerator; import com.intellij.codeInsight.template.emmet.tokens.TemplateToken; import com.intellij.codeInsight.template.impl.TemplateImpl; +import com.intellij.injected.editor.DocumentWindowImpl; import com.intellij.lang.xml.XMLLanguage; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; @@ -135,23 +138,48 @@ public class GenerationNode extends UserDataHolderBase { boolean insertSurroundedText) { myContainsSurroundedTextMarker = !(insertSurroundedText && myInsertSurroundedTextAtTheEnd); - boolean singleLineFilterEnabled = false; - GenerationNode generationNode = this; + if (generationNode != this) { + return generationNode.generate(callback, generator, Collections.emptyList(), insertSurroundedText); + } + + boolean shouldNotReformatTemplate = false; + boolean oneLineTemplateExpanding = false; for (ZenCodingFilter filter : filters) { generationNode = filter.filterNode(generationNode); if(filter instanceof SingleLineEmmetFilter) { - singleLineFilterEnabled = true; + shouldNotReformatTemplate = true; + oneLineTemplateExpanding = true; } } - if (generationNode != this) { - return generationNode.generate(callback, generator, Collections.emptyList(), insertSurroundedText); + CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(callback.getProject()); + String indentStr; + if (callback.isInInjectedFragment()) { + Editor editor = callback.getEditor(); + Document document = editor.getDocument(); + if(document instanceof DocumentWindowImpl && ((DocumentWindowImpl)document).isOneLine()) { + /* + * If document is one-line that in the moment of inserting text, + * new line chars will be filtered (see DocumentWindowImpl#insertString). + * So in this case we should filter text by SingleLineAvoid in order to avoid + * inconsistency of template segments. + */ + oneLineTemplateExpanding = true; + filters.add(new SingleLineEmmetFilter()); + } + indentStr = ""; + } + else if (settings.useTabCharacter(callback.getFileType())) { + indentStr = "\t"; + } + else { + int tabSize = settings.getTabSize(callback.getFileType()); + indentStr = StringUtil.repeatSymbol(' ', tabSize); } LiveTemplateBuilder builder = new LiveTemplateBuilder(); int end = -1; - boolean hasChildren = myChildren.size() > 0; TemplateImpl parentTemplate; @@ -188,26 +216,14 @@ public class GenerationNode extends UserDataHolderBase { } LiveTemplateBuilder.Marker marker = offset < builder.length() ? builder.createMarker(offset) : null; - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(callback.getProject()); - String indentStr; - if (callback.isInInjectedFragment()) { - indentStr = ""; - } - else if (settings.useTabCharacter(callback.getFileType())) { - indentStr = "\t"; - } - else { - int tabSize = settings.getTabSize(callback.getFileType()); - indentStr = StringUtil.repeatSymbol(' ', tabSize); - } - + //noinspection ForLoopReplaceableByForEach for (int i = 0, myChildrenSize = myChildren.size(); i < myChildrenSize; i++) { GenerationNode child = myChildren.get(i); TemplateImpl childTemplate = child.generate(callback, generator, filters, !myContainsSurroundedTextMarker); boolean blockTag = child.isBlockTag(); - if (!singleLineFilterEnabled && blockTag && !isNewLineBefore(builder.getText(), offset)) { + if (!oneLineTemplateExpanding && blockTag && !isNewLineBefore(builder.getText(), offset)) { builder.insertText(offset, "\n" + indentStr, false); offset += indentStr.length() + 1; } @@ -215,7 +231,7 @@ public class GenerationNode extends UserDataHolderBase { int e = builder.insertTemplate(offset, childTemplate, null); offset = marker != null ? marker.getEndOffset() : builder.length(); - if (!singleLineFilterEnabled && ((blockTag && !isNewLineAfter(builder.getText(), offset)) || myInsertNewLineBetweenNodes)) { + if (!oneLineTemplateExpanding && ((blockTag && !isNewLineAfter(builder.getText(), offset)) || myInsertNewLineBetweenNodes)) { builder.insertText(offset, "\n" + indentStr, false); offset += indentStr.length() + 1; } @@ -224,7 +240,7 @@ public class GenerationNode extends UserDataHolderBase { end = e; } } - if(singleLineFilterEnabled) { + if(shouldNotReformatTemplate) { builder.setIsToReformat(false); } return builder.buildTemplate(); From 6a8beaed933267b1d926699af76220d72e6b3592 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 6 Aug 2013 15:09:11 +0400 Subject: [PATCH 15/62] IDEA-97264 IntelliLang support for "Path to File" language: highlighting --- .../src/com/intellij/lang/Language.java | 7 ++++++ .../intelliLang/ReferenceInjectionTest.java | 22 ++++++++++++++++ .../AbstractLanguageInjectionSupport.java | 5 ++++ .../inject/InjectLanguageAction.java | 11 +++++--- .../inject/LanguageInjectionSupport.java | 18 +------------ .../intelliLang/references/Injectable.java | 4 +++ .../InjectedReferencesContributor.java | 25 +++++++++++++++---- .../references/ReferenceInjector.java | 3 +++ .../xml/XmlLanguageInjectionSupport.java | 5 +++- 9 files changed, 74 insertions(+), 26 deletions(-) diff --git a/platform/core-api/src/com/intellij/lang/Language.java b/platform/core-api/src/com/intellij/lang/Language.java index 4c9e7ec9ecfb..c087bd24506a 100644 --- a/platform/core-api/src/com/intellij/lang/Language.java +++ b/platform/core-api/src/com/intellij/lang/Language.java @@ -221,4 +221,11 @@ public abstract class Language extends UserDataHolderBase { } return null; } + + /** Fake language identifier without registering */ + protected Language(String id, @SuppressWarnings("UnusedParameters") boolean register) { + myID = id; + myBaseLanguage = null; + myMimeTypes = null; + } } diff --git a/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java b/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java index f3890bcc67d8..4b4489bb7d25 100644 --- a/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java +++ b/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java @@ -6,6 +6,7 @@ import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCa import org.intellij.plugins.intelliLang.inject.InjectLanguageAction; import org.intellij.plugins.intelliLang.inject.UnInjectLanguageAction; import org.intellij.plugins.intelliLang.references.FileReferenceInjector; +import org.intellij.plugins.intelliLang.references.InjectedReferencesInspection; import org.jdom.Element; /** @@ -27,6 +28,10 @@ public class ReferenceInjectionTest extends LightPlatformCodeInsightFixtureTestC assertFalse(new InjectLanguageAction().isAvailable(getProject(), myFixture.getEditor(), myFixture.getFile())); assertTrue(new UnInjectLanguageAction().isAvailable(getProject(), myFixture.getEditor(), myFixture.getFile())); + myFixture.configureByText("bar.xml", "http://foo.bar\" \n" + + " xxx=\"bar\"/>"); + myFixture.testHighlighting(); + UnInjectLanguageAction.invokeImpl(getProject(), myFixture.getEditor(), myFixture.getFile()); assertNull(myFixture.getReferenceAtCaretPosition()); } @@ -60,4 +65,21 @@ public class ReferenceInjectionTest extends LightPlatformCodeInsightFixtureTestC UnInjectLanguageAction.invokeImpl(getProject(), myFixture.getEditor(), myFixture.getFile()); assertNull(myFixture.getReferenceAtCaretPosition()); } + + @Override + protected void setUp() throws Exception { + super.setUp(); + myFixture.enableInspections(new InjectedReferencesInspection()); + } + + @Override + protected void tearDown() throws Exception { + myFixture.disableInspections(new InjectedReferencesInspection()); + super.tearDown(); + } + + @Override + protected boolean isWriteActionRequired() { + return false; + } } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java index 68869a4eb445..6ba500af8a10 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java @@ -16,6 +16,7 @@ package org.intellij.plugins.intelliLang.inject; +import com.intellij.lang.Language; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.fileTypes.FileTypeManager; @@ -48,6 +49,10 @@ public abstract class AbstractLanguageInjectionSupport extends LanguageInjection return false; } + public boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement) { + return false; + } + public boolean removeInjectionInPlace(final PsiLanguageInjectionHost psiElement) { return false; } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java index 20b6b05b92ab..2f3735c5f1a5 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java @@ -17,6 +17,7 @@ package org.intellij.plugins.intelliLang.inject; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.injected.editor.EditorWindow; +import com.intellij.lang.Language; import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; @@ -26,7 +27,10 @@ import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiLanguageInjectionHost; +import com.intellij.psi.PsiManager; import com.intellij.psi.impl.PsiModificationTrackerImpl; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.ui.ListCellRendererWrapper; @@ -99,13 +103,14 @@ public class InjectLanguageAction implements IntentionAction { if (defaultFunctionalityWorked(host, injectable.getId())) return; try { + Language language = injectable.toLanguage(); for (LanguageInjectionSupport support : InjectorUtils.getActiveInjectionSupports()) { - if (support.addInjectionInPlace(injectable, host)) { + if (support.addInjectionInPlace(language, host)) { ((PsiModificationTrackerImpl)PsiManager.getInstance(project).getModificationTracker()).incCounter(); return; } } - TemporaryPlacesRegistry.getInstance(project).getLanguageInjectionSupport().addInjectionInPlace(injectable, host); + TemporaryPlacesRegistry.getInstance(project).getLanguageInjectionSupport().addInjectionInPlace(language, host); } finally { if (injectable.getLanguage() != null) { // no need for reference injection diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java index 17b704b7521d..edcd194f7683 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java @@ -28,7 +28,6 @@ import com.intellij.ui.SimpleColoredText; import com.intellij.util.Consumer; import org.intellij.plugins.intelliLang.Configuration; import org.intellij.plugins.intelliLang.inject.config.BaseInjection; -import org.intellij.plugins.intelliLang.references.Injectable; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -57,22 +56,7 @@ public abstract class LanguageInjectionSupport { public abstract boolean useDefaultInjector(final PsiElement host); - public boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement) { - return addInjectionInPlace(language.getID(), psiElement); - } - - public boolean addInjectionInPlace(final String id, final PsiLanguageInjectionHost psiElement) { - return false; - } - - public final boolean addInjectionInPlace(final Injectable injectable, final PsiLanguageInjectionHost psiElement) { - if (injectable.getLanguage() == null) { - return addInjectionInPlace(injectable.getId(), psiElement); - } - else { - return addInjectionInPlace(injectable.getLanguage(), psiElement); - } - } + public abstract boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement); public abstract boolean removeInjectionInPlace(final PsiLanguageInjectionHost psiElement); diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/Injectable.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/Injectable.java index 3cee69134201..bdb4cef4e7fc 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/Injectable.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/Injectable.java @@ -68,6 +68,10 @@ public abstract class Injectable implements Comparable { return list; } + public Language toLanguage() { + return getLanguage() == null ? new Language(getId(), false) {} : getLanguage(); + } + public static Injectable fromLanguage(final Language language) { return new Injectable() { @NotNull diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java index dfcc403378f1..a5456035b235 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java @@ -22,8 +22,10 @@ import com.intellij.psi.*; import com.intellij.util.ArrayUtil; import com.intellij.util.ProcessingContext; import org.intellij.plugins.intelliLang.Configuration; +import org.intellij.plugins.intelliLang.inject.InjectedLanguage; import org.intellij.plugins.intelliLang.inject.InjectorUtils; import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport; +import org.intellij.plugins.intelliLang.inject.TemporaryPlacesRegistry; import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,7 +39,7 @@ import java.util.List; */ public class InjectedReferencesContributor extends PsiReferenceContributor { - private static final Key INJECTED_REFERENCE = Key.create("injected reference"); + static final Key INJECTED_REFERENCE = Key.create("injected reference"); public static boolean isInjected(@Nullable PsiReference reference) { return reference != null && reference.getElement().getUserData(INJECTED_REFERENCE) != null; @@ -53,20 +55,33 @@ public class InjectedReferencesContributor extends PsiReferenceContributor { ReferenceInjector[] extensions = ReferenceInjector.EXTENSION_POINT_NAME.getExtensions(); PsiReference[] references = new PsiReference[0]; Configuration configuration = Configuration.getProjectInstance(element.getProject()); - for (ReferenceInjector extension : extensions) { - Collection injections = configuration.getInjectionsByLanguageId(extension.getId()); + for (ReferenceInjector injector : extensions) { + Collection injections = configuration.getInjectionsByLanguageId(injector.getId()); for (BaseInjection injection : injections) { if (injection.acceptForReference(element)) { - element.putUserData(INJECTED_REFERENCE, extension); + element.putUserData(INJECTED_REFERENCE, injector); LanguageInjectionSupport support = InjectorUtils.findInjectionSupport(injection.getSupportId()); element.putUserData(LanguageInjectionSupport.INJECTOR_SUPPORT, support); List area = injection.getInjectedArea(element); for (TextRange range : area) { - references = ArrayUtil.mergeArrays(references, extension.getReferences(element, context, range)); + references = ArrayUtil.mergeArrays(references, injector.getReferences(element, context, range)); } } } } + if (element instanceof PsiLanguageInjectionHost) { + TemporaryPlacesRegistry registry = TemporaryPlacesRegistry.getInstance(element.getProject()); + InjectedLanguage language = registry.getLanguageFor((PsiLanguageInjectionHost)element, element.getContainingFile()); + if (language != null) { + ReferenceInjector injector = ReferenceInjector.findById(language.getID()); + if (injector != null) { + element.putUserData(INJECTED_REFERENCE, injector); + element.putUserData(LanguageInjectionSupport.INJECTOR_SUPPORT, registry.getLanguageInjectionSupport()); + TextRange range = ElementManipulators.getValueTextRange(element); + references = ArrayUtil.mergeArrays(references, injector.getReferences(element, context, range)); + } + } + } return references; } }); diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/ReferenceInjector.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/ReferenceInjector.java index 90397bebbd67..586645fc286a 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/ReferenceInjector.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/ReferenceInjector.java @@ -38,6 +38,9 @@ public abstract class ReferenceInjector extends Injectable { return null; } + /** + * Generated references should be soft ({@link com.intellij.psi.PsiReference#isSoft()}) + */ @NotNull public abstract PsiReference[] getReferences(@NotNull PsiElement element, @NotNull final ProcessingContext context, @NotNull TextRange range); diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java index 094bcfd2a562..8ab26e303bde 100644 --- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java +++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java @@ -16,6 +16,7 @@ package org.intellij.plugins.intelliLang.inject.xml; +import com.intellij.lang.Language; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.options.Configurable; @@ -88,8 +89,10 @@ public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSuppor return false; } - public boolean addInjectionInPlace(final String id, final PsiLanguageInjectionHost psiElement) { + @Override + public boolean addInjectionInPlace(Language language, final PsiLanguageInjectionHost psiElement) { if (!isMine(psiElement)) return false; + String id = language.getID(); if (psiElement instanceof XmlAttributeValue) { return doInjectInAttributeValue((XmlAttributeValue)psiElement, id); } From 06be4ae4dc3947db9e255a9c269eb5903b74dba8 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 6 Aug 2013 15:09:31 +0400 Subject: [PATCH 16/62] IDEA-97264 IntelliLang support for "Path to File" language: highlighting --- plugins/IntelliLang/src/META-INF/plugin.xml | 3 ++ .../InjectedReferences.html | 5 ++ .../references/FileReferenceInjector.java | 7 ++- .../InjectedReferencesInspection.java | 51 +++++++++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 plugins/IntelliLang/src/inspectionDescriptions/InjectedReferences.html create mode 100644 plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesInspection.java diff --git a/plugins/IntelliLang/src/META-INF/plugin.xml b/plugins/IntelliLang/src/META-INF/plugin.xml index a7bc30e9fc9b..1e5521ac47f0 100644 --- a/plugins/IntelliLang/src/META-INF/plugin.xml +++ b/plugins/IntelliLang/src/META-INF/plugin.xml @@ -52,6 +52,9 @@ + diff --git a/plugins/IntelliLang/src/inspectionDescriptions/InjectedReferences.html b/plugins/IntelliLang/src/inspectionDescriptions/InjectedReferences.html new file mode 100644 index 000000000000..ee9e97976427 --- /dev/null +++ b/plugins/IntelliLang/src/inspectionDescriptions/InjectedReferences.html @@ -0,0 +1,5 @@ + + +Checks references injected by IntelliLang plugin. + + \ No newline at end of file diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/FileReferenceInjector.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/FileReferenceInjector.java index 1b28df2208dc..b8e8b591b5e0 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/FileReferenceInjector.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/FileReferenceInjector.java @@ -44,6 +44,11 @@ public class FileReferenceInjector extends ReferenceInjector { @Override public PsiReference[] getReferences(@NotNull PsiElement element, @NotNull ProcessingContext context, @NotNull TextRange range) { String text = range.substring(element.getText()); - return new FileReferenceSet(text, element, range.getStartOffset(), null, true).getAllReferences(); + return new FileReferenceSet(text, element, range.getStartOffset(), null, true) { + @Override + protected boolean isSoft() { + return true; + } + }.getAllReferences(); } } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesInspection.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesInspection.java new file mode 100644 index 000000000000..1ac3e11c2627 --- /dev/null +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesInspection.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.intellij.plugins.intelliLang.references; + +import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiReference; +import org.jetbrains.annotations.NotNull; + +/** + * @author Dmitry Avdeev + * Date: 05.08.13 + */ +public class InjectedReferencesInspection extends LocalInspectionTool { + + @NotNull + @Override + public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { + return new PsiElementVisitor() { + @Override + public void visitElement(PsiElement element) { + + PsiReference[] references = element.getReferences(); + if (element.getUserData(InjectedReferencesContributor.INJECTED_REFERENCE) != null) { + for (PsiReference reference : references) { + if (reference.isSoft() && reference.resolve() == null) { + holder.registerProblem(reference); + } + } + } + + super.visitElement(element); + } + }; + } +} From ca52fb14dcea0d698cf8419ebac5936b1490e50c Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 6 Aug 2013 11:40:35 +0400 Subject: [PATCH 17/62] unused class removed --- .../intellij/remoteServer/runtime/ServerRuntimeData.java | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerRuntimeData.java diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerRuntimeData.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerRuntimeData.java deleted file mode 100644 index 04cd1507600b..000000000000 --- a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerRuntimeData.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.intellij.remoteServer.runtime; - -/** - * @author nik - */ -public interface ServerRuntimeData { -} From 84d627e3e99776b78a78efea67005a91a9a98c9b Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 6 Aug 2013 11:55:43 +0400 Subject: [PATCH 18/62] typo --- .../intellij/openapi/compiler/CompilationStatusListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilationStatusListener.java b/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilationStatusListener.java index 067509811f73..11fbe73d9ed0 100644 --- a/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilationStatusListener.java +++ b/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilationStatusListener.java @@ -26,7 +26,7 @@ public interface CompilationStatusListener extends EventListener { /** * Invoked in a Swing dispatch thread after the compilation is finished. * - * @param aborted true if compilatioin has been cancelled + * @param aborted true if compilation has been cancelled * @param errors error count * @param warnings warning count * @param compileContext context for the finished compilation From 3462b46691b3c2e22d3f6927b53f936ec2bcf3f5 Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 6 Aug 2013 12:07:20 +0400 Subject: [PATCH 19/62] remote servers api: infrastructure for async execution of tasks during connection/deployment --- .../com/intellij/remoteServer/ServerType.java | 4 +- .../runtime/RemoteOperationCallback.java | 10 ++++ .../remoteServer/runtime/ServerConnector.java | 3 +- .../runtime/ServerTaskExecutor.java | 14 ++++++ .../deployment/ServerRuntimeInstance.java | 5 +- .../impl/runtime/ServerConnectionImpl.java | 4 +- .../runtime/ServerConnectionManagerImpl.java | 6 ++- .../impl/runtime/ServerTaskExecutorImpl.java | 48 +++++++++++++++++++ .../appengine/cloud/AppEngineCloudType.java | 4 +- 9 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 platform/remote-servers/api/src/com/intellij/remoteServer/runtime/RemoteOperationCallback.java create mode 100644 platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerTaskExecutor.java create mode 100644 platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerTaskExecutorImpl.java diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java b/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java index 94c600ab94eb..cb832a7c34e7 100644 --- a/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java +++ b/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java @@ -6,10 +6,10 @@ import com.intellij.openapi.project.Project; import com.intellij.remoteServer.configuration.ServerConfiguration; import com.intellij.remoteServer.configuration.deployment.DeploymentConfigurator; import com.intellij.remoteServer.runtime.ServerConnector; +import com.intellij.remoteServer.runtime.ServerTaskExecutor; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import java.util.concurrent.Executor; /** * @author nik @@ -42,5 +42,5 @@ public abstract class ServerType { public abstract DeploymentConfigurator createDeployer(Project project); @NotNull - public abstract ServerConnector createConnector(@NotNull C configuration, @NotNull Project project, @NotNull Executor asyncTasksExecutor); + public abstract ServerConnector createConnector(@NotNull C configuration, @NotNull Project project, @NotNull ServerTaskExecutor asyncTasksExecutor); } diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/RemoteOperationCallback.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/RemoteOperationCallback.java new file mode 100644 index 000000000000..49a5c9f787a5 --- /dev/null +++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/RemoteOperationCallback.java @@ -0,0 +1,10 @@ +package com.intellij.remoteServer.runtime; + +import org.jetbrains.annotations.NotNull; + +/** + * @author nik + */ +public interface RemoteOperationCallback { + void errorOccurred(@NotNull String errorMessage); +} diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerConnector.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerConnector.java index 3520941d42c9..e3b16f04245c 100644 --- a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerConnector.java +++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerConnector.java @@ -12,8 +12,7 @@ public abstract class ServerConnector { public abstract void disconnect(); - public interface ConnectionCallback { + public interface ConnectionCallback extends RemoteOperationCallback { void connected(@NotNull ServerRuntimeInstance serverRuntimeInstance); - void connectionFailed(@NotNull String errorMessage); } } diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerTaskExecutor.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerTaskExecutor.java new file mode 100644 index 000000000000..05f72923e1c4 --- /dev/null +++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerTaskExecutor.java @@ -0,0 +1,14 @@ +package com.intellij.remoteServer.runtime; + +import com.intellij.util.ThrowableRunnable; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.Executor; + +/** + * @author nik + */ +public interface ServerTaskExecutor extends Executor { + void submit(@NotNull Runnable command); + void submit(@NotNull ThrowableRunnable command, @NotNull RemoteOperationCallback callback); +} diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/ServerRuntimeInstance.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/ServerRuntimeInstance.java index a844f9f59a95..e5f2d1d035ee 100644 --- a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/ServerRuntimeInstance.java +++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/ServerRuntimeInstance.java @@ -2,6 +2,7 @@ package com.intellij.remoteServer.runtime.deployment; import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration; import com.intellij.remoteServer.configuration.deployment.DeploymentSource; +import com.intellij.remoteServer.runtime.RemoteOperationCallback; import org.jetbrains.annotations.NotNull; /** @@ -15,9 +16,7 @@ public abstract class ServerRuntimeInstance { public abstract void undeploy(@NotNull DeploymentSource source, @NotNull D configuration, @NotNull DeploymentOperationCallback callback); - public interface DeploymentOperationCallback { + public interface DeploymentOperationCallback extends RemoteOperationCallback { void succeeded(); - - void failed(@NotNull String errorMessage); } } diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionImpl.java index 3a11a39d6ec3..a8b2d881b880 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionImpl.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionImpl.java @@ -93,7 +93,7 @@ public class ServerConnectionImpl implements } @Override - public void connectionFailed(@NotNull String errorMessage) { + public void errorOccurred(@NotNull String errorMessage) { myStatus = ConnectionStatus.DISCONNECTED; myRuntimeInstance = null; myStatusText = errorMessage; @@ -118,7 +118,7 @@ public class ServerConnectionImpl implements } @Override - public void failed(@NotNull String errorMessage) { + public void errorOccurred(@NotNull String errorMessage) { myDeploymentInfos.put(mySource, new DeploymentInformation(myFailedStatus, errorMessage)); } } diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java index 5029686fb5aa..178ae0dde6e1 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java @@ -1,11 +1,11 @@ package com.intellij.remoteServer.impl.runtime; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.remoteServer.configuration.RemoteServer; import com.intellij.remoteServer.configuration.ServerConfiguration; import com.intellij.remoteServer.runtime.ServerConnection; import com.intellij.remoteServer.runtime.ServerConnectionManager; -import com.intellij.util.concurrency.SequentialTaskExecutor; import org.jetbrains.annotations.NotNull; import org.jetbrains.ide.PooledThreadExecutor; @@ -29,9 +29,10 @@ public class ServerConnectionManagerImpl extends ServerConnectionManager { @NotNull @Override public ServerConnection getOrCreateConnection(@NotNull RemoteServer server) { + ApplicationManager.getApplication().assertIsDispatchThread(); ServerConnection connection = myConnections.get(server); if (connection == null) { - SequentialTaskExecutor executor = new SequentialTaskExecutor(myPooledThreadExecutor); + ServerTaskExecutorImpl executor = new ServerTaskExecutorImpl(); connection = new ServerConnectionImpl(server, server.getType().createConnector(server.getConfiguration(), myProject, executor)); myConnections.put(server, connection); } @@ -41,6 +42,7 @@ public class ServerConnectionManagerImpl extends ServerConnectionManager { @NotNull @Override public Collection getConnections() { + ApplicationManager.getApplication().assertIsDispatchThread(); return Collections.unmodifiableCollection(myConnections.values()); } } diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerTaskExecutorImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerTaskExecutorImpl.java new file mode 100644 index 000000000000..43722962fcbd --- /dev/null +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerTaskExecutorImpl.java @@ -0,0 +1,48 @@ +package com.intellij.remoteServer.impl.runtime; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.remoteServer.runtime.RemoteOperationCallback; +import com.intellij.remoteServer.runtime.ServerTaskExecutor; +import com.intellij.util.ThrowableRunnable; +import com.intellij.util.concurrency.SequentialTaskExecutor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.ide.PooledThreadExecutor; + +/** + * @author nik + */ +public class ServerTaskExecutorImpl implements ServerTaskExecutor { + private static final Logger LOG = Logger.getInstance(ServerTaskExecutorImpl.class); + private static final PooledThreadExecutor POOLED_THREAD_EXECUTOR = new PooledThreadExecutor(); + private final SequentialTaskExecutor myTaskExecutor; + + public ServerTaskExecutorImpl() { + myTaskExecutor = new SequentialTaskExecutor(POOLED_THREAD_EXECUTOR); + } + + @Override + public void execute(@NotNull Runnable command) { + myTaskExecutor.execute(command); + } + + @Override + public void submit(@NotNull Runnable command) { + execute(command); + } + + @Override + public void submit(@NotNull final ThrowableRunnable command, @NotNull final RemoteOperationCallback callback) { + execute(new Runnable() { + @Override + public void run() { + try { + command.run(); + } + catch (Throwable e) { + LOG.info(e); + callback.errorOccurred(e.getMessage()); + } + } + }); + } +} diff --git a/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java b/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java index f7ebeea68768..a6b39729c915 100644 --- a/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java +++ b/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java @@ -26,6 +26,7 @@ import com.intellij.packaging.artifacts.ArtifactPointerManager; import com.intellij.remoteServer.ServerType; import com.intellij.remoteServer.configuration.deployment.*; import com.intellij.remoteServer.runtime.ServerConnector; +import com.intellij.remoteServer.runtime.ServerTaskExecutor; import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance; import com.intellij.util.ui.FormBuilder; import icons.GoogleAppEngineIcons; @@ -36,7 +37,6 @@ import javax.swing.*; import java.awt.*; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.Executor; /** * @author nik @@ -75,7 +75,7 @@ public class AppEngineCloudType extends ServerType @Override public ServerConnector createConnector(@NotNull AppEngineServerConfiguration configuration, @NotNull Project project, - @NotNull Executor asyncTasksExecutor) { + @NotNull ServerTaskExecutor asyncTasksExecutor) { return new AppEngineServerConnector(project, configuration); } From 94f4462b36fb6b21ce7198db1f1ee8d29901cfdc Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 6 Aug 2013 15:33:23 +0400 Subject: [PATCH 20/62] remote servers api: 'Test connection' button added --- .../src/META-INF/RemoteServers.xml | 4 +- .../com/intellij/remoteServer/ServerType.java | 2 +- .../runtime/ServerConnection.java | 8 ++- .../runtime/ServerConnectionManager.java | 5 +- .../runtime/deployment/DeploymentTask.java | 20 ++++++ .../deployment/ServerRuntimeInstance.java | 7 +- .../RemoteServerConfigurable.form | 39 ++++++++++ .../RemoteServerConfigurable.java | 71 +++++++++++++++++-- .../impl/runtime/DeployToServerState.java | 5 +- .../impl/runtime/ServerConnectionImpl.java | 62 ++++++++++++---- .../runtime/ServerConnectionManagerImpl.java | 10 +-- .../DeploymentInformation.java | 2 +- .../deployment/DeploymentTaskImpl.java | 37 ++++++++++ .../appengine/cloud/AppEngineCloudType.java | 55 +++++++------- 14 files changed, 258 insertions(+), 69 deletions(-) create mode 100644 platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/DeploymentTask.java create mode 100644 platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.form rename platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/{ => deployment}/DeploymentInformation.java (91%) create mode 100644 platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/DeploymentTaskImpl.java diff --git a/platform/platform-resources/src/META-INF/RemoteServers.xml b/platform/platform-resources/src/META-INF/RemoteServers.xml index 54bd764d2533..a72377709dc4 100644 --- a/platform/platform-resources/src/META-INF/RemoteServers.xml +++ b/platform/platform-resources/src/META-INF/RemoteServers.xml @@ -8,8 +8,8 @@ serviceImplementation="com.intellij.remoteServer.impl.configuration.RemoteServersManagerImpl"/> - + diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java b/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java index cb832a7c34e7..5279f527175c 100644 --- a/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java +++ b/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java @@ -42,5 +42,5 @@ public abstract class ServerType { public abstract DeploymentConfigurator createDeployer(Project project); @NotNull - public abstract ServerConnector createConnector(@NotNull C configuration, @NotNull Project project, @NotNull ServerTaskExecutor asyncTasksExecutor); + public abstract ServerConnector createConnector(@NotNull C configuration, @NotNull ServerTaskExecutor asyncTasksExecutor); } diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerConnection.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerConnection.java index ab5a32b54be6..a73037bc80fb 100644 --- a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerConnection.java +++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerConnection.java @@ -4,6 +4,7 @@ import com.intellij.remoteServer.configuration.RemoteServer; import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration; import com.intellij.remoteServer.configuration.deployment.DeploymentSource; import com.intellij.remoteServer.runtime.deployment.DeploymentStatus; +import com.intellij.remoteServer.runtime.deployment.DeploymentTask; import org.jetbrains.annotations.NotNull; /** @@ -20,9 +21,12 @@ public interface ServerConnection { String getStatusText(); - void deploy(@NotNull DeploymentSource source, @NotNull D configuration); + void connect(@NotNull Runnable onFinished); - void undeploy(@NotNull DeploymentSource source, @NotNull D configuration); + + void deploy(@NotNull DeploymentTask task); + + void undeploy(@NotNull DeploymentTask task); @NotNull DeploymentStatus getDeploymentStatus(@NotNull DeploymentSource source); diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerConnectionManager.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerConnectionManager.java index 6a22b11ba374..494504c68062 100644 --- a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerConnectionManager.java +++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/ServerConnectionManager.java @@ -1,7 +1,6 @@ package com.intellij.remoteServer.runtime; import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.project.Project; import com.intellij.remoteServer.configuration.RemoteServer; import com.intellij.remoteServer.configuration.ServerConfiguration; import org.jetbrains.annotations.NotNull; @@ -13,8 +12,8 @@ import java.util.Collection; */ public abstract class ServerConnectionManager { @NotNull - public static ServerConnectionManager getInstance(@NotNull Project project) { - return ServiceManager.getService(project, ServerConnectionManager.class); + public static ServerConnectionManager getInstance() { + return ServiceManager.getService(ServerConnectionManager.class); } @NotNull diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/DeploymentTask.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/DeploymentTask.java new file mode 100644 index 000000000000..73708bad843b --- /dev/null +++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/DeploymentTask.java @@ -0,0 +1,20 @@ +package com.intellij.remoteServer.runtime.deployment; + +import com.intellij.openapi.project.Project; +import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration; +import com.intellij.remoteServer.configuration.deployment.DeploymentSource; +import org.jetbrains.annotations.NotNull; + +/** + * @author nik + */ +public interface DeploymentTask { + @NotNull + DeploymentSource getSource(); + + @NotNull + D getConfiguration(); + + @NotNull + Project getProject(); +} diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/ServerRuntimeInstance.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/ServerRuntimeInstance.java index e5f2d1d035ee..2d0e08e7de18 100644 --- a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/ServerRuntimeInstance.java +++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/ServerRuntimeInstance.java @@ -1,7 +1,6 @@ package com.intellij.remoteServer.runtime.deployment; import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration; -import com.intellij.remoteServer.configuration.deployment.DeploymentSource; import com.intellij.remoteServer.runtime.RemoteOperationCallback; import org.jetbrains.annotations.NotNull; @@ -10,11 +9,9 @@ import org.jetbrains.annotations.NotNull; */ public abstract class ServerRuntimeInstance { - public abstract void deploy(@NotNull DeploymentSource source, @NotNull D configuration, - @NotNull DeploymentOperationCallback callback); + public abstract void deploy(@NotNull DeploymentTask task, @NotNull DeploymentOperationCallback callback); - public abstract void undeploy(@NotNull DeploymentSource source, @NotNull D configuration, - @NotNull DeploymentOperationCallback callback); + public abstract void undeploy(@NotNull DeploymentTask task, @NotNull DeploymentOperationCallback callback); public interface DeploymentOperationCallback extends RemoteOperationCallback { void succeeded(); diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.form b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.form new file mode 100644 index 000000000000..38c658d0bc71 --- /dev/null +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.form @@ -0,0 +1,39 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.java index 50e6b1317949..1a65ddd4c06b 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/RemoteServerConfigurable.java @@ -1,15 +1,27 @@ package com.intellij.remoteServer.impl.configuration; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.UnnamedConfigurable; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.NamedConfigurable; import com.intellij.remoteServer.configuration.RemoteServer; import com.intellij.remoteServer.configuration.ServerConfiguration; +import com.intellij.remoteServer.runtime.ConnectionStatus; +import com.intellij.remoteServer.runtime.ServerConnection; +import com.intellij.remoteServer.runtime.ServerConnectionManager; +import com.intellij.util.concurrency.Semaphore; import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.concurrent.atomic.AtomicReference; /** * @author nik @@ -19,6 +31,9 @@ public class RemoteServerConfigurable extends NamedConfigurable> private final RemoteServer myServer; private String myServerName; private boolean myNew; + private JPanel myMainPanel; + private JPanel mySettingsPanel; + private JButton myTestConnectionButton; public RemoteServerConfigurable(RemoteServer server, Runnable treeUpdater, boolean isNew) { super(true, treeUpdater); @@ -41,10 +56,58 @@ public class RemoteServerConfigurable extends NamedConfigurable> @Override public JComponent createOptionsPanel() { - JComponent component = myConfigurable.createComponent(); - JPanel panel = new JPanel(new BorderLayout()); - panel.add(component, BorderLayout.NORTH); - return panel; + mySettingsPanel.add(BorderLayout.CENTER, myConfigurable.createComponent()); + myTestConnectionButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + apply(); + } + catch (ConfigurationException exc) { + Messages.showErrorDialog(myMainPanel, "Cannot test connection: " + exc.getMessage(), exc.getTitle()); + return; + } + testConnection(); + } + }); + return myMainPanel; + } + + private void testConnection() { + final ServerConnection connection = ServerConnectionManager.getInstance().getOrCreateConnection(myServer); + final AtomicReference showResultRef = new AtomicReference(null); + new Task.Modal(null, "Connecting...", true) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + indicator.setIndeterminate(true); + final Semaphore semaphore = new Semaphore(); + semaphore.down(); + connection.connect(new Runnable() { + @Override + public void run() { + showResultRef.set(new Runnable() { + @Override + public void run() { + if (connection.getStatus() == ConnectionStatus.CONNECTED) { + Messages.showInfoMessage(myMainPanel, "Connection successful", "Test Connection"); + } + else if (connection.getStatus() == ConnectionStatus.DISCONNECTED) { + Messages.showErrorDialog(myMainPanel, "Cannot connect: " + connection.getStatusText(), "Test Connection"); + } + } + }); + semaphore.up(); + } + }); + while (!indicator.isCanceled()) { + semaphore.waitFor(500); + } + Runnable showResult = showResultRef.get(); + if (showResult != null) { + ApplicationManager.getApplication().invokeLater(showResult); + } + } + }.queue(); } @Nls diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeployToServerState.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeployToServerState.java index 04dab47703dc..94015e971890 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeployToServerState.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeployToServerState.java @@ -25,6 +25,7 @@ import com.intellij.remoteServer.configuration.RemoteServer; import com.intellij.remoteServer.configuration.ServerConfiguration; import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration; import com.intellij.remoteServer.configuration.deployment.DeploymentSource; +import com.intellij.remoteServer.impl.runtime.deployment.DeploymentTaskImpl; import com.intellij.remoteServer.runtime.ServerConnection; import com.intellij.remoteServer.runtime.ServerConnectionManager; import org.jetbrains.annotations.NotNull; @@ -51,8 +52,8 @@ public class DeployToServerState implements } @Override - public void deploy(@NotNull final DeploymentSource source, @NotNull final D configuration) { - runOnInstance(new ParameterizedRunnable>() { + public void connect(@NotNull final Runnable onFinished) { + disconnect(); + connectIfNeeded(new ServerConnector.ConnectionCallback() { @Override - public void run(ServerRuntimeInstance instance) { - myDeploymentInfos.put(source, new DeploymentInformation(DeploymentStatus.DEPLOYING)); - instance.deploy(source, configuration, new UpdateDeploymentStatusCallback(source, DeploymentStatus.DEPLOYED, - DeploymentStatus.NOT_DEPLOYED)); + public void connected(@NotNull ServerRuntimeInstance serverRuntimeInstance) { + onFinished.run(); + } + + @Override + public void errorOccurred(@NotNull String errorMessage) { + onFinished.run(); + } + }); + } + + private void disconnect() { + if (myStatus == ConnectionStatus.CONNECTED) { + myRuntimeInstance = null; + myConnector.disconnect(); + myStatus = ConnectionStatus.DISCONNECTED; + } + } + + @Override + public void deploy(@NotNull final DeploymentTask task) { + connectIfNeeded(new ConnectionCallbackBase() { + @Override + public void connected(@NotNull ServerRuntimeInstance instance) { + myDeploymentInfos.put(task.getSource(), new DeploymentInformation(DeploymentStatus.DEPLOYING)); + instance.deploy(task, new UpdateDeploymentStatusCallback(task.getSource(), DeploymentStatus.DEPLOYED, + DeploymentStatus.NOT_DEPLOYED)); } }); } @Override - public void undeploy(@NotNull final DeploymentSource source, @NotNull final D configuration) { - runOnInstance(new ParameterizedRunnable>() { + public void undeploy(@NotNull final DeploymentTask task) { + connectIfNeeded(new ConnectionCallbackBase() { @Override - public void run(ServerRuntimeInstance instance) { - instance.undeploy(source, configuration, new UpdateDeploymentStatusCallback(source, DeploymentStatus.NOT_DEPLOYED, DeploymentStatus.DEPLOYED)); + public void connected(@NotNull ServerRuntimeInstance instance) { + myDeploymentInfos.put(task.getSource(), new DeploymentInformation(DeploymentStatus.UNDEPLOYING)); + instance.undeploy(task, new UpdateDeploymentStatusCallback(task.getSource(), DeploymentStatus.NOT_DEPLOYED, + DeploymentStatus.DEPLOYED)); } }); } @@ -76,10 +103,10 @@ public class ServerConnectionImpl implements return information != null ? information.getStatus() : DeploymentStatus.NOT_DEPLOYED; } - private void runOnInstance(final ParameterizedRunnable> action) { + private void connectIfNeeded(final ServerConnector.ConnectionCallback callback) { final ServerRuntimeInstance instance = myRuntimeInstance; if (instance != null) { - action.run(instance); + callback.connected(instance); return; } @@ -89,7 +116,7 @@ public class ServerConnectionImpl implements public void connected(@NotNull ServerRuntimeInstance instance) { myStatus = ConnectionStatus.CONNECTED; myRuntimeInstance = instance; - action.run(instance); + callback.connected(instance); } @Override @@ -97,10 +124,17 @@ public class ServerConnectionImpl implements myStatus = ConnectionStatus.DISCONNECTED; myRuntimeInstance = null; myStatusText = errorMessage; + callback.errorOccurred(errorMessage); } }); } + private static abstract class ConnectionCallbackBase implements ServerConnector.ConnectionCallback { + @Override + public void errorOccurred(@NotNull String errorMessage) { + } + } + private class UpdateDeploymentStatusCallback implements ServerRuntimeInstance.DeploymentOperationCallback { private final DeploymentSource mySource; private DeploymentStatus mySuccessStatus; diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java index 178ae0dde6e1..66a56da6ddd5 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java @@ -1,13 +1,11 @@ package com.intellij.remoteServer.impl.runtime; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.project.Project; import com.intellij.remoteServer.configuration.RemoteServer; import com.intellij.remoteServer.configuration.ServerConfiguration; import com.intellij.remoteServer.runtime.ServerConnection; import com.intellij.remoteServer.runtime.ServerConnectionManager; import org.jetbrains.annotations.NotNull; -import org.jetbrains.ide.PooledThreadExecutor; import java.util.Collection; import java.util.Collections; @@ -19,12 +17,6 @@ import java.util.Map; */ public class ServerConnectionManagerImpl extends ServerConnectionManager { private Map, ServerConnection> myConnections = new HashMap, ServerConnection>(); - private final PooledThreadExecutor myPooledThreadExecutor = new PooledThreadExecutor(); - private final Project myProject; - - public ServerConnectionManagerImpl(Project project) { - myProject = project; - } @NotNull @Override @@ -33,7 +25,7 @@ public class ServerConnectionManagerImpl extends ServerConnectionManager { ServerConnection connection = myConnections.get(server); if (connection == null) { ServerTaskExecutorImpl executor = new ServerTaskExecutorImpl(); - connection = new ServerConnectionImpl(server, server.getType().createConnector(server.getConfiguration(), myProject, executor)); + connection = new ServerConnectionImpl(server, server.getType().createConnector(server.getConfiguration(), executor)); myConnections.put(server, connection); } return connection; diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeploymentInformation.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/DeploymentInformation.java similarity index 91% rename from platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeploymentInformation.java rename to platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/DeploymentInformation.java index 54e2d35ad325..97117e4788b7 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/DeploymentInformation.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/DeploymentInformation.java @@ -1,4 +1,4 @@ -package com.intellij.remoteServer.impl.runtime; +package com.intellij.remoteServer.impl.runtime.deployment; import com.intellij.remoteServer.runtime.deployment.DeploymentStatus; import org.jetbrains.annotations.NotNull; diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/DeploymentTaskImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/DeploymentTaskImpl.java new file mode 100644 index 000000000000..f9ecc769d705 --- /dev/null +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/DeploymentTaskImpl.java @@ -0,0 +1,37 @@ +package com.intellij.remoteServer.impl.runtime.deployment; + +import com.intellij.openapi.project.Project; +import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration; +import com.intellij.remoteServer.configuration.deployment.DeploymentSource; +import com.intellij.remoteServer.runtime.deployment.DeploymentTask; +import org.jetbrains.annotations.NotNull; + +/** + * @author nik + */ +public class DeploymentTaskImpl implements DeploymentTask { + private final DeploymentSource mySource; + private final D myConfiguration; + private final Project myProject; + + public DeploymentTaskImpl(DeploymentSource source, D configuration, Project project) { + mySource = source; + myConfiguration = configuration; + myProject = project; + } + + @NotNull + public DeploymentSource getSource() { + return mySource; + } + + @NotNull + public D getConfiguration() { + return myConfiguration; + } + + @NotNull + public Project getProject() { + return myProject; + } +} diff --git a/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java b/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java index a6b39729c915..a7b798c6df2e 100644 --- a/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java +++ b/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java @@ -27,6 +27,7 @@ import com.intellij.remoteServer.ServerType; import com.intellij.remoteServer.configuration.deployment.*; import com.intellij.remoteServer.runtime.ServerConnector; import com.intellij.remoteServer.runtime.ServerTaskExecutor; +import com.intellij.remoteServer.runtime.deployment.DeploymentTask; import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance; import com.intellij.util.ui.FormBuilder; import icons.GoogleAppEngineIcons; @@ -74,9 +75,8 @@ public class AppEngineCloudType extends ServerType @NotNull @Override public ServerConnector createConnector(@NotNull AppEngineServerConfiguration configuration, - @NotNull Project project, @NotNull ServerTaskExecutor asyncTasksExecutor) { - return new AppEngineServerConnector(project, configuration); + return new AppEngineServerConnector(configuration); } @NotNull @@ -153,40 +153,43 @@ public class AppEngineCloudType extends ServerType } private static class AppEngineServerConnector extends ServerConnector { - private final Project myProject; private final AppEngineServerConfiguration myConfiguration; - public AppEngineServerConnector(Project project, AppEngineServerConfiguration configuration) { - myProject = project; + public AppEngineServerConnector(AppEngineServerConfiguration configuration) { myConfiguration = configuration; } @Override - public void connect(@NotNull ConnectionCallback callback) { - callback.connected(new ServerRuntimeInstance() { - @Override - public void deploy(@NotNull DeploymentSource source, - @NotNull DummyDeploymentConfiguration configuration, - @NotNull DeploymentOperationCallback callback) { - Artifact artifact = ((ArtifactDeploymentSource)source).getArtifact(); - if (artifact == null) return; - - AppEngineUploader uploader = AppEngineUploader.createUploader(myProject, artifact, myConfiguration); - if (uploader != null) { - uploader.startUploading(); - } - } - - @Override - public void undeploy(@NotNull DeploymentSource source, - @NotNull DummyDeploymentConfiguration configuration, - @NotNull DeploymentOperationCallback callback) { - } - }); + public void connect(@NotNull final ConnectionCallback callback) { + callback.connected(new AppEngineRuntimeInstance(myConfiguration)); } @Override public void disconnect() { } } + + private static class AppEngineRuntimeInstance extends ServerRuntimeInstance { + private final AppEngineServerConfiguration myConfiguration; + + public AppEngineRuntimeInstance(AppEngineServerConfiguration configuration) { + myConfiguration = configuration; + } + + @Override + public void deploy(@NotNull DeploymentTask task, @NotNull DeploymentOperationCallback callback) { + Artifact artifact = ((ArtifactDeploymentSource)task.getSource()).getArtifact(); + if (artifact == null) return; + + AppEngineUploader uploader = AppEngineUploader.createUploader(task.getProject(), artifact, myConfiguration); + if (uploader != null) { + uploader.startUploading(); + } + } + + @Override + public void undeploy(@NotNull DeploymentTask task, + @NotNull DeploymentOperationCallback callback) { + } + } } From 1bd39a6322f7a4ff4a1e94497f2484cce30515d2 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 6 Aug 2013 12:01:09 +0200 Subject: [PATCH 21/62] recursive lambda checks for functional interfaces --- .../intellij/psi/LambdaHighlightingUtil.java | 9 +++++-- .../src/com/intellij/psi/LambdaUtil.java | 24 ++++++++++++------- .../lambda/highlighting/CastInContexts.java | 2 +- .../FunctionalInterfaceCheck.java | 5 ++++ .../highlighting/NoInferenceResult.java | 2 +- .../lambda/highlighting/ReturnValue.java | 2 +- .../daemon/lambda/LambdaHighlightingTest.java | 1 + 7 files changed, 31 insertions(+), 14 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceCheck.java diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java index fc1d2957c2da..a00e8806eb76 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java @@ -87,7 +87,12 @@ public class LambdaHighlightingUtil { @Nullable public static String checkInterfaceFunctional(PsiType functionalInterfaceType) { - final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); + if (functionalInterfaceType instanceof PsiIntersectionType) { + for (PsiType type : ((PsiIntersectionType)functionalInterfaceType).getConjuncts()) { + if (checkInterfaceFunctional(type) == null) return null; + } + } + final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(functionalInterfaceType)); final PsiClass aClass = resolveResult.getElement(); if (aClass != null) { if (checkReturnTypeApplicable(resolveResult, aClass)) { @@ -95,7 +100,7 @@ public class LambdaHighlightingUtil { } return checkInterfaceFunctional(aClass); } - return null; + return functionalInterfaceType.getPresentableText() + " is not a functional interface"; } private static boolean checkReturnTypeApplicable(PsiClassType.ClassResolveResult resolveResult, final PsiClass aClass) { diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index 464299f2ab07..41c4aa51cac1 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -484,23 +484,30 @@ public class LambdaUtil { } } else if (parent instanceof PsiReturnStatement) { - final PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class); - if (method != null) { - return method.getReturnType(); + final PsiLambdaExpression gParent = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class); + if (gParent != null) { + return getFunctionalInterfaceTypeByContainingLambda(gParent); + } else { + final PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class); + if (method != null) { + return method.getReturnType(); + } } } else if (parent instanceof PsiLambdaExpression) { - final PsiType parentInterfaceType = ((PsiLambdaExpression)parent).getFunctionalInterfaceType(); - if (parentInterfaceType != null) { - return getFunctionalInterfaceReturnType(parentInterfaceType); - } + return getFunctionalInterfaceTypeByContainingLambda((PsiLambdaExpression)parent); } return null; } + private static PsiType getFunctionalInterfaceTypeByContainingLambda(@NotNull PsiLambdaExpression parentLambda) { + final PsiType parentInterfaceType = parentLambda.getFunctionalInterfaceType(); + return parentInterfaceType != null ? getFunctionalInterfaceReturnType(parentInterfaceType) : null; + } + private static int adjustLambdaIdx(int lambdaIdx, PsiMethod resolve, PsiParameter[] parameters) { final int finalLambdaIdx; - if (((PsiMethod)resolve).isVarArgs() && lambdaIdx >= parameters.length) { + if (resolve.isVarArgs() && lambdaIdx >= parameters.length) { finalLambdaIdx = parameters.length - 1; } else { finalLambdaIdx = lambdaIdx; @@ -524,7 +531,6 @@ public class LambdaUtil { final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(param, PsiLambdaExpression.class); if (lambdaExpression != null) { - final PsiParameterList parameterList = lambdaExpression.getParameterList(); PsiType type = getFunctionalInterfaceType(lambdaExpression, true, parameterIndex); if (type == null) { type = getFunctionalInterfaceType(lambdaExpression, false); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/CastInContexts.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/CastInContexts.java index 1f577f8ca40f..b9d5d4b2eb69 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/CastInContexts.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/CastInContexts.java @@ -22,6 +22,6 @@ class CastInContexts { } { - int i = (int) ()-> 1; + int i = (int) ()-> 1; } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceCheck.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceCheck.java new file mode 100644 index 000000000000..74537d41e2c0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceCheck.java @@ -0,0 +1,5 @@ +class Demo { + public static void main(String[] args) { + Runnable r = () -> () -> () -> {}; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/NoInferenceResult.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/NoInferenceResult.java index b0656f5c0ecc..7af6276e5d31 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/NoInferenceResult.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/NoInferenceResult.java @@ -16,7 +16,7 @@ class NoInferenceResult { void test() { m((String s1) -> (String s2) -> s1 + s2); - m((String s1) -> {return (String s2) -> s1 + s2;}); + m((String s1) -> {return (String s2) -> s1 + s2;}); m((String s1) -> s1.length()); m((String s1) -> s1); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnValue.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnValue.java index 39ba57fcdc17..e23d2c71bfcf 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnValue.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnValue.java @@ -48,7 +48,7 @@ class Test2 { } { - X x = () -> 123; + X x = () -> 123; X x1 = () -> 123; } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java index d8c404b274a0..10b35d3d6c56 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java @@ -89,6 +89,7 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase { public void testConflictResolution() throws Exception {doTest();} public void testIDEA108195() throws Exception {doTest();} public void testDiamondInference() throws Exception { doTest();} + public void testFunctionalInterfaceCheck() throws Exception { doTest();} private void doTest() { doTest(false); From 6d3989e21d905cdb6e74596e71e3bf0d2878f5ca Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 6 Aug 2013 12:38:08 +0200 Subject: [PATCH 22/62] IDEA-111613 Bad code is green: IDEA doesn't show 'Unhandled exception' error when a method with parametrized 'throws' section is used with wildcard type argument --- .../src/com/intellij/codeInsight/ExceptionUtil.java | 2 +- .../advHighlighting6/UnhandledExceptions.java | 13 +++++++++++++ .../daemon/LightAdvHighlightingJdk6Test.java | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnhandledExceptions.java diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java index fc040080d808..44055a7f08b0 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java @@ -541,7 +541,7 @@ public class ExceptionUtil { List result = ContainerUtil.newArrayList(); for (PsiClassType referencedType : referencedTypes) { - final PsiType type = substitutor.substitute(referencedType); + final PsiType type = GenericsUtil.eliminateWildcards(substitutor.substitute(referencedType), false); if (!(type instanceof PsiClassType)) continue; PsiClassType classType = (PsiClassType)type; PsiClass exceptionClass = ((PsiClassType)type).resolve(); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnhandledExceptions.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnhandledExceptions.java new file mode 100644 index 000000000000..54eac1eedabe --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnhandledExceptions.java @@ -0,0 +1,13 @@ +interface I { + void m() throws T; +} + +class C { + void x(I i) { + i.m(); + } + + void y(I i) { + i.m(); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java index b7790ae82d0d..4af4e6bcdf27 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java @@ -58,4 +58,5 @@ public class LightAdvHighlightingJdk6Test extends LightDaemonAnalyzerTestCase { public void testClassObjectAccessibility() throws Exception { setLanguageLevel(LanguageLevel.JDK_1_6); doTest(false, false); } public void testRedundantCastInConditionalExpression() throws Exception { setLanguageLevel(LanguageLevel.JDK_1_6); doTest(true, false); } public void testJava5CastConventions() { setLanguageLevel(LanguageLevel.JDK_1_5); doTest(true, false); } + public void testUnhandledExceptions() { doTest(true, false); } } From c9fdcdaf04ee82d40fff40d5f9895b5c290dc80e Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 6 Aug 2013 16:01:27 +0400 Subject: [PATCH 23/62] IDEA-97264 IntelliLang support for "Path to File" language: highlighting --- .../tree/java/PsiLiteralExpressionImpl.java | 3 ++- .../util/ReflectionAssignabilityCache.java | 1 + .../intelliLang/ReferenceInjectionTest.java | 15 +++++++++++++++ .../intelliLang/inject/InjectLanguageAction.java | 4 ++++ .../references/InjectedReferencesContributor.java | 11 ++++++----- .../references/InjectedReferencesInspection.java | 8 ++++---- 6 files changed, 32 insertions(+), 10 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLiteralExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLiteralExpressionImpl.java index 74d1350b3dc7..f6c790a362c9 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLiteralExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLiteralExpressionImpl.java @@ -382,7 +382,8 @@ public class PsiLiteralExpressionImpl @Override @NotNull public PsiReference[] getReferences() { - return PsiReferenceService.getService().getContributedReferences(this); + PsiReference[] references = PsiReferenceService.getService().getContributedReferences(this); + return references; } @Override diff --git a/platform/util/src/com/intellij/util/ReflectionAssignabilityCache.java b/platform/util/src/com/intellij/util/ReflectionAssignabilityCache.java index e9e2cecc45e3..a5a1c68a7f14 100644 --- a/platform/util/src/com/intellij/util/ReflectionAssignabilityCache.java +++ b/platform/util/src/com/intellij/util/ReflectionAssignabilityCache.java @@ -19,6 +19,7 @@ import com.intellij.util.containers.ConcurrentFactoryMap; /** * @author peter + * @see ReflectionCache */ public class ReflectionAssignabilityCache { private final ConcurrentFactoryMap> myCache = new ConcurrentFactoryMap>() { diff --git a/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java b/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java index 4b4489bb7d25..46bebc508add 100644 --- a/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java +++ b/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java @@ -66,6 +66,21 @@ public class ReferenceInjectionTest extends LightPlatformCodeInsightFixtureTestC assertNull(myFixture.getReferenceAtCaretPosition()); } + public void testInjectIntoJava() throws Exception { + myFixture.configureByText("Foo.java", "class Foo {\n" + + " String bar() {\n" + + " return \"bar.xml\";\n" + + " } \n" + + "}"); + assertNull(myFixture.getReferenceAtCaretPosition()); + + InjectLanguageAction.invokeImpl(getProject(), myFixture.getEditor(), myFixture.getFile(), new FileReferenceInjector()); + assertNotNull(myFixture.getReferenceAtCaretPosition()); + + UnInjectLanguageAction.invokeImpl(getProject(), myFixture.getEditor(), myFixture.getFile()); + assertNull(myFixture.getReferenceAtCaretPosition()); + } + @Override protected void setUp() throws Exception { super.setUp(); diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java index 2f3735c5f1a5..ea12ada745ee 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java @@ -15,6 +15,7 @@ */ package org.intellij.plugins.intelliLang.inject; +import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.injected.editor.EditorWindow; import com.intellij.lang.Language; @@ -116,6 +117,9 @@ public class InjectLanguageAction implements IntentionAction { if (injectable.getLanguage() != null) { // no need for reference injection FileContentUtil.reparseFiles(project, Collections.emptyList(), true); } + else { + DaemonCodeAnalyzer.getInstance(project).restart(); + } } } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java index a5456035b235..ccf74a248217 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java @@ -39,10 +39,10 @@ import java.util.List; */ public class InjectedReferencesContributor extends PsiReferenceContributor { - static final Key INJECTED_REFERENCE = Key.create("injected reference"); + static final Key INJECTED_REFERENCES = Key.create("injected references"); public static boolean isInjected(@Nullable PsiReference reference) { - return reference != null && reference.getElement().getUserData(INJECTED_REFERENCE) != null; + return reference != null && reference.getElement().getUserData(INJECTED_REFERENCES) != null; } @Override @@ -51,15 +51,15 @@ public class InjectedReferencesContributor extends PsiReferenceContributor { @NotNull @Override public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { - element.putUserData(INJECTED_REFERENCE, null); ReferenceInjector[] extensions = ReferenceInjector.EXTENSION_POINT_NAME.getExtensions(); PsiReference[] references = new PsiReference[0]; Configuration configuration = Configuration.getProjectInstance(element.getProject()); + boolean injected = false; for (ReferenceInjector injector : extensions) { Collection injections = configuration.getInjectionsByLanguageId(injector.getId()); for (BaseInjection injection : injections) { if (injection.acceptForReference(element)) { - element.putUserData(INJECTED_REFERENCE, injector); + injected = true; LanguageInjectionSupport support = InjectorUtils.findInjectionSupport(injection.getSupportId()); element.putUserData(LanguageInjectionSupport.INJECTOR_SUPPORT, support); List area = injection.getInjectedArea(element); @@ -75,13 +75,14 @@ public class InjectedReferencesContributor extends PsiReferenceContributor { if (language != null) { ReferenceInjector injector = ReferenceInjector.findById(language.getID()); if (injector != null) { - element.putUserData(INJECTED_REFERENCE, injector); + injected = true; element.putUserData(LanguageInjectionSupport.INJECTOR_SUPPORT, registry.getLanguageInjectionSupport()); TextRange range = ElementManipulators.getValueTextRange(element); references = ArrayUtil.mergeArrays(references, injector.getReferences(element, context, range)); } } } + element.putUserData(INJECTED_REFERENCES, injected ? references : null); return references; } }); diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesInspection.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesInspection.java index 1ac3e11c2627..3d0920724c5e 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesInspection.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesInspection.java @@ -35,10 +35,10 @@ public class InjectedReferencesInspection extends LocalInspectionTool { @Override public void visitElement(PsiElement element) { - PsiReference[] references = element.getReferences(); - if (element.getUserData(InjectedReferencesContributor.INJECTED_REFERENCE) != null) { - for (PsiReference reference : references) { - if (reference.isSoft() && reference.resolve() == null) { + PsiReference[] injected = element.getUserData(InjectedReferencesContributor.INJECTED_REFERENCES); + if (injected != null) { + for (PsiReference reference : injected) { + if (reference.resolve() == null) { holder.registerProblem(reference); } } From 84582a99bfa38c249d131cd16daf1e62429c50e8 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 6 Aug 2013 16:18:16 +0400 Subject: [PATCH 24/62] showing hint on temporary injection --- .../src/com/intellij/codeInsight/hint/HintManagerImpl.java | 3 +++ .../plugins/intelliLang/inject/InjectLanguageAction.java | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java index 52ad3df3abb5..c3be5108c4ae 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java @@ -684,6 +684,9 @@ public class HintManagerImpl extends HintManager implements Disposable { } public void showInformationHint(@NotNull Editor editor, @NotNull JComponent component, boolean showByBalloon) { + if (ApplicationManager.getApplication().isUnitTestMode()) { + return; + } LightweightHint hint = new LightweightHint(component); Point p = getHintPosition(hint, editor, ABOVE); showEditorHint(hint, editor, p, HIDE_BY_ANY_KEY | HIDE_BY_TEXT_CHANGE | HIDE_BY_SCROLLING, 0, false); diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java index ea12ada745ee..3ab993cd5de0 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java @@ -16,6 +16,7 @@ package org.intellij.plugins.intelliLang.inject; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; +import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.injected.editor.EditorWindow; import com.intellij.lang.Language; @@ -27,6 +28,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -111,7 +113,9 @@ public class InjectLanguageAction implements IntentionAction { return; } } - TemporaryPlacesRegistry.getInstance(project).getLanguageInjectionSupport().addInjectionInPlace(language, host); + if (TemporaryPlacesRegistry.getInstance(project).getLanguageInjectionSupport().addInjectionInPlace(language, host)) { + HintManager.getInstance().showInformationHint(editor, StringUtil.escapeXml(language.getDisplayName()) + " was temporarily injected"); + } } finally { if (injectable.getLanguage() != null) { // no need for reference injection From f400deb9bee224851d28a8196ac35ffc9c48561f Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 6 Aug 2013 16:31:03 +0400 Subject: [PATCH 25/62] IDEA-111634 Bring back code selection --- .../src/com/intellij/openapi/editor/impl/EditorImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 440dafba4a00..5c39ebce4732 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 @@ -5596,7 +5596,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi mySelectionModel.setSelection(caretOffset, caretOffset); } else { - if (!e.isPopupTrigger() && eventArea == EditorMouseEventArea.EDITING_AREA) { + if (!e.isPopupTrigger() + && (eventArea == EditorMouseEventArea.EDITING_AREA || eventArea == EditorMouseEventArea.LINE_NUMBERS_AREA)) + { switch (e.getClickCount()) { case 2: selectWordAtCaret(mySettings.isMouseClickSelectionHonorsCamelWords() && mySettings.isCamelWords()); From 0ed4530ad7260a22cd11282bd093ba11a110fd73 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 6 Aug 2013 16:22:54 +0400 Subject: [PATCH 26/62] obsolete showSource icon removed --- platform/icons/src/actions/showSource.png | Bin 250 -> 0 bytes .../util/src/com/intellij/icons/AllIcons.java | 1 - 2 files changed, 1 deletion(-) delete mode 100644 platform/icons/src/actions/showSource.png diff --git a/platform/icons/src/actions/showSource.png b/platform/icons/src/actions/showSource.png deleted file mode 100644 index b37d9e68b9af7fafa86204282a51e83e7e8773e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 250 zcmVhRp^ z@8RzA;qLV1^Z4fS_v-fg>-YQa`uy(t{>Ine)(&5c00003bW%=J0L;t}>(U1R002@+ zL_t(|UWLxb5`ZuW1kg<&#oqh>|ED>`G7jqQ?F|C}(8es&*tK<;D?kQEL@x9M%gi?P ze&^J|)r9OhX0x|j);QRIWvj=zyc3-6i{6$vu-v9sr07*qoM6N<$f?JD$ ASO5S3 diff --git a/platform/util/src/com/intellij/icons/AllIcons.java b/platform/util/src/com/intellij/icons/AllIcons.java index bd2a44f46293..4e1754bffbee 100644 --- a/platform/util/src/com/intellij/icons/AllIcons.java +++ b/platform/util/src/com/intellij/icons/AllIcons.java @@ -136,7 +136,6 @@ public class AllIcons { public static final Icon ShowHiddens = IconLoader.getIcon("/actions/showHiddens.png"); // 16x16 public static final Icon ShowImportStatements = IconLoader.getIcon("/actions/showImportStatements.png"); // 16x16 public static final Icon ShowReadAccess = IconLoader.getIcon("/actions/showReadAccess.png"); // 16x16 - public static final Icon ShowSource = IconLoader.getIcon("/actions/showSource.png"); // 16x16 public static final Icon ShowViewer = IconLoader.getIcon("/actions/showViewer.png"); // 16x16 public static final Icon ShowWriteAccess = IconLoader.getIcon("/actions/showWriteAccess.png"); // 16x16 public static final Icon SortAsc = IconLoader.getIcon("/actions/sortAsc.png"); // 9x8 From e18ad6979a0b9dda2dd2c0b2528014479ee878af Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 6 Aug 2013 16:46:55 +0400 Subject: [PATCH 27/62] better popup --- .../inject/InjectLanguageAction.java | 13 ++++++++---- .../intelliLang/references/Injectable.java | 20 +++++++++++++++++-- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java index 3ab993cd5de0..fa2f66b129f8 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java @@ -36,7 +36,8 @@ import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.psi.PsiManager; import com.intellij.psi.impl.PsiModificationTrackerImpl; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.ui.ListCellRendererWrapper; +import com.intellij.ui.ColoredListCellRendererWrapper; +import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.components.JBList; import com.intellij.util.FileContentUtil; import com.intellij.util.Function; @@ -135,11 +136,15 @@ public class InjectLanguageAction implements IntentionAction { final List injectables = Injectable.getAllInjectables(); final JList list = new JBList(injectables); - list.setCellRenderer(new ListCellRendererWrapper() { + list.setCellRenderer(new ColoredListCellRendererWrapper() { @Override - public void customize(JList list, Injectable language, int index, boolean selected, boolean hasFocus) { + protected void doCustomize(JList list, Injectable language, int index, boolean selected, boolean hasFocus) { setIcon(language.getIcon()); - setText(language.getDisplayName()); + append(language.getDisplayName()); + String description = language.getAdditionalDescription(); + if (description != null) { + append(description, SimpleTextAttributes.GRAYED_ATTRIBUTES); + } } }); new PopupChooserBuilder(list).setItemChoosenCallback(new Runnable() { diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/Injectable.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/Injectable.java index bdb4cef4e7fc..9aecfbae69c6 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/Injectable.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/Injectable.java @@ -41,6 +41,11 @@ public abstract class Injectable implements Comparable { @NotNull public abstract String getDisplayName(); + @Nullable + public String getAdditionalDescription() { + return null; + } + @NotNull public Icon getIcon() { return EmptyIcon.ICON_16; @@ -69,7 +74,12 @@ public abstract class Injectable implements Comparable { } public Language toLanguage() { - return getLanguage() == null ? new Language(getId(), false) {} : getLanguage(); + return getLanguage() == null ? new Language(getId(), false) { + @Override + public String getDisplayName() { + return Injectable.this.getDisplayName(); + } + } : getLanguage(); } public static Injectable fromLanguage(final Language language) { @@ -83,8 +93,14 @@ public abstract class Injectable implements Comparable { @NotNull @Override public String getDisplayName() { + return language.getDisplayName(); + } + + @Nullable + @Override + public String getAdditionalDescription() { final FileType ft = language.getAssociatedFileType(); - return language.getDisplayName() + (ft != null ? " (" + ft.getDescription() + ")" : ""); + return ft != null ? " (" + ft.getDescription() + ")" : null; } @NotNull From 0fdad272fadcb35350ad0b51cdfd4e1ed2c1d472 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 6 Aug 2013 14:36:13 +0200 Subject: [PATCH 28/62] WEB-8728 PHP files: doesn't work 'Open in Browser' --- .../browsers/impl/WebBrowserServiceImpl.java | 9 +++------ .../ide/browsers/WebBrowserUrlProvider.java | 17 +++++++---------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java index bee53af627be..b35748c4d196 100644 --- a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java +++ b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java @@ -31,9 +31,6 @@ import com.intellij.xml.util.HtmlUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; -import java.util.List; - public class WebBrowserServiceImpl extends WebBrowserService { @Override public boolean canOpenInBrowser(@NotNull PsiElement psiElement) { @@ -100,9 +97,9 @@ public class WebBrowserServiceImpl extends WebBrowserService { private static Pair getProvider(PsiElement element, PsiFile psiFile) { Ref result = Ref.create(); - List allProviders = Arrays.asList(WebBrowserUrlProvider.EP_NAME.getExtensions()); - for (WebBrowserUrlProvider urlProvider : DumbService.getInstance(element.getProject()).filterByDumbAwareness(allProviders)) { - if (urlProvider.canHandleElement(element, psiFile, result)) { + DumbService dumbService = DumbService.getInstance(element.getProject()); + for (WebBrowserUrlProvider urlProvider : WebBrowserUrlProvider.EP_NAME.getExtensions()) { + if ((!dumbService.isDumb() || DumbService.isDumbAware(urlProvider)) && urlProvider.canHandleElement(element, psiFile, result)) { return Pair.create(urlProvider, result.get()); } } diff --git a/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProvider.java b/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProvider.java index 688191fcef19..2bdf78c50732 100644 --- a/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProvider.java +++ b/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProvider.java @@ -35,26 +35,23 @@ public abstract class WebBrowserUrlProvider { } } - public boolean canHandleElement(@NotNull PsiElement element, @NotNull PsiFile psiFile, Ref result) { + public boolean canHandleElement(@NotNull PsiElement element, @NotNull PsiFile psiFile, @NotNull Ref result) { VirtualFile file = psiFile.getVirtualFile(); if (file == null) { return false; } - Url url; try { - url = getUrl(element, psiFile, file); + Url url = getUrl(element, psiFile, file); + if (url != null) { + result.set(url); + return true; + } } catch (BrowserException ignored) { - return false; } - if (url == null) { - return false; - } - - result.set(url); - return true; + return false; } @Nullable From 99b21d05dc5517c4f21d7d68fd1f9bdf330af4a1 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 6 Aug 2013 15:03:22 +0200 Subject: [PATCH 29/62] escape xml inside html, probably twice --- .../com/intellij/codeInsight/hint/ParameterInfoComponent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java index 682d442e479d..ab4cc84710bb 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java @@ -341,7 +341,7 @@ class ParameterInfoComponent extends JPanel { myLabel.setForeground(FOREGROUND_COLOR); if (flagsMap.isEmpty()) { - myLabel.setText(XmlStringUtil.wrapInHtml(text)); + myLabel.setText(XmlStringUtil.wrapInHtml(XmlStringUtil.escapeString(text))); } else { String labelText = buildLabelText(text, flagsMap); From 663a3121173aa0fc345897125e694eaf38f86926 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 6 Aug 2013 17:11:52 +0400 Subject: [PATCH 30/62] ReferenceInjector moved to platform --- .../intellij/psi/injection}/Injectable.java | 18 +----------------- .../psi/injection}/ReferenceInjector.java | 4 ++-- .../src/META-INF/LangExtensionPoints.xml | 1 + plugins/IntelliLang/src/META-INF/plugin.xml | 7 +------ .../intelliLang/InjectionsSettingsUI.java | 2 +- .../inject/InjectLanguageAction.java | 18 ++++++++++++++++-- .../references/FileReferenceInjector.java | 1 + .../InjectedReferencesContributor.java | 1 + 8 files changed, 24 insertions(+), 28 deletions(-) rename {plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references => platform/lang-api/src/com/intellij/psi/injection}/Injectable.java (80%) rename {plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references => platform/lang-api/src/com/intellij/psi/injection}/ReferenceInjector.java (89%) diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/Injectable.java b/platform/lang-api/src/com/intellij/psi/injection/Injectable.java similarity index 80% rename from plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/Injectable.java rename to platform/lang-api/src/com/intellij/psi/injection/Injectable.java index 9aecfbae69c6..717414aaf380 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/Injectable.java +++ b/platform/lang-api/src/com/intellij/psi/injection/Injectable.java @@ -13,20 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.intellij.plugins.intelliLang.references; +package com.intellij.psi.injection; import com.intellij.lang.Language; import com.intellij.openapi.fileTypes.FileType; import com.intellij.util.ui.EmptyIcon; -import org.intellij.plugins.intelliLang.inject.InjectedLanguage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; /** * @author Dmitry Avdeev @@ -62,17 +57,6 @@ public abstract class Injectable implements Comparable { @Nullable public abstract Language getLanguage(); - public static List getAllInjectables() { - Language[] languages = InjectedLanguage.getAvailableLanguages(); - List list = new ArrayList(); - for (Language language : languages) { - list.add(fromLanguage(language)); - } - list.addAll(Arrays.asList(ReferenceInjector.EXTENSION_POINT_NAME.getExtensions())); - Collections.sort(list); - return list; - } - public Language toLanguage() { return getLanguage() == null ? new Language(getId(), false) { @Override diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/ReferenceInjector.java b/platform/lang-api/src/com/intellij/psi/injection/ReferenceInjector.java similarity index 89% rename from plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/ReferenceInjector.java rename to platform/lang-api/src/com/intellij/psi/injection/ReferenceInjector.java index 586645fc286a..ade17feccb58 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/ReferenceInjector.java +++ b/platform/lang-api/src/com/intellij/psi/injection/ReferenceInjector.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.intellij.plugins.intelliLang.references; +package com.intellij.psi.injection; import com.intellij.lang.Language; import com.intellij.openapi.extensions.ExtensionPointName; @@ -31,7 +31,7 @@ import org.jetbrains.annotations.NotNull; */ public abstract class ReferenceInjector extends Injectable { - final static ExtensionPointName EXTENSION_POINT_NAME = ExtensionPointName.create("org.intellij.intelliLang.referenceInjector"); + public final static ExtensionPointName EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.referenceInjector"); @Override public final Language getLanguage() { diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index 295d94c40d93..7d8758cee092 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -103,6 +103,7 @@ + diff --git a/plugins/IntelliLang/src/META-INF/plugin.xml b/plugins/IntelliLang/src/META-INF/plugin.xml index 1e5521ac47f0..59b3948cc0c4 100644 --- a/plugins/IntelliLang/src/META-INF/plugin.xml +++ b/plugins/IntelliLang/src/META-INF/plugin.xml @@ -16,7 +16,6 @@ - @@ -51,14 +50,10 @@ - + - - - - diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java index ed8dead6c460..24a8730b24e0 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java @@ -55,7 +55,7 @@ import org.intellij.plugins.intelliLang.inject.InjectorUtils; import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport; import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.intellij.plugins.intelliLang.inject.config.InjectionPlace; -import org.intellij.plugins.intelliLang.references.ReferenceInjector; +import com.intellij.psi.injection.ReferenceInjector; import org.jdom.Document; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java index fa2f66b129f8..341b8f1528d6 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java @@ -44,19 +44,33 @@ import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; import org.intellij.plugins.intelliLang.Configuration; -import org.intellij.plugins.intelliLang.references.Injectable; +import com.intellij.psi.injection.Injectable; import org.intellij.plugins.intelliLang.references.InjectedReferencesContributor; +import com.intellij.psi.injection.ReferenceInjector; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; public class InjectLanguageAction implements IntentionAction { @NonNls private static final String INJECT_LANGUAGE_FAMILY = "Inject Language/Reference"; + public static List getAllInjectables() { + Language[] languages = InjectedLanguage.getAvailableLanguages(); + List list = new ArrayList(); + for (Language language : languages) { + list.add(Injectable.fromLanguage(language)); + } + list.addAll(Arrays.asList(ReferenceInjector.EXTENSION_POINT_NAME.getExtensions())); + Collections.sort(list); + return list; + } + @NotNull public String getText() { return INJECT_LANGUAGE_FAMILY; @@ -133,7 +147,7 @@ public class InjectLanguageAction implements IntentionAction { } private static boolean doChooseLanguageToInject(Editor editor, final Processor onChosen) { - final List injectables = Injectable.getAllInjectables(); + final List injectables = getAllInjectables(); final JList list = new JBList(injectables); list.setCellRenderer(new ColoredListCellRendererWrapper() { diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/FileReferenceInjector.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/FileReferenceInjector.java index b8e8b591b5e0..d5d4cc813eab 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/FileReferenceInjector.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/FileReferenceInjector.java @@ -19,6 +19,7 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet; +import com.intellij.psi.injection.ReferenceInjector; import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NotNull; diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java index ccf74a248217..5694661988bc 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java @@ -19,6 +19,7 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.patterns.PlatformPatterns; import com.intellij.psi.*; +import com.intellij.psi.injection.ReferenceInjector; import com.intellij.util.ArrayUtil; import com.intellij.util.ProcessingContext; import org.intellij.plugins.intelliLang.Configuration; From 81c5661c69f694967a1bfc68096f9500a2f5a431 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 6 Aug 2013 17:12:40 +0400 Subject: [PATCH 31/62] ReferenceInjector moved to platform --- .../src/com/intellij/psi/injection/ReferenceInjector.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/lang-api/src/com/intellij/psi/injection/ReferenceInjector.java b/platform/lang-api/src/com/intellij/psi/injection/ReferenceInjector.java index ade17feccb58..80ad118108d3 100644 --- a/platform/lang-api/src/com/intellij/psi/injection/ReferenceInjector.java +++ b/platform/lang-api/src/com/intellij/psi/injection/ReferenceInjector.java @@ -26,6 +26,8 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; /** + * This will work only in presence of IntelliLang plugin. + * * @author Dmitry Avdeev * Date: 01.08.13 */ From c7931005d0de28bbe476feb7257f0d5ee2dd8926 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 26 Jul 2013 17:07:40 +0400 Subject: [PATCH 32/62] Remove unused class --- .../openapi/vcs/ThreeStateBoolean.java | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 platform/vcs-api/src/com/intellij/openapi/vcs/ThreeStateBoolean.java diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/ThreeStateBoolean.java b/platform/vcs-api/src/com/intellij/openapi/vcs/ThreeStateBoolean.java deleted file mode 100644 index 69bad16990ea..000000000000 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/ThreeStateBoolean.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.vcs; - -public enum ThreeStateBoolean { - yes, - no, - z; - - public static ThreeStateBoolean getInstance(final boolean value) { - return value ? yes : no; - } -} From 13e6436cf77c493864dda4d021eec08cac711619 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 28 Jul 2013 14:42:22 +0400 Subject: [PATCH 33/62] Support empty nameAttribute in the @OptionTag --- .../util/src/com/intellij/util/xmlb/OptionTagBinding.java | 8 +++++++- .../src/com/intellij/util/xmlb/annotations/OptionTag.java | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/xmlb/OptionTagBinding.java b/platform/util/src/com/intellij/util/xmlb/OptionTagBinding.java index 8b11f497f457..efc36a5cb1cb 100644 --- a/platform/util/src/com/intellij/util/xmlb/OptionTagBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/OptionTagBinding.java @@ -18,6 +18,7 @@ package com.intellij.util.xmlb; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.xmlb.annotations.OptionTag; import org.jdom.Attribute; @@ -64,7 +65,9 @@ class OptionTagBinding implements Binding { Element targetElement = new Element(myTagName); Object value = accessor.read(o); - targetElement.setAttribute(myNameAttribute, myName); + if (!StringUtil.isEmpty(myNameAttribute)) { + targetElement.setAttribute(myNameAttribute, myName); + } if (value == null) return targetElement; @@ -123,6 +126,9 @@ class OptionTagBinding implements Binding { Element e = (Element)node; if (!e.getName().equals(myTagName)) return false; String name = e.getAttributeValue(myNameAttribute); + if (StringUtil.isEmpty(myNameAttribute)) { + return name == null || name.equals(myName); + } return name != null && name.equals(myName); } diff --git a/platform/util/src/com/intellij/util/xmlb/annotations/OptionTag.java b/platform/util/src/com/intellij/util/xmlb/annotations/OptionTag.java index 3f921b3ed206..669d0116e734 100644 --- a/platform/util/src/com/intellij/util/xmlb/annotations/OptionTag.java +++ b/platform/util/src/com/intellij/util/xmlb/annotations/OptionTag.java @@ -23,7 +23,8 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Store value in tag like <option name="optionName" value="optionValue"/> + *

Store value in tag like {@code

+ *

nameAttribute can be empty, in which case it is skipped: {@code

* * @author nik */ From dd3dda81a8b0c7c73ad5e4ce89478c8e0b5e502e Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 28 Jul 2013 14:53:34 +0400 Subject: [PATCH 34/62] Simplify VcsShowConfirmationOption.Value: remove id param from enum --- .../vcs/VcsShowConfirmationOption.java | 25 +++++++------------ .../VcsGeneralConfigurationPanel.java | 6 +++-- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsShowConfirmationOption.java b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsShowConfirmationOption.java index 0eb8ca02c32d..9322251a1871 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsShowConfirmationOption.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsShowConfirmationOption.java @@ -16,34 +16,27 @@ package com.intellij.openapi.vcs; public interface VcsShowConfirmationOption { + enum Value { - SHOW_CONFIRMATION(0), - DO_NOTHING_SILENTLY(1), - DO_ACTION_SILENTLY(2); + // NB: don't reorder enum values, otherwise you may break user settings based on the obsolete implementation + SHOW_CONFIRMATION, + DO_NOTHING_SILENTLY, + DO_ACTION_SILENTLY; - private final int myId; - - Value(final int id) { - myId = id; - } - - public int getId() { - return myId; - } - public String toString() { - return String.valueOf(myId); + // compatibility with the old implementation + return String.valueOf(ordinal()); } + @Deprecated public static Value fromString(String s){ - if (s == null) return SHOW_CONFIRMATION; if (s.equals("1")) return DO_NOTHING_SILENTLY; if (s.equals("2")) return DO_ACTION_SILENTLY; return SHOW_CONFIRMATION; } } - public static final VcsShowConfirmationOption STATIC_SHOW_CONFIRMATION = new VcsShowConfirmationOption() { + VcsShowConfirmationOption STATIC_SHOW_CONFIRMATION = new VcsShowConfirmationOption() { @Override public Value getValue() { return Value.SHOW_CONFIRMATION; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java index c9bfa4baeaa3..781e4fd949a6 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java @@ -216,8 +216,10 @@ public class VcsGeneralConfigurationPanel implements SearchableConfigurable { myForceNonEmptyComment.setSelected(settings.FORCE_NON_EMPTY_COMMENT); myClearInitialCommitMessage.setSelected(settings.CLEAR_INITIAL_COMMIT_MESSAGE); myCbOfferToMoveChanges.setSelected(settings.OFFER_MOVE_TO_ANOTHER_CHANGELIST_ON_PARTIAL_COMMIT); - int id = settings.REMOVE_EMPTY_INACTIVE_CHANGELISTS.getId(); - UIUtil.setSelectedButton(myEmptyChangelistRemovingGroup, id == 0 ? 0 : id == 1 ? 2 : 1); + VcsShowConfirmationOption.Value value = settings.REMOVE_EMPTY_INACTIVE_CHANGELISTS; + UIUtil.setSelectedButton(myEmptyChangelistRemovingGroup, value == VcsShowConfirmationOption.Value.SHOW_CONFIRMATION + ? 0 + : value == VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY ? 2 : 1); myShowReadOnlyStatusDialog.setSelected(getReadOnlyStatusHandler().getState().SHOW_DIALOG); if (settings.MOVE_TO_FAILED_COMMIT_CHANGELIST == VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY) { myFailedCommitChangelistCombo.setSelectedIndex(0); From a14e96b964ddfa6f703331f19ad41d8282c21ccd Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 28 Jul 2013 14:56:10 +0400 Subject: [PATCH 35/62] VcsConfiguration: remove meaningless code around ACTIVE_VCS_NAME param The field is never updated; the startup activity seems meaningless and has no effect; the project is not needed anymore. --- .../com/intellij/openapi/vcs/VcsConfiguration.java | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsConfiguration.java b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsConfiguration.java index d482a19b5fd0..554d121e52a9 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsConfiguration.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsConfiguration.java @@ -21,7 +21,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.impl.IgnoreSpaceEnum; import com.intellij.openapi.progress.PerformInBackgroundOption; import com.intellij.openapi.project.Project; -import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.DefaultJDOMExternalizer; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; @@ -58,8 +57,6 @@ public final class VcsConfiguration implements PersistentStateComponent @NonNls public static final String PATCH = "patch"; @NonNls public static final String DIFF = "diff"; - private Project myProject; - public boolean OFFER_MOVE_TO_ANOTHER_CHANGELIST_ON_PARTIAL_COMMIT = true; public boolean CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT = !PlatformUtils.isPyCharm() && !PlatformUtils.isRubyMine(); public boolean CHECK_NEW_TODO = true; @@ -145,7 +142,6 @@ public final class VcsConfiguration implements PersistentStateComponent public float FILE_HISTORY_DIALOG_COMMENTS_SPLITTER_PROPORTION = 0.8f; public float FILE_HISTORY_DIALOG_SPLITTER_PROPORTION = 0.5f; - public String ACTIVE_VCS_NAME = null; public boolean UPDATE_GROUP_BY_PACKAGES = false; public boolean UPDATE_GROUP_BY_CHANGELIST = false; public boolean UPDATE_FILTER_BY_SCOPE = false; @@ -160,8 +156,7 @@ public final class VcsConfiguration implements PersistentStateComponent private final PerformInBackgroundOption myCheckoutOption = new CheckoutInBackgroundOption(); private final PerformInBackgroundOption myAddRemoveOption = new AddRemoveInBackgroundOption(); - public VcsConfiguration(final Project project) { - myProject = project; + public VcsConfiguration() { } public Element getState() { @@ -199,13 +194,6 @@ public final class VcsConfiguration implements PersistentStateComponent for (final Object message : messages) { saveCommitMessage(((Element)message).getAttributeValue(VALUE_ATTR)); } - if (ACTIVE_VCS_NAME != null && ACTIVE_VCS_NAME.length() > 0) { - StartupManager.getInstance(myProject).registerStartupActivity(new Runnable() { - public void run() { - ProjectLevelVcsManager.getInstance(myProject).setDirectoryMapping("", ACTIVE_VCS_NAME); - } - }); - } } public void writeExternal(Element element) throws WriteExternalException { From f847739b36c171b25277494683b814c98c083fc1 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 28 Jul 2013 15:01:33 +0400 Subject: [PATCH 36/62] VcsConfiguration: move to PersistentStateComponent standard usage Make VcsConfiguration to be the PersistentStateComponent's state. Annotate non-standard elements to keep compatibility with previous implementation. This fixes IDEA-103538, IDEA-81143 --- .../openapi/vcs/VcsConfiguration.java | 87 ++++--------------- 1 file changed, 15 insertions(+), 72 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsConfiguration.java b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsConfiguration.java index 554d121e52a9..f5e2de674959 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsConfiguration.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsConfiguration.java @@ -21,13 +21,13 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.impl.IgnoreSpaceEnum; import com.intellij.openapi.progress.PerformInBackgroundOption; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.DefaultJDOMExternalizer; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.PlatformUtils; -import org.jdom.Element; +import com.intellij.util.xmlb.XmlSerializerUtil; +import com.intellij.util.xmlb.annotations.AbstractCollection; +import com.intellij.util.xmlb.annotations.OptionTag; +import com.intellij.util.xmlb.annotations.Property; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -37,22 +37,14 @@ import java.util.List; /** * author: lesya */ - @State( name = "VcsManagerConfiguration", - storages = { - @Storage( - file = StoragePathMacros.WORKSPACE_FILE - ) - } -) -public final class VcsConfiguration implements PersistentStateComponent { + storages = { @Storage(file = StoragePathMacros.WORKSPACE_FILE) }) +public final class VcsConfiguration implements PersistentStateComponent { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.VcsConfiguration"); public final static long ourMaximumFileForBaseRevisionSize = 500 * 1000; @NonNls static final String VALUE_ATTR = "value"; - @NonNls private static final String CONFIRM_MOVE_TO_FAILED_COMMIT_ELEMENT = "confirmMoveToFailedCommit"; - @NonNls private static final String CONFIRM_REMOVE_EMPTY_CHANGELIST_ELEMENT = "confirmRemoveEmptyChangelist"; @NonNls public static final String PATCH = "patch"; @NonNls public static final String DIFF = "diff"; @@ -68,7 +60,9 @@ public final class VcsConfiguration implements PersistentStateComponent public boolean PERFORM_ADD_REMOVE_IN_BACKGROUND = true; public boolean PERFORM_ROLLBACK_IN_BACKGROUND = false; public volatile boolean CHECK_LOCALLY_CHANGED_CONFLICTS_IN_BACKGROUND = false; + @OptionTag(tag = "confirmMoveToFailedCommit", nameAttribute = "") public VcsShowConfirmationOption.Value MOVE_TO_FAILED_COMMIT_CHANGELIST = VcsShowConfirmationOption.Value.SHOW_CONFIRMATION; + @OptionTag(tag = "confirmRemoveEmptyChangelist", nameAttribute = "") public VcsShowConfirmationOption.Value REMOVE_EMPTY_INACTIVE_CHANGELISTS = VcsShowConfirmationOption.Value.SHOW_CONFIRMATION; public int CHANGED_ON_SERVER_INTERVAL = 60; public boolean SHOW_ONLY_CHANGED_IN_SELECTION_DIFF = true; @@ -129,7 +123,9 @@ public final class VcsConfiguration implements PersistentStateComponent public boolean FORCE_NON_EMPTY_COMMENT = false; public boolean CLEAR_INITIAL_COMMIT_MESSAGE = false; - private final ArrayList myLastCommitMessages = new ArrayList(); + @Property(surroundWithTag = false) + @AbstractCollection(elementTag = "MESSAGE", elementValueAttribute = "value", surroundWithTag = false) + public List myLastCommitMessages = new ArrayList(); public String LAST_COMMIT_MESSAGE = null; public boolean MAKE_NEW_CHANGELIST_ACTIVE = false; @@ -159,60 +155,12 @@ public final class VcsConfiguration implements PersistentStateComponent public VcsConfiguration() { } - public Element getState() { - try { - final Element e = new Element("state"); - writeExternal(e); - return e; - } - catch (WriteExternalException e1) { - LOG.error(e1); - return null; - } + public VcsConfiguration getState() { + return this; } - public void loadState(Element state) { - try { - readExternal(state); - } - catch (InvalidDataException e) { - LOG.error(e); - } - } - - public void readExternal(Element element) throws InvalidDataException { - DefaultJDOMExternalizer.readExternal(this, element); - Element child = element.getChild(CONFIRM_MOVE_TO_FAILED_COMMIT_ELEMENT); - if (child != null) { - MOVE_TO_FAILED_COMMIT_CHANGELIST = VcsShowConfirmationOption.Value.fromString(child.getAttributeValue(VALUE_ATTR)); - } - child = element.getChild(CONFIRM_REMOVE_EMPTY_CHANGELIST_ELEMENT); - if (child != null) { - REMOVE_EMPTY_INACTIVE_CHANGELISTS = VcsShowConfirmationOption.Value.fromString(child.getAttributeValue(VALUE_ATTR)); - } - final List messages = element.getChildren(MESSAGE_ELEMENT_NAME); - for (final Object message : messages) { - saveCommitMessage(((Element)message).getAttributeValue(VALUE_ATTR)); - } - } - - public void writeExternal(Element element) throws WriteExternalException { - DefaultJDOMExternalizer.writeExternal(this, element); - if (MOVE_TO_FAILED_COMMIT_CHANGELIST != VcsShowConfirmationOption.Value.SHOW_CONFIRMATION) { - Element confirmChild = new Element(CONFIRM_MOVE_TO_FAILED_COMMIT_ELEMENT); - confirmChild.setAttribute(VALUE_ATTR, MOVE_TO_FAILED_COMMIT_CHANGELIST.toString()); - element.addContent(confirmChild); - } - if (REMOVE_EMPTY_INACTIVE_CHANGELISTS != VcsShowConfirmationOption.Value.SHOW_CONFIRMATION) { - Element confirmChild = new Element(CONFIRM_REMOVE_EMPTY_CHANGELIST_ELEMENT); - confirmChild.setAttribute(VALUE_ATTR, REMOVE_EMPTY_INACTIVE_CHANGELISTS.toString()); - element.addContent(confirmChild); - } - for (String message : myLastCommitMessages) { - final Element messageElement = new Element(MESSAGE_ELEMENT_NAME); - messageElement.setAttribute(VALUE_ATTR, message); - element.addContent(messageElement); - } + public void loadState(VcsConfiguration state) { + XmlSerializerUtil.copyBean(state, this); } public static VcsConfiguration getInstance(Project project) { @@ -220,17 +168,12 @@ public final class VcsConfiguration implements PersistentStateComponent } public void saveCommitMessage(final String comment) { - LAST_COMMIT_MESSAGE = comment; - if (comment == null || comment.length() == 0) return; - myLastCommitMessages.remove(comment); - while (myLastCommitMessages.size() >= MAX_STORED_MESSAGES) { myLastCommitMessages.remove(0); } - myLastCommitMessages.add(comment); } From 94e69dc2d002296080879dbab22db191ed89bb2e Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 6 Aug 2013 10:49:05 +0200 Subject: [PATCH 37/62] EA-48384 - assert: MarkRootAction.actionPerformed --- .../com/intellij/ide/projectView/actions/MarkRootAction.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkRootAction.java b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkRootAction.java index 08948eff23c6..bfdf2914a636 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkRootAction.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkRootAction.java @@ -59,7 +59,9 @@ public class MarkRootAction extends DumbAwareAction { public void actionPerformed(AnActionEvent e) { Module module = e.getData(LangDataKeys.MODULE); VirtualFile[] vFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY); - assert vFiles != null; + if (module == null || vFiles == null) { + return; + } final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel(); for (VirtualFile vFile : vFiles) { ContentEntry entry = findContentEntry(model, vFile); From 2cd3930688ca8719c1cc91bc5cb7106d07cbdb0f Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 6 Aug 2013 11:16:54 +0200 Subject: [PATCH 38/62] EA-48117 - assert: ComponentManagerImpl.getPicoContainer --- .../roots/ui/configuration/projectRoot/ModuleConfigurable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleConfigurable.java index 8c90e730598d..d49e9be5576a 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleConfigurable.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleConfigurable.java @@ -99,7 +99,7 @@ public class ModuleConfigurable extends ProjectStructureElementConfigurable Date: Tue, 6 Aug 2013 14:38:33 +0200 Subject: [PATCH 39/62] kill LiteralEscaper API which isn't used any more --- .../lang/java/JavaLiteralEscaper.java | 45 ----------------- .../lang/LanguageLiteralEscapers.java | 45 ----------------- .../src/com/intellij/lang/LiteralEscaper.java | 28 ----------- .../src/META-INF/LangExtensionPoints.xml | 5 -- .../src/META-INF/XmlPlugin.xml | 2 - resources/src/META-INF/IdeaPlugin.xml | 2 - .../intellij/lang/xml/XmlLiteralEscaper.java | 48 ------------------- 7 files changed, 175 deletions(-) delete mode 100644 java/java-impl/src/com/intellij/lang/java/JavaLiteralEscaper.java delete mode 100644 platform/lang-api/src/com/intellij/lang/LanguageLiteralEscapers.java delete mode 100644 platform/lang-api/src/com/intellij/lang/LiteralEscaper.java delete mode 100644 xml/impl/src/com/intellij/lang/xml/XmlLiteralEscaper.java diff --git a/java/java-impl/src/com/intellij/lang/java/JavaLiteralEscaper.java b/java/java-impl/src/com/intellij/lang/java/JavaLiteralEscaper.java deleted file mode 100644 index 4d3712d6ae08..000000000000 --- a/java/java-impl/src/com/intellij/lang/java/JavaLiteralEscaper.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2000-2009 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.lang.java; - -import com.intellij.lang.LiteralEscaper; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiJavaToken; -import com.intellij.psi.JavaTokenType; -import com.intellij.openapi.util.text.StringUtil; - -/** - * @author yole - */ -public class JavaLiteralEscaper implements LiteralEscaper { - @Override - public String getEscapedText(final PsiElement context, final String originalText) { - if (context instanceof PsiJavaToken && ((PsiJavaToken)context).getTokenType() == JavaTokenType.STRING_LITERAL) { - return StringUtil.escapeStringCharacters(originalText); - } - return originalText; - } - - @Override - public String escapeText(String originalText) { - return StringUtil.escapeStringCharacters(originalText); - } - - @Override - public String unescapeText(String originalText) { - return StringUtil.unescapeStringCharacters(originalText); - } -} diff --git a/platform/lang-api/src/com/intellij/lang/LanguageLiteralEscapers.java b/platform/lang-api/src/com/intellij/lang/LanguageLiteralEscapers.java deleted file mode 100644 index 1ed7d41f74e6..000000000000 --- a/platform/lang-api/src/com/intellij/lang/LanguageLiteralEscapers.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2000-2009 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.lang; - -import com.intellij.psi.PsiElement; - -/** - * @author yole - */ -public class LanguageLiteralEscapers extends LanguageExtension { - public static final LanguageLiteralEscapers INSTANCE = new LanguageLiteralEscapers(); - - private LanguageLiteralEscapers() { - super("com.intellij.lang.literalEscaper", new LiteralEscaper() { - @Override - public String getEscapedText(final PsiElement context, final String originalText) { - return originalText; - } - - @Override - public String escapeText(String originalText) { - return originalText; - } - - @Override - public String unescapeText(String originalText) { - return originalText; - } - }); - } -} diff --git a/platform/lang-api/src/com/intellij/lang/LiteralEscaper.java b/platform/lang-api/src/com/intellij/lang/LiteralEscaper.java deleted file mode 100644 index 2108f2cd136a..000000000000 --- a/platform/lang-api/src/com/intellij/lang/LiteralEscaper.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2000-2009 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.lang; - -import com.intellij.psi.PsiElement; - -/** - * @author yole - */ -public interface LiteralEscaper { - String getEscapedText(PsiElement context, String originalText); - String escapeText(String originalText); - String unescapeText(String originalText); -} diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index 7d8758cee092..6bda69e29358 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -145,11 +145,6 @@
- - - - diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index f778527950c1..769a2c2a55b5 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -111,8 +111,6 @@ - - diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index f43ceb834a27..9c1d4fc51fe8 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -934,8 +934,6 @@ - - diff --git a/xml/impl/src/com/intellij/lang/xml/XmlLiteralEscaper.java b/xml/impl/src/com/intellij/lang/xml/XmlLiteralEscaper.java deleted file mode 100644 index 74df4c229d54..000000000000 --- a/xml/impl/src/com/intellij/lang/xml/XmlLiteralEscaper.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.lang.xml; - -import com.intellij.lang.ASTNode; -import com.intellij.lang.LiteralEscaper; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiElement; -import com.intellij.psi.xml.XmlElementType; -import com.intellij.psi.xml.XmlToken; - -/** - * @author Gregory.Shrago - */ -public class XmlLiteralEscaper implements LiteralEscaper { - public String getEscapedText(PsiElement context, String originalText) { - if (context instanceof XmlToken) { - context = context.getParent(); - } - - ASTNode contextNode = context != null ? context.getNode():null; - if (contextNode != null && contextNode.getElementType() == XmlElementType.XML_CDATA) { - return originalText; - } - return escapeText(originalText); - } - - public String escapeText(String originalText) { - return StringUtil.escapeXml(originalText); - } - - public String unescapeText(String originalText) { - return StringUtil.unescapeXml(originalText); - } -} From 712071401ce06183c008395f483987070ad0c599 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 6 Aug 2013 17:57:33 +0400 Subject: [PATCH 40/62] IDEA-111421 Reformat code action on spring xml config included in another config can break entire spring config --- .../XmlUnusedNamespaceInspection.java | 37 +- .../com/intellij/xml/XmlNamespacesTest.java | 22 +- .../testData/unusedNs/spring-batch-2.1.xsd | 1291 +++++++++++++++++ .../testData/unusedNs/spring-beans-2.5.xsd | 1164 +++++++++++++++ xml/tests/testData/unusedNs/spring.xml | 9 + xml/tests/testData/unusedNs/spring_after.xml | 8 + 6 files changed, 2508 insertions(+), 23 deletions(-) create mode 100644 xml/tests/testData/unusedNs/spring-batch-2.1.xsd create mode 100644 xml/tests/testData/unusedNs/spring-beans-2.5.xsd create mode 100644 xml/tests/testData/unusedNs/spring.xml create mode 100644 xml/tests/testData/unusedNs/spring_after.xml diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnusedNamespaceInspection.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnusedNamespaceInspection.java index fb366d7aacf7..2db87f70c7a9 100644 --- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnusedNamespaceInspection.java +++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnusedNamespaceInspection.java @@ -24,6 +24,7 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.reference.impl.providers.URLReference; import com.intellij.psi.impl.source.xml.SchemaPrefix; @@ -73,21 +74,21 @@ public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool XmlAttributeValue value = attribute.getValueElement(); assert value != null; holder.registerProblem(attribute, "Namespace declaration is never used", ProblemHighlightType.LIKE_UNUSED_SYMBOL, - new RemoveNamespaceDeclarationFix(declaredPrefix, false)); + new RemoveNamespaceDeclarationFix(declaredPrefix, false, !refCountHolder.isUsedNamespace(namespace))); XmlTag parent = attribute.getParent(); if (declaredPrefix.length() == 0) { XmlAttribute location = getDefaultLocation(parent); if (location != null) { holder.registerProblem(location, NAMESPACE_LOCATION_IS_NEVER_USED, ProblemHighlightType.LIKE_UNUSED_SYMBOL, - new RemoveNamespaceDeclarationFix(declaredPrefix, true)); + new RemoveNamespaceDeclarationFix(declaredPrefix, true, true)); } } else if (!refCountHolder.isUsedNamespace(namespace)) { for (PsiReference reference : getLocationReferences(namespace, parent)) { if (!XmlHighlightVisitor.hasBadResolve(reference, false)) holder.registerProblemForReference(reference, ProblemHighlightType.LIKE_UNUSED_SYMBOL, NAMESPACE_LOCATION_IS_NEVER_USED, - new RemoveNamespaceDeclarationFix(declaredPrefix, true)); + new RemoveNamespaceDeclarationFix(declaredPrefix, true, true)); } } } @@ -236,10 +237,12 @@ public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool protected final String myPrefix; private final boolean myLocationFix; + private final boolean myRemoveLocation; - private RemoveNamespaceDeclarationFix(@Nullable String prefix, boolean locationFix) { + private RemoveNamespaceDeclarationFix(@Nullable String prefix, boolean locationFix, boolean removeLocation) { myPrefix = prefix; myLocationFix = locationFix; + myRemoveLocation = removeLocation; } @NotNull @@ -306,17 +309,19 @@ public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool Document document = documentManager.getDocument(attribute.getContainingFile()); assert document != null; attribute.delete(); - if (prefix.length() == 0) { - XmlAttribute locationAttr = getDefaultLocation(parent); - if (locationAttr != null) { - locationAttr.delete(); + if (myRemoveLocation) { + if (prefix.length() == 0) { + XmlAttribute locationAttr = getDefaultLocation(parent); + if (locationAttr != null) { + locationAttr.delete(); + } + } + else { + documentManager.doPostponedOperationsAndUnblockDocument(document); + PsiReference[] references = getLocationReferences(namespace, parent); + removeReferencesOrAttribute(references); + documentManager.commitDocument(document); } - } - else { - documentManager.doPostponedOperationsAndUnblockDocument(document); - PsiReference[] references = getLocationReferences(namespace, parent); - removeReferencesOrAttribute(references); - documentManager.commitDocument(document); } } @@ -349,7 +354,7 @@ public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool public static final String NAME = "Remove unused namespace location"; private RemoveNamespaceLocationFix(String namespace) { - super(namespace, true); + super(namespace, true, true); } @NotNull @@ -360,7 +365,7 @@ public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool @Override protected void doRemove(Project project, XmlAttribute attribute, XmlTag parent) { - if (myPrefix.length() == 0) { + if (StringUtil.isEmpty(myPrefix)) { attribute.delete(); } else { diff --git a/xml/tests/src/com/intellij/xml/XmlNamespacesTest.java b/xml/tests/src/com/intellij/xml/XmlNamespacesTest.java index 03d221ce29d3..e457bdc1cfb9 100644 --- a/xml/tests/src/com/intellij/xml/XmlNamespacesTest.java +++ b/xml/tests/src/com/intellij/xml/XmlNamespacesTest.java @@ -4,7 +4,7 @@ import com.intellij.codeInsight.actions.OptimizeImportsProcessor; import com.intellij.codeInsight.daemon.impl.analysis.XmlUnusedNamespaceInspection; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.htmlInspections.XmlInspectionToolProvider; -import com.intellij.javaee.ExternalResourceManagerImpl; +import com.intellij.javaee.ExternalResourceManagerExImpl; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.testFramework.IdeaTestCase; @@ -208,6 +208,14 @@ public class XmlNamespacesTest extends CodeInsightFixtureTestCase { doOptimizeImportsTest(text); } + public void testUsedInXmlns() throws Exception { + myFixture.testHighlighting("spring.xml", "spring-beans-2.5.xsd", "spring-batch-2.1.xsd"); + IntentionAction action = myFixture.getAvailableIntention(XmlUnusedNamespaceInspection.RemoveNamespaceDeclarationFix.NAME); + assertNotNull(action); + myFixture.launchAction(action); + myFixture.checkResultByFile("spring_after.xml"); + } + private void doUnusedDeclarationTest(String text, String after, String name) throws Exception { doUnusedDeclarationTest(text, after, name, true); } @@ -241,12 +249,12 @@ public class XmlNamespacesTest extends CodeInsightFixtureTestCase { protected void setUp() throws Exception { super.setUp(); myFixture.enableInspections(new XmlInspectionToolProvider()); - ExternalResourceManagerImpl.registerResourceTemporarily("http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd", - getTestDataPath() + "/web-app_2_5.xsd", getTestRootDisposable()); - ExternalResourceManagerImpl.registerResourceTemporarily("http://xml.apache.org/axis/wsdd/", - getTestDataPath() + "/wsdd.dtd", getTestRootDisposable()); - ExternalResourceManagerImpl.registerResourceTemporarily("http://xml.apache.org/axis/wsdd/providers/java", - getTestDataPath() + "/wsdd_provider_java.xsd", getTestRootDisposable()); + ExternalResourceManagerExImpl.registerResourceTemporarily("http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd", + getTestDataPath() + "/web-app_2_5.xsd", getTestRootDisposable()); + ExternalResourceManagerExImpl.registerResourceTemporarily("http://xml.apache.org/axis/wsdd/", + getTestDataPath() + "/wsdd.dtd", getTestRootDisposable()); + ExternalResourceManagerExImpl.registerResourceTemporarily("http://xml.apache.org/axis/wsdd/providers/java", + getTestDataPath() + "/wsdd_provider_java.xsd", getTestRootDisposable()); } @Override diff --git a/xml/tests/testData/unusedNs/spring-batch-2.1.xsd b/xml/tests/testData/unusedNs/spring-batch-2.1.xsd new file mode 100644 index 000000000000..a4cadf5108e9 --- /dev/null +++ b/xml/tests/testData/unusedNs/spring-batch-2.1.xsd @@ -0,0 +1,1291 @@ + + + + + + + + + + + + + + Defines a job composed of a set of steps and + transitions between steps. The job will be exposed in + the enclosing + bean factory as a component of type Job + that can be launched using a + JobLauncher. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Defines a stage in job processing backed by a + Step. The id attribute must be specified since this + step definition + will be referred to from other elements + to form a Job flow. + + + + + + + + + + + + + + + + + Defines a flow composed of a set of steps and + transitions between steps. + + + + + + + + + + + + + + + + + + A reference to a JobExecutionListener (or a POJO + if using before-job-method / after-job-method or + source level + annotations). + + + + + + + + + + + + + + + A bean definition for a step listener (or POJO if + using *-method attributes or source level + annotations) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Defines a stage in job processing backed by a + Step. The id attribute must be specified. The + step + requires either + a chunk definition, + a tasklet reference, or a reference to a + (possibly abstract) parent step. + + + + + + + + + + + + + + + Declares job should split here into two or more + subflows. + + + + + + + + A subflow within a job, having the same + format as a job, but without a separate identity. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Declares job should include an externalized flow + here. + + + + + + + + + + + + + + + + + + + + + + Declares job should query a decider to determine + where execution should go next. + + + + + + + + + The decider is a reference to a + JobExecutionDecider that can produce a status to base + the next + transition on. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The tasklet is a reference to another bean + definition that implements + the Tasklet interface. + + + + + + + + + + If the tasklet is specified as a bean definition, then a method can be specified and a POJO + will + be adapted to the Tasklet interface. The method suggested should have the same arguments + as Tasklet.execute (or a subset), and have a compatible return type (boolean, void or RepeatStatus). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + An exception class name. + + + + + + + + + + + + + + + + + Classify an exception as "included" in the set. Exceptions of this type or a subclass are + included. + + + + + + + + + + + + + + + + Classify an exception as "excluded" from the + set. Exceptions of this type or a subclass are + excluded + + + + + + + + + + + + + + + A reference to a listener, a POJO with a + listener-annotated method, or a POJO with + a method + referenced by a + *-method attribute. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Defines a transition from this step to the + next + one depending on the value of the exit + status. + + + + + + A pattern to match against the exit status + code. Use * and ? as wildcard characters. When a + step finishes + the most + specific match will be chosen to select the next step. + Hint: + always include a default + transition with on="*". + + + + + + + The name of the step to go to next. Must + resolve to one of the other steps in this job. + + + + + + + + + Declares job should be stop at this point and + provides pointer where execution should continue + when + the job is + restarted. + + + + + + A pattern to match against the exit status + code. Use * and ? as wildcard characters. + When a step + finishes + the most specific match will be chosen to + select the next step. + + + + + + The name of the step to start on when the + stopped job is restarted. + Must resolve to one of the + other steps + in this job. + + + + + + + + + Declares job should end at this point, without + the possibility of restart. + BatchStatus will be + COMPLETED. + ExitStatus is configurable. + + + + + + A pattern to match against the exit status + code. Use * and ? as wildcard characters. + When a step + finishes + the most specific match will be chosen to + select the next step. + + + + + + The exit code value to end on, defaults to + COMPLETED. + + + + + + + + Declares job should fail at this point. + BatchStatus will be FAILED. ExitStatus is configurable. + + + + + + A pattern to match against the exit status + code. Use * and ? as wildcard characters. + When a step + finishes + the most specific match will be chosen to + select the next step. + + + + + + The exit code value to end on, defaults to + FAILED. + + + + + + + + + + + + + + + + + + + + + + + + + The name of the parent bean from which the + configuration should inherit. + + + + + + + + + + + + + Is this bean "abstract", that is, not meant to be + instantiated itself + but rather just serving as + parent for concrete + child bean definitions? + The default is "false". Specify "true" to + tell the bean factory to not + try + to instantiate that particular bean + in any case. + + Note: This attribute will not be inherited by child + bean definitions. + Hence, it needs to be specified per abstract bean + definition. + + + + + + + + + + Should this list be merged with the corresponding + list provided + by the parent? If not, it will + overwrite the parent + list. + + + + + + + + + + This attribute indicates the method from the + class that should + be used to dynamically create a + proxy. + + + + + + + + + + + + + diff --git a/xml/tests/testData/unusedNs/spring-beans-2.5.xsd b/xml/tests/testData/unusedNs/spring-beans-2.5.xsd new file mode 100644 index 000000000000..170660a6a46c --- /dev/null +++ b/xml/tests/testData/unusedNs/spring-beans-2.5.xsd @@ -0,0 +1,1164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ' element. + ]]> + + + + + + + + + + ' element. + ]]> + + + + + + + + + + + + + + ' element. + ]]> + + + + + + + + + + + + + ' element for the semantic details of autowire candidate beans. + ]]> + + + + + ' element. + ]]> + + + + + ' element. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + element (or "ref" + attribute). We recommend this in most cases as it makes documentation + more explicit. + + 2. "byName" + Autowiring by property name. If a bean of class Cat exposes a "dog" + property, Spring will try to set this to the value of the bean "dog" + in the current container. If there is no matching bean by name, nothing + special happens; use dependency-check="objects" to raise an error in + that case. + + 3. "byType" + Autowiring if there is exactly one bean of the property type in the + container. If there is more than one, a fatal error is raised, and + you cannot use byType autowiring for that bean. If there is none, + nothing special happens; use dependency-check="objects" to raise an + error in that case. + + 4. "constructor" + Analogous to "byType" for constructor arguments. If there is not exactly + one bean of the constructor argument type in the bean factory, a fatal + error is raised. + + 5. "autodetect" + Chooses "constructor" or "byType" through introspection of the bean + class. If a default constructor is found, "byType" gets applied. + + Note that explicit dependencies, i.e. "property" and "constructor-arg" + elements, always override autowiring. Autowire behavior can be combined + with dependency checking, which will be performed after all autowiring + has been completed. + + Note: This attribute will not be inherited by child bean definitions. + Hence, it needs to be specified per concrete bean definition. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + " element. + ]]> + + + + + ..." element. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ". + ]]> + + + + + ..." element. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ". + ]]> + + + + + ..." + element. + ]]> + + + + + ". + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/tests/testData/unusedNs/spring.xml b/xml/tests/testData/unusedNs/spring.xml new file mode 100644 index 000000000000..6579845e8244 --- /dev/null +++ b/xml/tests/testData/unusedNs/spring.xml @@ -0,0 +1,9 @@ + +xmlns:batch="http://www.springframework.org/schema/batch" + xsi:schemaLocation="http://www.springframework.org/schema/beans spring-beans-2.5.xsd + http://www.springframework.org/schema/batch spring-batch-2.1.xsd"> + + + diff --git a/xml/tests/testData/unusedNs/spring_after.xml b/xml/tests/testData/unusedNs/spring_after.xml new file mode 100644 index 000000000000..f1262d937f4c --- /dev/null +++ b/xml/tests/testData/unusedNs/spring_after.xml @@ -0,0 +1,8 @@ + + + + + From 1b427a30a33af1738a7fa7ad6b200294c8691280 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 6 Aug 2013 16:28:40 +0200 Subject: [PATCH 41/62] EA-48471 (diagnostic) --- .../src/com/intellij/util/Alarm.java | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/platform/platform-api/src/com/intellij/util/Alarm.java b/platform/platform-api/src/com/intellij/util/Alarm.java index 3778292dc9c1..6b9a48d3e6a8 100644 --- a/platform/platform-api/src/com/intellij/util/Alarm.java +++ b/platform/platform-api/src/com/intellij/util/Alarm.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -284,21 +284,16 @@ public class Alarm implements Disposable { myFuture = null; } - if (myThreadToUse == ThreadToUse.SWING_THREAD && !isEdt()) { - try { + try { + if (myThreadToUse == ThreadToUse.SWING_THREAD && !isEdt()) { SwingUtilities.invokeAndWait(task); } - catch (Exception e) { - LOG.error(e); - } - } - else { - try { + else { task.run(); } - catch (Exception e) { - LOG.error(e); - } + } + catch (Exception e) { + LOG.error("Exception in task " + task, e); } } }; From ffe5278818862629d86590afd8d3506e6228d46b Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 6 Aug 2013 18:40:28 +0400 Subject: [PATCH 42/62] Don't block UI then debug Grails application --- .../SpringLoadedPositionManager.java | 72 +++++++++---------- 1 file changed, 33 insertions(+), 39 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/springloaded/SpringLoadedPositionManager.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/springloaded/SpringLoadedPositionManager.java index fd819c96978f..814a5f4c0973 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/springloaded/SpringLoadedPositionManager.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/springloaded/SpringLoadedPositionManager.java @@ -53,30 +53,34 @@ public class SpringLoadedPositionManager implements PositionManager { @NotNull @Override public List getAllClasses(final SourcePosition classPosition) throws NoDataException { - AccessToken accessToken = ReadAction.start(); + int line; + String className; + AccessToken accessToken = ReadAction.start(); try { - String className = findEnclosingName(classPosition); + className = findEnclosingName(classPosition); if (className == null) throw new NoDataException(); - List referenceTypes = myDebugProcess.getVirtualMachineProxy().classesByName(className); - if (referenceTypes.isEmpty()) throw new NoDataException(); - - Set res = new HashSet(); - - for (ReferenceType referenceType : referenceTypes) { - findNested(res, referenceType, classPosition); - } - - if (res.isEmpty()) { - throw new NoDataException(); - } - - return new ArrayList(res); + line = classPosition.getLine(); } finally { accessToken.finish(); } + + List referenceTypes = myDebugProcess.getVirtualMachineProxy().classesByName(className); + if (referenceTypes.isEmpty()) throw new NoDataException(); + + Set res = new HashSet(); + + for (ReferenceType referenceType : referenceTypes) { + findNested(res, referenceType, line); + } + + if (res.isEmpty()) { + throw new NoDataException(); + } + + return new ArrayList(res); } @NotNull @@ -87,28 +91,18 @@ public class SpringLoadedPositionManager implements PositionManager { @Nullable private static String findEnclosingName(final SourcePosition position) { - AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock(); - - try { - PsiElement element = findElementAt(position); - while (true) { - element = PsiTreeUtil.getParentOfType(element, GrTypeDefinition.class, PsiClassImpl.class); - if (element == null - || (element instanceof GrTypeDefinition && !((GrTypeDefinition)element).isAnonymous()) - || (element instanceof PsiClassImpl && ((PsiClassImpl)element).getName() != null) - ) { - break; - } + PsiElement element = findElementAt(position); + while (true) { + element = PsiTreeUtil.getParentOfType(element, GrTypeDefinition.class, PsiClassImpl.class); + if (element == null + || (element instanceof GrTypeDefinition && !((GrTypeDefinition)element).isAnonymous()) + || (element instanceof PsiClassImpl && ((PsiClassImpl)element).getName() != null) + ) { + break; } + } - if (element != null) { - return getClassNameForJvm((PsiClass)element); - } - return null; - } - finally { - accessToken.finish(); - } + return null; } @Nullable @@ -167,7 +161,7 @@ public class SpringLoadedPositionManager implements PositionManager { && GENERATED_CLASS_NAME.matcher(name.substring(ownerClassName.length())).matches(); } - private static void findNested(Set res, ReferenceType fromClass, SourcePosition classPosition) { + private static void findNested(Set res, ReferenceType fromClass, int line) { if (!fromClass.isPrepared()) return; List nestedTypes = fromClass.nestedTypes(); @@ -183,12 +177,12 @@ public class SpringLoadedPositionManager implements PositionManager { } } else { - findNested(res, nested, classPosition); + findNested(res, nested, line); } } try { - final int lineNumber = classPosition.getLine() + 1; + final int lineNumber = line + 1; ReferenceType effectiveRef = springLoadedGeneratedClass == null ? fromClass : springLoadedGeneratedClass; From 19320ad7032de7f6d18f6b67ac8b7a627640c906 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 6 Aug 2013 15:49:45 +0200 Subject: [PATCH 43/62] do not update IDEA/plugin when start with params to open file/project in existing frame or command line (IDEA-111128) --- .../bootstrap/src/com/intellij/ide/Bootstrap.java | 2 +- .../src/com/intellij/ide/ClassloaderUtil.java | 4 ++-- platform/bootstrap/src/com/intellij/idea/Main.java | 14 ++++++++------ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/platform/bootstrap/src/com/intellij/ide/Bootstrap.java b/platform/bootstrap/src/com/intellij/ide/Bootstrap.java index 05280434f3d0..bc938beda8ff 100644 --- a/platform/bootstrap/src/com/intellij/ide/Bootstrap.java +++ b/platform/bootstrap/src/com/intellij/ide/Bootstrap.java @@ -35,7 +35,7 @@ public class Bootstrap { } public static void main(String[] args, String mainClass, String methodName, List classpathElements) throws Exception { - UrlClassLoader newClassLoader = ClassloaderUtil.initClassloader(classpathElements); + UrlClassLoader newClassLoader = ClassloaderUtil.initClassloader(classpathElements, args.length == 0); WindowsCommandLineProcessor.ourMirrorClass = Class.forName(WindowsCommandLineProcessor.class.getName(), true, newClassLoader); Class klass = Class.forName(PLUGIN_MANAGER, true, newClassLoader); diff --git a/platform/bootstrap/src/com/intellij/ide/ClassloaderUtil.java b/platform/bootstrap/src/com/intellij/ide/ClassloaderUtil.java index 6d6f715d026d..801c459303a3 100644 --- a/platform/bootstrap/src/com/intellij/ide/ClassloaderUtil.java +++ b/platform/bootstrap/src/com/intellij/ide/ClassloaderUtil.java @@ -49,7 +49,7 @@ public class ClassloaderUtil extends ClassUtilCore { return Logger.getInstance("ClassloaderUtil"); } - public static UrlClassLoader initClassloader(final List classpathElements) throws Exception { + public static UrlClassLoader initClassloader(final List classpathElements, boolean updatePlugins) throws Exception { PathManager.loadProperties(); addParentClasspath(classpathElements); @@ -60,7 +60,7 @@ public class ClassloaderUtil extends ClassUtilCore { UrlClassLoader newClassLoader = new UrlClassLoader(classpathElements, null, true, true); // prepare plugins - if (!isLoadingOfExternalPluginsDisabled()) { + if (updatePlugins && !isLoadingOfExternalPluginsDisabled()) { try { StartupActionScriptManager.executeActionScript(); } diff --git a/platform/bootstrap/src/com/intellij/idea/Main.java b/platform/bootstrap/src/com/intellij/idea/Main.java index 4f52325eed11..4ea58e732286 100644 --- a/platform/bootstrap/src/com/intellij/idea/Main.java +++ b/platform/bootstrap/src/com/intellij/idea/Main.java @@ -59,12 +59,14 @@ public class Main { throw new HeadlessException("Unable to detect graphics environment"); } - try { - installPatch(); - } - catch (Throwable t) { - showMessage("Update Failed", t); - System.exit(UPDATE_FAILED); + if (args.length == 0) { + try { + installPatch(); + } + catch (Throwable t) { + showMessage("Update Failed", t); + System.exit(UPDATE_FAILED); + } } } From 0b7a357578035e21e2ffdeaf4cfabfbe357ac1df Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 6 Aug 2013 15:57:07 +0200 Subject: [PATCH 44/62] IDEA-111652 'Select Methods To Propagate Parameters' dialog store dimensions --- .../refactoring/changeSignature/CallerChooserBase.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/CallerChooserBase.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/CallerChooserBase.java index 7c525027cf0f..909b44799a02 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/CallerChooserBase.java +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/CallerChooserBase.java @@ -45,6 +45,7 @@ import com.intellij.util.Query; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.TreeSelectionEvent; @@ -300,4 +301,9 @@ public abstract class CallerChooserBase extends DialogWrap return myTree; } + @Nullable + @Override + protected String getDimensionServiceKey() { + return "caller.chooser.dialog"; + } } From 14a363c3c2e3f930d704d4799e15a935638f07ad Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 6 Aug 2013 16:50:19 +0200 Subject: [PATCH 45/62] IDEA-111257 Custom scope + Autoscroll from Source : do not try to select scope which doesn't present in view --- .../intellij/ide/scopeView/ScopeViewPane.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java index 051d4cb3bcec..bf8c41fce241 100644 --- a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java +++ b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java @@ -138,10 +138,7 @@ public class ScopeViewPane extends AbstractProjectViewPane { @Override @NotNull public String[] getSubIds() { - NamedScope[] scopes = myDependencyValidationManager.getScopes(); - scopes = ArrayUtil.mergeArrays(scopes, myNamedScopeManager.getScopes()); - scopes = NonProjectFilesScope.removeFromList(scopes); - scopes = ArrayUtil.remove(scopes, CustomScopesProviderEx.getAllScope()); + NamedScope[] scopes = getShownScopes(); String[] ids = new String[scopes.length]; for (int i = 0; i < scopes.length; i++) { final NamedScope scope = scopes[i]; @@ -150,6 +147,14 @@ public class ScopeViewPane extends AbstractProjectViewPane { return ids; } + private NamedScope[] getShownScopes() { + NamedScope[] scopes = myDependencyValidationManager.getScopes(); + scopes = ArrayUtil.mergeArrays(scopes, myNamedScopeManager.getScopes()); + scopes = NonProjectFilesScope.removeFromList(scopes); + scopes = ArrayUtil.remove(scopes, CustomScopesProviderEx.getAllScope()); + return scopes; + } + @Override @NotNull public String getPresentableSubIdName(@NotNull final String subId) { @@ -183,15 +188,13 @@ public class ScopeViewPane extends AbstractProjectViewPane { if (psiFile == null) return; if (!(element instanceof PsiElement)) return; - List allScopes = new ArrayList(); - ContainerUtil.addAll(allScopes, myDependencyValidationManager.getScopes()); - ContainerUtil.addAll(allScopes, myNamedScopeManager.getScopes()); - for (int i = 0; i < allScopes.size(); i++) { - final NamedScope scope = allScopes.get(i); + NamedScope[] allScopes = getShownScopes(); + for (int i = 0; i < allScopes.length; i++) { + final NamedScope scope = allScopes[i]; String name = scope.getName(); if (name.equals(getSubId())) { - allScopes.set(i, allScopes.get(0)); - allScopes.set(0, scope); + allScopes[i] = allScopes[0]; + allScopes[0] = scope; break; } } From 634c748f5e7fc1061f3a074267b609b2da601fe7 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 6 Aug 2013 19:31:59 +0400 Subject: [PATCH 46/62] IDEA-105251 --- .../org/jetbrains/idea/svn/FilePathUtil.java | 2 +- .../idea/svn/update/SvnUpdateContext.java | 19 +++++++++++++++---- .../idea/svn/update/SvnUpdatePanel.form | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/FilePathUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/FilePathUtil.java index 374ec7f8733c..6a5c3cb0d7ab 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/FilePathUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/FilePathUtil.java @@ -32,7 +32,7 @@ public class FilePathUtil { public static boolean isNested(final Collection roots, final File root) { for (FilePath filePath : roots) { final File ioFile = filePath.getIOFile(); - if (ioFile.equals(root)) continue; + if (FileUtil.isAncestor(ioFile, root, true)) { return true; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java index 033b0deb5b32..3da7e90ad98c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java @@ -54,13 +54,24 @@ public class SvnUpdateContext implements SequentialUpdatesContext { } public boolean shouldRunFor(final File ioRoot) { - if (myUpdatedExternals.contains(ioRoot)) return false; - if (FilePathUtil.isNested(myContentRoots, ioRoot)) { + boolean result = true; + + if (myUpdatedExternals.contains(ioRoot)) { + result = false; + } + else if (FilePathUtil.isNested(myContentRoots, ioRoot)) { final RootUrlInfo info = myVcs.getSvnFileUrlMapping().getWcRootForFilePath(ioRoot); + if (info != null) { - return ! NestedCopyType.switched.equals(info.getType()); + if (NestedCopyType.switched.equals(info.getType())) { + result = false; + } + else if (NestedCopyType.external.equals(info.getType())) { + result = !myVcs.getSvnConfiguration().IGNORE_EXTERNALS; + } } } - return true; + + return result; } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.form b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.form index 9ba9df6a2107..230271b9354c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.form +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.form @@ -57,7 +57,7 @@ - + From af64533af5a21c60f755fb393d76ed2dc7c98727 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 6 Aug 2013 17:34:01 +0200 Subject: [PATCH 47/62] EA-39114 (NPE) --- .../platform-api/src/com/intellij/ide/DataManager.java | 6 ++++-- .../src/com/intellij/ide/dnd/DnDManager.java | 9 +++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ide/DataManager.java b/platform/platform-api/src/com/intellij/ide/DataManager.java index 4a0201581a8c..c535abf50392 100644 --- a/platform/platform-api/src/com/intellij/ide/DataManager.java +++ b/platform/platform-api/src/com/intellij/ide/DataManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package com.intellij.ide; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.AsyncResult; import com.intellij.openapi.util.Key; @@ -29,7 +30,8 @@ import java.awt.*; public abstract class DataManager { public static DataManager getInstance() { - return ApplicationManager.getApplication().getComponent(DataManager.class); + Application application = ApplicationManager.getApplication(); + return application != null ? application.getComponent(DataManager.class) : null; } @NonNls public static final String CLIENT_PROPERTY_DATA_PROVIDER = "DataProvider"; diff --git a/platform/platform-api/src/com/intellij/ide/dnd/DnDManager.java b/platform/platform-api/src/com/intellij/ide/dnd/DnDManager.java index b0ca95badc0d..9fb73e0cae4d 100644 --- a/platform/platform-api/src/com/intellij/ide/dnd/DnDManager.java +++ b/platform/platform-api/src/com/intellij/ide/dnd/DnDManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,10 +24,7 @@ import java.awt.*; public abstract class DnDManager { public static DnDManager getInstance() { Application application = ApplicationManager.getApplication(); - if (application == null) { - return null; - } - return (DnDManager)application.getPicoContainer().getComponentInstance(DnDManager.class.getName()); + return application != null ? (DnDManager)application.getPicoContainer().getComponentInstance(DnDManager.class.getName()) : null; } public abstract void registerSource(DnDSource source, JComponent component); @@ -41,6 +38,6 @@ public abstract class DnDManager { public abstract void registerTarget(DnDTarget target, JComponent component); public abstract void unregisterTarget(DnDTarget target, JComponent component); - + public abstract Component getLastDropHandler(); } From f824d3cd372d3b79048827082e12b2bfe389c77e Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 6 Aug 2013 19:40:18 +0400 Subject: [PATCH 48/62] remembering last injected language --- .../inject/InjectLanguageAction.java | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java index 341b8f1528d6..90fa8291b03b 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java @@ -18,6 +18,7 @@ package org.intellij.plugins.intelliLang.inject; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.ide.util.PropertiesComponent; import com.intellij.injected.editor.EditorWindow; import com.intellij.lang.Language; import com.intellij.lang.injection.InjectedLanguageManager; @@ -25,7 +26,9 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.PopupChooserBuilder; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; @@ -43,6 +46,7 @@ import com.intellij.util.FileContentUtil; import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; import org.intellij.plugins.intelliLang.Configuration; import com.intellij.psi.injection.Injectable; import org.intellij.plugins.intelliLang.references.InjectedReferencesContributor; @@ -59,6 +63,7 @@ import java.util.List; public class InjectLanguageAction implements IntentionAction { @NonNls private static final String INJECT_LANGUAGE_FAMILY = "Inject Language/Reference"; + public static final String LAST_INJECTED_LANGUAGE = "LAST_INJECTED_LANGUAGE"; public static List getAllInjectables() { Language[] languages = InjectedLanguage.getAvailableLanguages(); @@ -161,17 +166,29 @@ public class InjectLanguageAction implements IntentionAction { } } }); - new PopupChooserBuilder(list).setItemChoosenCallback(new Runnable() { + JBPopup popup = new PopupChooserBuilder(list).setItemChoosenCallback(new Runnable() { public void run() { - onChosen.process((Injectable)list.getSelectedValue()); + Injectable value = (Injectable)list.getSelectedValue(); + onChosen.process(value); + PropertiesComponent.getInstance().setValue(LAST_INJECTED_LANGUAGE, value.getId()); } }).setFilteringEnabled(new Function() { @Override public String fun(Object language) { return ((Injectable)language).getDisplayName(); } - }) - .createPopup().showInBestPositionFor(editor); + }).createPopup(); + final String lastInjected = PropertiesComponent.getInstance().getValue(LAST_INJECTED_LANGUAGE); + if (lastInjected != null) { + Injectable injectable = ContainerUtil.find(injectables, new Condition() { + @Override + public boolean value(Injectable injectable) { + return lastInjected.equals(injectable.getId()); + } + }); + list.setSelectedValue(injectable, true); + } + popup.showInBestPositionFor(editor); return true; } From 07f6928752b74591a94baab7b0bb39b0324f8524 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 6 Aug 2013 18:50:42 +0200 Subject: [PATCH 49/62] EA-48491 (NPE) --- .../src/com/intellij/codeEditor/printing/PrintManager.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintManager.java b/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintManager.java index f678716132f0..a28983107fa5 100644 --- a/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintManager.java +++ b/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintManager.java @@ -15,11 +15,7 @@ */ package com.intellij.codeEditor.printing; -import com.intellij.CommonBundle; import com.intellij.ide.highlighter.HighlighterFactory; -import com.intellij.notification.Notification; -import com.intellij.notification.NotificationType; -import com.intellij.notification.Notifications; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.actionSystem.PlatformDataKeys; @@ -160,8 +156,7 @@ class PrintManager { printerJob.cancel(); } catch (Exception e) { - Notifications.Bus.notify(new Notification("Print", CommonBundle.getErrorTitle(), e.getMessage(), NotificationType.ERROR)); - LOG.warn(e); + LOG.error(e); } } }); From 5bbb2796a9f967f3593f8dc07b25f2e05e710f70 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 6 Aug 2013 19:25:35 +0200 Subject: [PATCH 50/62] On/Off button initial --- .../ide/actions/SearchEverywhereAction.java | 16 ++- .../intellij/ui/components/OnOffButton.java | 128 ++++++++++++++++++ 2 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 platform/platform-api/src/com/intellij/ui/components/OnOffButton.java 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 c080c87c5c62..bfb072b71e8d 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java @@ -21,6 +21,7 @@ import com.intellij.ide.IdeEventQueue; import com.intellij.ide.SearchTopHitProvider; import com.intellij.ide.ui.LafManager; import com.intellij.ide.ui.LafManagerListener; +import com.intellij.ide.ui.search.BooleanOptionDescription; import com.intellij.ide.ui.search.OptionDescription; import com.intellij.ide.ui.search.SearchableOptionsRegistrarImpl; import com.intellij.ide.util.gotoByName.*; @@ -58,6 +59,7 @@ import com.intellij.psi.codeStyle.NameUtil; import com.intellij.psi.util.PsiUtilCore; import com.intellij.ui.*; import com.intellij.ui.components.JBLabel; +import com.intellij.ui.components.OnOffButton; import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; @@ -330,11 +332,19 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Component cmp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - if (myLocationString != null) { + if (myLocationString != null || value instanceof BooleanOptionDescription) { final JPanel panel = new JPanel(new BorderLayout()); - panel.setBackground(UIUtil.getListBackground()); + panel.setBackground(UIUtil.getListBackground(isSelected)); panel.add(cmp, BorderLayout.CENTER); - panel.add(myLocation.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus), BorderLayout.EAST); + final Component rightComponent; + if (value instanceof BooleanOptionDescription) { + final OnOffButton button = new OnOffButton(); + button.setSelected(((BooleanOptionDescription)value).isOptionEnabled()); + rightComponent = button; + } else { + rightComponent = myLocation.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } + panel.add(rightComponent, BorderLayout.EAST); cmp = panel; } diff --git a/platform/platform-api/src/com/intellij/ui/components/OnOffButton.java b/platform/platform-api/src/com/intellij/ui/components/OnOffButton.java new file mode 100644 index 000000000000..11dadb6a64e5 --- /dev/null +++ b/platform/platform-api/src/com/intellij/ui/components/OnOffButton.java @@ -0,0 +1,128 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.ui.components; + +import com.intellij.ui.Gray; +import com.intellij.util.ui.GraphicsUtil; +import com.intellij.util.ui.UIUtil; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicToggleButtonUI; +import java.awt.*; + +/** + * @author Konstantin Bulenkov + */ +public class OnOffButton extends JToggleButton { + private String myOnText; + private String myOffText; + public OnOffButton() { + setUI(OnOffButtonUI.createUI(this)); + setOpaque(false); + setBorder(null); + } + + public String getOnText() { + return myOnText == null ? "ON" : myOnText; + } + + public void setOnText(String onText) { + myOnText = onText; + } + + public String getOffText() { + return myOffText == null ? "OFF" : myOffText; + } + + public void setOffText(String offText) { + myOffText = offText; + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + } + + public static class OnOffButtonUI extends BasicToggleButtonUI { + private final OnOffButton myButton; + + public OnOffButtonUI(OnOffButton checkBox) { + myButton = checkBox; + } + + @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"}) + public static ComponentUI createUI(JComponent c) { + return new OnOffButtonUI((OnOffButton)c); + } + + @Override + public Dimension getPreferredSize(JComponent c) { + final OnOffButton button = (OnOffButton)c; + String text = button.getOffText().length() > button.getOnText().length() ? button.getOffText() : button.getOnText(); + text = text.toUpperCase(); + final FontMetrics fm = c.getFontMetrics(c.getFont()); + int w = fm.stringWidth(text); + int h = fm.getHeight(); + h += 2*4; + w += 3 * h / 2 + 4; + return new Dimension(w, h); + } + @Override + public void paint(Graphics gr, JComponent c) { + final OnOffButton button = (OnOffButton)c; + final Dimension size = button.getSize(); + int w = size.width-4; + int h = size.height-4; + if (h % 2 == 1) { + h--; + } + Graphics2D g = ((Graphics2D)gr); + GraphicsUtil.setupAAPainting(g); + g.translate(1,1); + if (button.isSelected()) { + g.setColor(new Color(13, 41, 62)); + g.fillRoundRect(0, 0, w, h, h, h); + g.setColor(UIUtil.getBorderColor()); + g.drawRoundRect(0, 0, w, h, h, h); + g.setColor(Gray._128); + g.fillOval(w - h + 1, 1, h - 1, h - 1); + g.setColor(UIUtil.getListForeground(true)); + g.drawString(button.getOnText(), h/2, h - 4); + } else { + g.setColor(UIUtil.getPanelBackground()); + g.fillRoundRect(0, 0, w, h, h, h); + g.setColor(UIUtil.getBorderColor()); + g.drawRoundRect(0, 0, w, h, h, h); + g.setColor(UIUtil.getLabelDisabledForeground()); + g.drawString(button.getOffText(), h + 4 , h - 4); + g.setColor(Gray._128); + g.fillOval(0, 0, h - 1, h - 1); + } + g.translate(-1, -1); + } + + @Override + public Dimension getMinimumSize(JComponent c) { + return getPreferredSize(c); + } + + @Override + public Dimension getMaximumSize(JComponent c) { + return getPreferredSize(c); + } + } +} From 6b885adf26bb01c5e2a7c105159302341ed37f35 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 6 Aug 2013 19:26:18 +0200 Subject: [PATCH 51/62] UI settings top hits --- .../intellij/ide/ui/UISimpleSettingsProvider.java | 15 +++++++++++++++ .../src/META-INF/PlatformExtensions.xml | 1 + 2 files changed, 16 insertions(+) diff --git a/platform/platform-api/src/com/intellij/ide/ui/UISimpleSettingsProvider.java b/platform/platform-api/src/com/intellij/ide/ui/UISimpleSettingsProvider.java index 38fe94bb028b..2623a55208a9 100644 --- a/platform/platform-api/src/com/intellij/ide/ui/UISimpleSettingsProvider.java +++ b/platform/platform-api/src/com/intellij/ide/ui/UISimpleSettingsProvider.java @@ -23,10 +23,25 @@ import com.intellij.util.Consumer; */ public class UISimpleSettingsProvider implements SearchTopHitProvider { private static UISettingsOptionDescription CYCLING_SCROLLING = new UISettingsOptionDescription("CYCLING_SCROLLING", "Cyclic scrolling", "appearance"); + private static UISettingsOptionDescription MEMORY_INDICATOR = new UISettingsOptionDescription("SHOW_MEMORY_INDICATOR", "Show Memory Indicator", "appearance"); @Override public void consumeTopHits(String pattern, Consumer collector) { + pattern = pattern.trim().toLowerCase(); + if (pattern.startsWith("cyc") || pattern.startsWith("scr") || patternContains(pattern, "scroll")) { + collector.consume(CYCLING_SCROLLING); + } else if (patternContains(pattern, "memo")) { + collector.consume(MEMORY_INDICATOR); + } + } + private static boolean patternContains(String pattern, String search) { + for (String s : pattern.split(" ")) { + if (s.contains(search)) { + return true; + } + } + return false; } } diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index bb3e5ba7ebe4..a7227be4a095 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -305,5 +305,6 @@ groupKey="group.names.portability.issues" enabledByDefault="false" level="WARNING" implementationClass="com.intellij.codeStyle.InconsistentLineSeparatorsInspection"/> + From 7273ccb136d83f7bf0c65e5344a5dacf8d70b3e1 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Tue, 6 Aug 2013 21:43:20 +0400 Subject: [PATCH 52/62] Extensible comment injector API --- .../config/MethodParameterInjection.java | 4 +- .../inject/java/ConcatenationInjector.java | 16 +++-- .../java/JavaLanguageInjectionSupport.java | 20 ++++-- .../plugins/intelliLang/Configuration.java | 44 ------------- .../AbstractLanguageInjectionSupport.java | 15 ++++- .../inject/CommentLanguageInjector.java | 66 +++++++++++++------ .../inject/DefaultLanguageInjector.java | 34 +++------- .../inject/InjectLanguageAction.java | 8 +-- .../intelliLang/inject/InjectorUtils.java | 32 +++++++-- .../inject/LanguageInjectionSupport.java | 12 ++-- .../inject/TemporaryPlacesInjector.java | 18 ++--- .../inject/TemporaryPlacesRegistry.java | 5 ++ .../inject/config/AbstractTagInjection.java | 4 +- .../xml/XmlLanguageInjectionSupport.java | 21 ++++-- .../inject/xml/XmlLanguageInjector.java | 8 +-- .../groovy/GrConcatenationInjector.java | 27 +++----- .../GroovyLanguageInjectionSupport.java | 7 +- 17 files changed, 184 insertions(+), 157 deletions(-) diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/MethodParameterInjection.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/MethodParameterInjection.java index 3b2a2fbad60b..464aa38ccc03 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/MethodParameterInjection.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/MethodParameterInjection.java @@ -26,7 +26,7 @@ import com.intellij.psi.*; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.util.IncorrectOperationException; import gnu.trove.THashMap; -import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport; +import org.intellij.plugins.intelliLang.inject.java.JavaLanguageInjectionSupport; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -42,7 +42,7 @@ public class MethodParameterInjection extends BaseInjection { private final Map myParameterMap = new THashMap(); public MethodParameterInjection() { - super(LanguageInjectionSupport.JAVA_SUPPORT_ID); + super(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID); } @NotNull diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java index 1bbcbaa55ac8..e5de908ce464 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java @@ -69,7 +69,7 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { myConfiguration = configuration; myProject = project; myTemporaryPlacesRegistry = temporaryPlacesRegistry; - mySupport = InjectorUtils.findNotNullInjectionSupport(LanguageInjectionSupport.JAVA_SUPPORT_ID); + mySupport = InjectorUtils.findNotNullInjectionSupport(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID); myXmlIndex = CachedValuesManager.getManager(myProject).createCachedValue(new CachedValueProvider>() { public Result> compute() { final Map, BaseInjection> map = new THashMap, BaseInjection>(); @@ -139,7 +139,7 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { if (!hasLiteral) return; final Language tempLanguage = tempInjectedLanguage == null ? null : tempInjectedLanguage.getLanguage(); final PsiFile finalContainingFile = containingFile; - InjectionProcessor injectionProcessor = new InjectionProcessor(myConfiguration, operands) { + InjectionProcessor injectionProcessor = new InjectionProcessor(myConfiguration, mySupport, operands) { @Override protected void processInjection(Language language, List> list, @@ -162,7 +162,7 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { } }; if (tempLanguage != null) { - BaseInjection baseInjection = new BaseInjection(LanguageInjectionSupport.JAVA_SUPPORT_ID); + BaseInjection baseInjection = new BaseInjection(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID); baseInjection.setInjectedLanguageId(tempInjectedLanguage.getID()); injectionProcessor.processInjectionInner(baseInjection, false); InjectorUtils.putInjectedFileUserData(registrar, LanguageInjectionSupport.TEMPORARY_INJECTED_LANGUAGE, tempInjectedLanguage); @@ -175,12 +175,14 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { public static class InjectionProcessor { private final Configuration myConfiguration; + private final LanguageInjectionSupport mySupport; private final PsiElement[] myOperands; private boolean myShouldStop; private boolean myUnparsable; - public InjectionProcessor(Configuration configuration, PsiElement... operands) { + public InjectionProcessor(Configuration configuration, LanguageInjectionSupport support, PsiElement... operands) { myConfiguration = configuration; + mySupport = support; myOperands = operands; } @@ -301,11 +303,11 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { } private boolean processCommentInjections(PsiVariable owner) { - Ref causeRef = Ref.create(); + Ref causeRef = Ref.create(); PsiElement anchor = owner.getFirstChild() instanceof PsiComment? (owner.getModifierList() != null? owner.getModifierList() : owner.getTypeElement()) : owner; if (anchor == null) return true; - BaseInjection injection = InjectorUtils.findCommentInjection(anchor, LanguageInjectionSupport.JAVA_SUPPORT_ID, causeRef); + BaseInjection injection = mySupport.findInjectionComment(anchor, causeRef); return injection == null || processCommentInjectionInner(owner, causeRef.get(), injection); } @@ -351,7 +353,7 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { final String id = AnnotationUtilEx.calcAnnotationValue(annotations, "value"); final String prefix = AnnotationUtilEx.calcAnnotationValue(annotations, "prefix"); final String suffix = AnnotationUtilEx.calcAnnotationValue(annotations, "suffix"); - final BaseInjection injection = new BaseInjection(LanguageInjectionSupport.JAVA_SUPPORT_ID); + final BaseInjection injection = new BaseInjection(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID); if (prefix != null) injection.setPrefix(prefix); if (suffix != null) injection.setSuffix(suffix); if (id != null) injection.setInjectedLanguageId(id); diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java index 70843dbd4763..7bf11d2cdb65 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java @@ -61,6 +61,7 @@ import org.intellij.plugins.intelliLang.inject.config.ui.configurables.MethodPar import org.intellij.plugins.intelliLang.util.ContextComputationProcessor; import org.intellij.plugins.intelliLang.util.PsiUtilEx; import org.jdom.Element; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -75,6 +76,8 @@ import static org.intellij.plugins.intelliLang.inject.config.MethodParameterInje */ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSupport { + @NonNls public static final String JAVA_SUPPORT_ID = "java"; + private static boolean isMine(final PsiLanguageInjectionHost psiElement) { return PsiUtilEx.isStringOrCharacterLiteral(psiElement); } @@ -93,6 +96,11 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo return new Configurable[]{new AdvancedSettingsUI(project, configuration)}; } + @Override + public boolean isApplicableTo(PsiLanguageInjectionHost host) { + return host instanceof PsiLiteralExpression; + } + public boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement) { if (!isMine(psiElement)) return false; return doInjectInJava(psiElement.getProject(), psiElement, language.getID()); @@ -105,7 +113,7 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo final PsiLiteralExpression host = (PsiLiteralExpression)psiElement; final Project project = host.getProject(); final Configuration configuration = Configuration.getProjectInstance(project); - collectInjections(host, configuration, injectionsMap, annotations); + collectInjections(host, configuration, this, injectionsMap, annotations); if (injectionsMap.isEmpty() && annotations.isEmpty()) return false; final ArrayList originalInjections = new ArrayList(injectionsMap.keySet()); @@ -129,7 +137,7 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo final PsiLiteralExpression host = (PsiLiteralExpression)psiElement; final Project project = host.getProject(); final Configuration configuration = Configuration.getProjectInstance(project); - collectInjections(host, configuration, injectionsMap, annotations); + collectInjections(host, configuration, this, injectionsMap, annotations); if (injectionsMap.isEmpty() || !annotations.isEmpty()) return false; final BaseInjection originalInjection = injectionsMap.keySet().iterator().next(); @@ -146,7 +154,7 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo } - private BaseInjection showInjectionUI(final Project project, final MethodParameterInjection methodParameterInjection) { + private static BaseInjection showInjectionUI(final Project project, final MethodParameterInjection methodParameterInjection) { final AbstractInjectionPanel panel = new MethodParameterPanel(methodParameterInjection, project); panel.reset(); final DialogBuilder builder = new DialogBuilder(project); @@ -343,10 +351,12 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo } } - private static void collectInjections(final PsiLiteralExpression host, final Configuration configuration, + private static void collectInjections(PsiLiteralExpression host, + Configuration configuration, + JavaLanguageInjectionSupport support, final HashMap> injectionsMap, final ArrayList annotations) { - new ConcatenationInjector.InjectionProcessor(configuration, host) { + new ConcatenationInjector.InjectionProcessor(configuration, support, host) { @Override protected boolean processCommentInjectionInner(PsiVariable owner, PsiElement comment, BaseInjection injection) { diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java index 867833638a08..821284f9abc9 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java @@ -186,14 +186,10 @@ public class Configuration implements PersistentStateComponent, Modific @NonNls public static final String COMPONENT_NAME = "LanguageInjectionConfiguration"; // element names - @NonNls private static final String TAG_INJECTION_NAME = "TAGS"; - @NonNls private static final String ATTRIBUTE_INJECTION_NAME = "ATTRIBUTES"; - @NonNls private static final String PARAMETER_INJECTION_NAME = "PARAMETERS"; @NonNls private static final String INSTRUMENTATION_TYPE_NAME = "INSTRUMENTATION"; @NonNls private static final String LANGUAGE_ANNOTATION_NAME = "LANGUAGE_ANNOTATION"; @NonNls private static final String PATTERN_ANNOTATION_NAME = "PATTERN_ANNOTATION"; @NonNls private static final String SUBST_ANNOTATION_NAME = "SUBST_ANNOTATION"; - @NonNls private static final String ENTRY_NAME = "entry"; @NonNls private static final String RESOLVE_REFERENCES = "RESOLVE_REFERENCES"; @NonNls private static final String LOOK_FOR_VAR_ASSIGNMENTS = "LOOK_FOR_VAR_ASSIGNMENTS"; @NonNls private static final String USE_DFA_IF_AVAILABLE = "USE_DFA_IF_AVAILABLE"; @@ -242,7 +238,6 @@ public class Configuration implements PersistentStateComponent, Modific for (LanguageInjectionSupport support : InjectorUtils.getActiveInjectionSupports()) { supports.put(support.getId(), support); } - loadStateOld(element, supports.get(LanguageInjectionSupport.XML_SUPPORT_ID), supports.get(LanguageInjectionSupport.JAVA_SUPPORT_ID)); for (Element child : element.getChildren("injection")){ final String key = child.getAttributeValue("injector-id"); final LanguageInjectionSupport support = supports.get(key); @@ -268,31 +263,6 @@ public class Configuration implements PersistentStateComponent, Modific return places.length != 0 && result.length == 0? null : result; } - private void loadStateOld(Element element, final LanguageInjectionSupport xmlSupport, final LanguageInjectionSupport javaSupport) { - if (xmlSupport != null) { - final Element xmlTagMarker = new Element("XmlTagInjection"); - myInjections.get(LanguageInjectionSupport.XML_SUPPORT_ID).addAll(readExternal(element.getChild(TAG_INJECTION_NAME), new Factory() { - public BaseInjection create() { - return xmlSupport.createInjection(xmlTagMarker); - } - })); - final Element xmlAttributeMarker = new Element("XmlAttributeInjection"); - myInjections.get(LanguageInjectionSupport.XML_SUPPORT_ID).addAll(readExternal(element.getChild(ATTRIBUTE_INJECTION_NAME), new Factory() { - public BaseInjection create() { - return xmlSupport.createInjection(xmlAttributeMarker); - } - })); - } - if (javaSupport != null) { - final Element javaMethodMarker = new Element("MethodParameterInjection"); - myInjections.get(LanguageInjectionSupport.JAVA_SUPPORT_ID).addAll(readExternal(element.getChild(PARAMETER_INJECTION_NAME), new Factory() { - public BaseInjection create() { - return javaSupport.createInjection(javaMethodMarker); - } - })); - } - } - private static boolean readBoolean(Element element, String key, boolean defValue) { final String value = JDOMExternalizerUtil.readField(element, key); if (value == null) return defValue; @@ -361,20 +331,6 @@ public class Configuration implements PersistentStateComponent, Modific return element; } - @SuppressWarnings({"unchecked"}) - private static List readExternal(Element element, Factory factory) { - final List injections = new ArrayList(); - if (element != null) { - final List list = element.getChildren(ENTRY_NAME); - for (Element entry : list) { - final T o = factory.create(); - o.loadState(entry); - injections.add(o); - } - } - return injections; - } - public static Configuration getInstance() { return ServiceManager.getService(Configuration.class); } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java index 6ba500af8a10..f7b40b637f5e 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java @@ -26,6 +26,7 @@ import com.intellij.openapi.ui.DialogBuilder; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Factory; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiLanguageInjectionHost; @@ -36,6 +37,7 @@ import org.intellij.plugins.intelliLang.Configuration; import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.intellij.plugins.intelliLang.inject.config.ui.BaseInjectionPanel; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -45,10 +47,21 @@ import javax.swing.*; */ public abstract class AbstractLanguageInjectionSupport extends LanguageInjectionSupport { - public boolean useDefaultInjector(final PsiElement host) { + @Override + public boolean isApplicableTo(PsiLanguageInjectionHost host) { + return useDefaultInjector(host); // todo temporary plugin compatibility fix. TBR + } + + public boolean useDefaultInjector(final PsiLanguageInjectionHost host) { return false; } + @Nullable + @Override + public BaseInjection findInjectionComment(@NotNull PsiElement host, @Nullable Ref commentRef) { + return InjectorUtils.findCommentInjection(host, "comment", commentRef); + } + public boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement) { return false; } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CommentLanguageInjector.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CommentLanguageInjector.java index 1bbc1e40b1f2..30d8943a4fac 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CommentLanguageInjector.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CommentLanguageInjector.java @@ -1,15 +1,15 @@ package org.intellij.plugins.intelliLang.inject; -import com.intellij.lang.Language; import com.intellij.lang.injection.MultiHostInjector; import com.intellij.lang.injection.MultiHostRegistrar; -import com.intellij.openapi.util.Ref; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.Trinity; -import com.intellij.psi.*; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiLanguageInjectionHost; +import com.intellij.util.ArrayUtil; +import org.intellij.plugins.intelliLang.Configuration; import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -18,29 +18,53 @@ import java.util.List; */ public class CommentLanguageInjector implements MultiHostInjector { + private final LanguageInjectionSupport[] mySupports; + private final LanguageInjectionSupport myInjectorSupport = new AbstractLanguageInjectionSupport() { + @NotNull + @Override + public String getId() { + return "comment"; + } + + @Override + public boolean isApplicableTo(PsiLanguageInjectionHost host) { + return true; + } + + @NotNull + @Override + public Class[] getPatternClasses() { + return ArrayUtil.EMPTY_CLASS_ARRAY; + } + }; + + + /** @noinspection UnusedParameters*/ + public CommentLanguageInjector(Configuration configuration) { + List supports = new ArrayList(InjectorUtils.getActiveInjectionSupports()); + supports.add(myInjectorSupport); + mySupports = ArrayUtil.toObjectArray(supports, LanguageInjectionSupport.class); + } + @NotNull public List> elementsToInjectIn() { return Collections.singletonList(PsiLanguageInjectionHost.class); } public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull final PsiElement context) { + if (!(context instanceof PsiLanguageInjectionHost) || !((PsiLanguageInjectionHost)context).isValidHost()) return; PsiLanguageInjectionHost host = (PsiLanguageInjectionHost)context; - if (!host.isValidHost()) return; - if (context.getClass().getSimpleName().startsWith("XmlAttribute")) return; // no injection in XML attributes, they cannot be commented - ElementManipulator manipulator = ElementManipulators.getManipulator(host); - if (manipulator == null) return; - TextRange rangeInElement = manipulator.getRangeInElement(host); - if (rangeInElement.isEmpty()) return; - PsiElement anchor = rangeInElement.getStartOffset() == 0 ? context.getParent() : context; // handle XmlText - BaseInjection injection = InjectorUtils.findCommentInjection(anchor, "comment", Ref.create()); - //BaseInjection injection = InjectorUtils.findCommentInjection(context, "comment", Ref.create()); - if (injection == null) return; - InjectedLanguage injectedLanguage = InjectedLanguage.create(injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), false); - Language language = injectedLanguage != null ? injectedLanguage.getLanguage() : null; - if (language != null) { - Trinity info = - Trinity.create(host, injectedLanguage, rangeInElement); - InjectorUtils.registerInjection(language, Collections.singletonList(info), context.getContainingFile(), registrar); + + boolean applicableFound = false; + for (LanguageInjectionSupport support : mySupports) { + if (!support.isApplicableTo(host)) continue; + if (support == myInjectorSupport && applicableFound) continue; + applicableFound = true; + + BaseInjection injection = support.findInjectionComment(host, null); + if (injection == null) continue; + if (!InjectorUtils.registerInjectionSimple(host, injection, support, registrar)) continue; + return; } } } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/DefaultLanguageInjector.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/DefaultLanguageInjector.java index 1847cd26e274..f95bea6947f2 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/DefaultLanguageInjector.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/DefaultLanguageInjector.java @@ -16,11 +16,8 @@ package org.intellij.plugins.intelliLang.inject; -import com.intellij.lang.Language; import com.intellij.lang.injection.MultiHostInjector; import com.intellij.lang.injection.MultiHostRegistrar; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.Trinity; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.util.ArrayUtil; @@ -28,7 +25,6 @@ import org.intellij.plugins.intelliLang.Configuration; import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -47,30 +43,18 @@ public final class DefaultLanguageInjector implements MultiHostInjector { return Collections.singletonList(PsiLanguageInjectionHost.class); } - public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull final PsiElement host) { + public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull final PsiElement context) { + if (!(context instanceof PsiLanguageInjectionHost) || !((PsiLanguageInjectionHost)context).isValidHost()) return; + PsiLanguageInjectionHost host = (PsiLanguageInjectionHost)context; + for (LanguageInjectionSupport support : mySupports) { + if (!support.isApplicableTo(host)) continue; if (!support.useDefaultInjector(host)) continue; + for (BaseInjection injection : myInjectionConfiguration.getInjections(support.getId())) { - if (injection.acceptsPsiElement(host)) { - final Language language = InjectedLanguage.findLanguageById(injection.getInjectedLanguageId()); - if (language == null) continue; - - final InjectedLanguage injectedLanguage = - InjectedLanguage.create(injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), false); - - List ranges = injection.getInjectedArea(host); - final List> list = - new ArrayList>(ranges.size()); - for (TextRange range : ranges) { - list.add(Trinity.create((PsiLanguageInjectionHost)host, injectedLanguage, range)); - } - //if (host.getChildren().length > 0) { - // host.putUserData(LanguageInjectionSupport.HAS_UNPARSABLE_FRAGMENTS, Boolean.TRUE); - //} - InjectorUtils.registerInjection(language, list, host.getContainingFile(), registrar); - InjectorUtils.registerSupport(support, true, registrar); - break; - } + if (!injection.acceptsPsiElement(host)) continue; + if (!InjectorUtils.registerInjectionSimple(host, injection, support, registrar)) continue; + return; } } } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java index 90fa8291b03b..070cb2d36e25 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java @@ -128,10 +128,10 @@ public class InjectLanguageAction implements IntentionAction { try { Language language = injectable.toLanguage(); for (LanguageInjectionSupport support : InjectorUtils.getActiveInjectionSupports()) { - if (support.addInjectionInPlace(language, host)) { - ((PsiModificationTrackerImpl)PsiManager.getInstance(project).getModificationTracker()).incCounter(); - return; - } + if (!support.isApplicableTo(host)) continue; + if (!support.addInjectionInPlace(language, host)) continue; + ((PsiModificationTrackerImpl)PsiManager.getInstance(project).getModificationTracker()).incCounter(); + return; } if (TemporaryPlacesRegistry.getInstance(project).getLanguageInjectionSupport().addInjectionInPlace(language, host)) { HintManager.getInstance().showInformationHint(editor, StringUtil.escapeXml(language.getDisplayName()) + " was temporarily injected"); diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java index 5615e7a396bc..01a76297235d 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java @@ -16,10 +16,8 @@ package org.intellij.plugins.intelliLang.inject; -import com.intellij.codeInsight.daemon.impl.CollectHighlightsUtil; import com.intellij.lang.Language; import com.intellij.lang.injection.MultiHostRegistrar; -import com.intellij.openapi.editor.Document; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.*; @@ -59,6 +57,32 @@ public class InjectorUtils { } + public static boolean registerInjectionSimple(@NotNull PsiLanguageInjectionHost host, + @NotNull BaseInjection injection, + @Nullable LanguageInjectionSupport support, + @NotNull MultiHostRegistrar registrar) { + Language language = InjectedLanguage.findLanguageById(injection.getInjectedLanguageId()); + if (language == null) return false; + + InjectedLanguage injectedLanguage = + InjectedLanguage.create(injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), false); + + List ranges = injection.getInjectedArea(host); + List> list = ContainerUtil.newArrayListWithExpectedSize(ranges.size()); + + for (TextRange range : ranges) { + list.add(Trinity.create(host, injectedLanguage, range)); + } + //if (host.getChildren().length > 0) { + // host.putUserData(LanguageInjectionSupport.HAS_UNPARSABLE_FRAGMENTS, Boolean.TRUE); + //} + registerInjection(language, list, host.getContainingFile(), registrar); + if (support != null) { + registerSupport(support, true, registrar); + } + return !ranges.isEmpty(); + } + public static void registerInjection(Language language, List> list, PsiFile containingFile, MultiHostRegistrar registrar) { // if language isn't injected when length == 0, subsequent edits will not cause the language to be injected as well. // Maybe IDEA core is caching a bit too aggressively here? @@ -196,12 +220,12 @@ public class InjectorUtils { return true; } - public static BaseInjection findCommentInjection(PsiElement context, final String supportId, final Ref causeRef) { + public static BaseInjection findCommentInjection(PsiElement context, final String supportId, final Ref causeRef) { return findNearestComment(context, new NullableFunction() { @Nullable @Override public BaseInjection fun(PsiComment comment) { - causeRef.set(comment); + if (causeRef != null) causeRef.set(comment); String text = ElementManipulators.getValueText(comment).trim(); return detectInjectionFromText(supportId, text); } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java index edcd194f7683..7630fe9e68f0 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java @@ -22,6 +22,7 @@ import com.intellij.openapi.options.Configurable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Factory; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.ui.SimpleColoredText; @@ -31,6 +32,7 @@ import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author Gregory.Shrago @@ -44,9 +46,6 @@ public abstract class LanguageInjectionSupport { public static Key INJECTOR_SUPPORT = Key.create("INJECTOR_SUPPORT"); public static Key SETTINGS_EDITOR = Key.create("SETTINGS_EDITOR"); - @NonNls public static final String XML_SUPPORT_ID = "xml"; - @NonNls public static final String JAVA_SUPPORT_ID = "java"; - @NonNls @NotNull public abstract String getId(); @@ -54,7 +53,12 @@ public abstract class LanguageInjectionSupport { @NotNull public abstract Class[] getPatternClasses(); - public abstract boolean useDefaultInjector(final PsiElement host); + public abstract boolean isApplicableTo(PsiLanguageInjectionHost host); + + public abstract boolean useDefaultInjector(PsiLanguageInjectionHost host); + + @Nullable + public abstract BaseInjection findInjectionComment(@NotNull PsiElement host, @Nullable Ref commentRef); public abstract boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement); diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/TemporaryPlacesInjector.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/TemporaryPlacesInjector.java index b725eaa8eb43..5139768499e1 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/TemporaryPlacesInjector.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/TemporaryPlacesInjector.java @@ -47,18 +47,20 @@ public class TemporaryPlacesInjector implements MultiHostInjector { } public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull final PsiElement context) { + if (!(context instanceof PsiLanguageInjectionHost) || !((PsiLanguageInjectionHost)context).isValidHost()) return; PsiLanguageInjectionHost host = (PsiLanguageInjectionHost)context; + PsiFile containingFile = context.getContainingFile(); InjectedLanguage injectedLanguage = myRegistry.getLanguageFor(host, containingFile); Language language = injectedLanguage != null ? injectedLanguage.getLanguage() : null; - if (language != null) { - final ElementManipulator manipulator = ElementManipulators.getManipulator(host); - if (manipulator == null) return; - List> trinities = - Collections.singletonList(Trinity.create(host, injectedLanguage, manipulator.getRangeInElement(host))); - InjectorUtils.registerInjection(language, trinities, containingFile, registrar); - InjectorUtils.registerSupport(myRegistry.getLanguageInjectionSupport(), false, registrar); - } + if (language == null) return; + + final ElementManipulator manipulator = ElementManipulators.getManipulator(host); + if (manipulator == null) return; + List> trinities = + Collections.singletonList(Trinity.create(host, injectedLanguage, manipulator.getRangeInElement(host))); + InjectorUtils.registerInjection(language, trinities, containingFile, registrar); + InjectorUtils.registerSupport(myRegistry.getLanguageInjectionSupport(), false, registrar); } } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/TemporaryPlacesRegistry.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/TemporaryPlacesRegistry.java index eaf14241183e..56d1e9863320 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/TemporaryPlacesRegistry.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/TemporaryPlacesRegistry.java @@ -50,6 +50,11 @@ public class TemporaryPlacesRegistry { return "temp"; } + @Override + public boolean isApplicableTo(PsiLanguageInjectionHost host) { + return true; + } + @NotNull @Override public Class[] getPatternClasses() { diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/AbstractTagInjection.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/AbstractTagInjection.java index 71021f5eaa8a..0662837d0574 100644 --- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/AbstractTagInjection.java +++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/AbstractTagInjection.java @@ -23,7 +23,7 @@ import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlTag; -import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport; +import org.intellij.plugins.intelliLang.inject.xml.XmlLanguageInjectionSupport; import org.intellij.plugins.intelliLang.util.StringMatcher; import org.jaxen.JaxenException; import org.jaxen.XPath; @@ -60,7 +60,7 @@ public class AbstractTagInjection extends BaseInjection { private boolean myApplyToSubTagTexts; public AbstractTagInjection() { - super(LanguageInjectionSupport.XML_SUPPORT_ID); + super(XmlLanguageInjectionSupport.XML_SUPPORT_ID); } @NotNull diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java index 8ab26e303bde..89ea02a4d029 100644 --- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java +++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java @@ -24,15 +24,13 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogBuilder; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Factory; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.patterns.*; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.xml.XmlAttribute; -import com.intellij.psi.xml.XmlAttributeValue; -import com.intellij.psi.xml.XmlTag; -import com.intellij.psi.xml.XmlText; +import com.intellij.psi.xml.*; import com.intellij.util.Consumer; import com.intellij.util.PlatformIcons; import com.intellij.util.containers.ContainerUtil; @@ -48,6 +46,7 @@ import org.intellij.plugins.intelliLang.inject.config.ui.XmlTagPanel; import org.intellij.plugins.intelliLang.inject.config.ui.configurables.XmlAttributeInjectionConfigurable; import org.intellij.plugins.intelliLang.inject.config.ui.configurables.XmlTagInjectionConfigurable; import org.jdom.Element; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -60,6 +59,8 @@ import java.util.Collections; */ public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSupport { + @NonNls public static final String XML_SUPPORT_ID = "xml"; + private static boolean isMine(final PsiLanguageInjectionHost host) { if (host instanceof XmlAttributeValue) { final PsiElement p = host.getParent(); @@ -85,8 +86,16 @@ public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSuppor return new Class[] {XmlPatterns.class}; } - public boolean useDefaultInjector(final PsiElement host) { - return false; + @Override + public boolean isApplicableTo(PsiLanguageInjectionHost host) { + return host instanceof XmlElement; + } + + @Nullable + @Override + public BaseInjection findInjectionComment(@NotNull PsiElement host, @Nullable Ref commentRef) { + if (host instanceof XmlAttributeValue) return null; + return InjectorUtils.findCommentInjection(host instanceof XmlText ? host.getParent() : host, getId(), commentRef); } @Override diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java index a05a24426dc9..f8026edb4f11 100644 --- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java +++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java @@ -63,7 +63,7 @@ public final class XmlLanguageInjector implements MultiHostInjector { public XmlLanguageInjector(Configuration configuration) { myConfiguration = configuration; - mySupport = InjectorUtils.findNotNullInjectionSupport(LanguageInjectionSupport.XML_SUPPORT_ID); + mySupport = InjectorUtils.findNotNullInjectionSupport(XmlLanguageInjectionSupport.XML_SUPPORT_ID); } @NotNull @@ -104,7 +104,7 @@ public final class XmlLanguageInjector implements MultiHostInjector { if (place instanceof XmlTag) { final XmlTag xmlTag = (XmlTag)place; - List injections = myConfiguration.getInjections(LanguageInjectionSupport.XML_SUPPORT_ID); + List injections = myConfiguration.getInjections(XmlLanguageInjectionSupport.XML_SUPPORT_ID); //noinspection ForLoopReplaceableByForEach for (int i = 0, injectionsSize = injections.size(); i < injectionsSize; i++) { final BaseInjection injection = injections.get(i); @@ -168,7 +168,7 @@ public final class XmlLanguageInjector implements MultiHostInjector { return; } - List injections = myConfiguration.getInjections(LanguageInjectionSupport.XML_SUPPORT_ID); + List injections = myConfiguration.getInjections(XmlLanguageInjectionSupport.XML_SUPPORT_ID); //noinspection ForLoopReplaceableByForEach for (int i = 0, size = injections.size(); i < size; i++) { BaseInjection injection = injections.get(i); @@ -236,7 +236,7 @@ public final class XmlLanguageInjector implements MultiHostInjector { Trinity> index = myXmlIndex; if (index == null || myConfiguration.getModificationCount() != index.first.longValue()) { final Map, BaseInjection> map = new THashMap, BaseInjection>(); - for (BaseInjection injection : myConfiguration.getInjections(LanguageInjectionSupport.XML_SUPPORT_ID)) { + for (BaseInjection injection : myConfiguration.getInjections(XmlLanguageInjectionSupport.XML_SUPPORT_ID)) { for (InjectionPlace place : injection.getInjectionPlaces()) { if (!place.isEnabled() || place.getElementPattern() == null) continue; map.put(place.getElementPattern(), injection); diff --git a/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GrConcatenationInjector.java b/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GrConcatenationInjector.java index b83f706e9796..9125490442ee 100644 --- a/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GrConcatenationInjector.java +++ b/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GrConcatenationInjector.java @@ -15,16 +15,14 @@ */ package org.intellij.plugins.intelliLang.inject.groovy; -import com.intellij.lang.Language; import com.intellij.lang.injection.MultiHostInjector; import com.intellij.lang.injection.MultiHostRegistrar; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.Trinity; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import org.intellij.plugins.intelliLang.Configuration; -import org.intellij.plugins.intelliLang.inject.InjectedLanguage; import org.intellij.plugins.intelliLang.inject.InjectorUtils; +import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport; import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.intellij.plugins.intelliLang.util.AnnotationUtilEx; import org.intellij.plugins.intelliLang.util.PsiUtilEx; @@ -94,23 +92,14 @@ public class GrConcatenationInjector implements MultiHostInjector { final PsiAnnotation[] annotations = getAnnotationFrom(annotationOwner, pair, true, true); if (annotations.length > 0) { - final String id = AnnotationUtilEx.calcAnnotationValue(annotations, "value"); - final String prefix = AnnotationUtilEx.calcAnnotationValue(annotations, "prefix"); - final String suffix = AnnotationUtilEx.calcAnnotationValue(annotations, "suffix"); - final BaseInjection injection = new BaseInjection(GroovyLanguageInjectionSupport.GROOVY_SUPPORT_ID); - if (prefix != null) injection.setPrefix(prefix); - if (suffix != null) injection.setSuffix(suffix); - if (id != null) injection.setInjectedLanguageId(id); + BaseInjection injection = new BaseInjection(GroovyLanguageInjectionSupport.GROOVY_SUPPORT_ID); - //todo suffixes & prefixes are not supported - final Language language = InjectedLanguage.findLanguageById(injection.getInjectedLanguageId()); + injection.setPrefix(StringUtil.notNullize(AnnotationUtilEx.calcAnnotationValue(annotations, "prefix"))); + injection.setSuffix(StringUtil.notNullize(AnnotationUtilEx.calcAnnotationValue(annotations, "suffix"))); + injection.setInjectedLanguageId(StringUtil.notNullize(AnnotationUtilEx.calcAnnotationValue(annotations, "value"))); - Trinity info = Trinity.create( - host, - InjectedLanguage.create(injection.getInjectedLanguageId(), prefix, suffix, true), - ElementManipulators.getManipulator(host).getRangeInElement(host) - ); - InjectorUtils.registerInjection(language, Collections.singletonList(info), host.getContainingFile(), registrar); + LanguageInjectionSupport support = InjectorUtils.findInjectionSupport(GroovyLanguageInjectionSupport.GROOVY_SUPPORT_ID); + InjectorUtils.registerInjectionSimple(host, injection, support, registrar); } } diff --git a/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GroovyLanguageInjectionSupport.java b/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GroovyLanguageInjectionSupport.java index 452bca159bd8..564677a2936f 100644 --- a/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GroovyLanguageInjectionSupport.java +++ b/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GroovyLanguageInjectionSupport.java @@ -62,10 +62,15 @@ public class GroovyLanguageInjectionSupport extends AbstractLanguageInjectionSup return new Class[] {GroovyPatterns.class}; } - public boolean useDefaultInjector(final PsiElement host) { + @Override + public boolean isApplicableTo(PsiLanguageInjectionHost host) { return host instanceof GroovyPsiElement; } + public boolean useDefaultInjector(PsiLanguageInjectionHost host) { + return true; + } + @Override public String getHelpId() { return "reference.settings.language.injection.groovy"; From 995b2b8cd4112fad8fd5bbb6b85edae57d4e6353 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Tue, 6 Aug 2013 22:19:59 +0400 Subject: [PATCH 53/62] Extensible comment injector API: fix name --- .../plugins/intelliLang/inject/java/ConcatenationInjector.java | 2 +- .../intelliLang/inject/AbstractLanguageInjectionSupport.java | 2 +- .../plugins/intelliLang/inject/CommentLanguageInjector.java | 2 +- .../plugins/intelliLang/inject/LanguageInjectionSupport.java | 2 +- .../intelliLang/inject/xml/XmlLanguageInjectionSupport.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java index e5de908ce464..b2f1360b59d9 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java @@ -307,7 +307,7 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { PsiElement anchor = owner.getFirstChild() instanceof PsiComment? (owner.getModifierList() != null? owner.getModifierList() : owner.getTypeElement()) : owner; if (anchor == null) return true; - BaseInjection injection = mySupport.findInjectionComment(anchor, causeRef); + BaseInjection injection = mySupport.findCommentInjection(anchor, causeRef); return injection == null || processCommentInjectionInner(owner, causeRef.get(), injection); } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java index f7b40b637f5e..bcfd9c5c2b8a 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java @@ -58,7 +58,7 @@ public abstract class AbstractLanguageInjectionSupport extends LanguageInjection @Nullable @Override - public BaseInjection findInjectionComment(@NotNull PsiElement host, @Nullable Ref commentRef) { + public BaseInjection findCommentInjection(@NotNull PsiElement host, @Nullable Ref commentRef) { return InjectorUtils.findCommentInjection(host, "comment", commentRef); } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CommentLanguageInjector.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CommentLanguageInjector.java index 30d8943a4fac..1869f1f6e63c 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CommentLanguageInjector.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CommentLanguageInjector.java @@ -61,7 +61,7 @@ public class CommentLanguageInjector implements MultiHostInjector { if (support == myInjectorSupport && applicableFound) continue; applicableFound = true; - BaseInjection injection = support.findInjectionComment(host, null); + BaseInjection injection = support.findCommentInjection(host, null); if (injection == null) continue; if (!InjectorUtils.registerInjectionSimple(host, injection, support, registrar)) continue; return; diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java index 7630fe9e68f0..77e875359e4c 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/LanguageInjectionSupport.java @@ -58,7 +58,7 @@ public abstract class LanguageInjectionSupport { public abstract boolean useDefaultInjector(PsiLanguageInjectionHost host); @Nullable - public abstract BaseInjection findInjectionComment(@NotNull PsiElement host, @Nullable Ref commentRef); + public abstract BaseInjection findCommentInjection(@NotNull PsiElement host, @Nullable Ref commentRef); public abstract boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement); diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java index 89ea02a4d029..6c84a879b1a6 100644 --- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java +++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java @@ -93,7 +93,7 @@ public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSuppor @Nullable @Override - public BaseInjection findInjectionComment(@NotNull PsiElement host, @Nullable Ref commentRef) { + public BaseInjection findCommentInjection(@NotNull PsiElement host, @Nullable Ref commentRef) { if (host instanceof XmlAttributeValue) return null; return InjectorUtils.findCommentInjection(host instanceof XmlText ? host.getParent() : host, getId(), commentRef); } From ad657339ffa5d689b235a27fb34a0c0db6edf3d0 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 6 Aug 2013 19:22:09 +0200 Subject: [PATCH 54/62] continue least upper bound calculation till second nested layer (IDEA-67676) --- .../src/com/intellij/psi/GenericsUtil.java | 22 ++++++++-- .../IntersectionTypes.java | 44 ++++++++++++++++++- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java index f6637fde49e1..ff3543a37f16 100644 --- a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java @@ -120,7 +120,7 @@ public class GenericsUtil { PsiType mapping2 = subst2.substitute(parameter); if (mapping1 != null && mapping2 != null) { - substitutor = substitutor.put(parameter, getLeastContainingTypeArgument(mapping1, mapping2, compared, manager)); + substitutor = substitutor.put(parameter, getLeastContainingTypeArgument(mapping1, mapping2, compared, manager, type1.equals(mapping1) && type2.equals(mapping2) ? aSuper : null, parameter)); } else { substitutor = substitutor.put(parameter, null); @@ -150,9 +150,23 @@ public class GenericsUtil { private static PsiType getLeastContainingTypeArgument(PsiType type1, PsiType type2, Set> compared, - PsiManager manager) { + PsiManager manager, + PsiClass nestedLayer, + PsiTypeParameter parameter) { Pair types = new Pair(type1, type2); - if (compared.contains(types)) return PsiWildcardType.createUnbounded(manager); + if (compared.contains(types)) { + if (nestedLayer != null) { + PsiSubstitutor subst = PsiSubstitutor.EMPTY; + for (PsiTypeParameter param : PsiUtil.typeParametersIterable(nestedLayer)) { + subst = subst.put(param, PsiWildcardType.createUnbounded(manager)); + } + subst = subst.put(parameter, getLeastContainingTypeArgument(type1, type2, compared, manager, null, null)); + + final PsiClassType boundType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createType(nestedLayer, subst); + return PsiWildcardType.createExtends(manager, boundType); + } + return PsiWildcardType.createUnbounded(manager); + } compared.add(types); try { @@ -180,7 +194,7 @@ public class GenericsUtil { } } else if (type2 instanceof PsiWildcardType) { - return getLeastContainingTypeArgument(type2, type1, compared, manager); + return getLeastContainingTypeArgument(type2, type1, compared, manager, null, null); } //Done with wildcards diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IntersectionTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IntersectionTypes.java index a197bf02df7b..b201ac5aa7ae 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IntersectionTypes.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IntersectionTypes.java @@ -8,7 +8,7 @@ class Test { } void foo() { - List> l = this.asList(String.class, Integer.class); + List> l = this.asList(String.class, Integer.class); l.size(); List objects = this.asList(new String(), new Integer(0)); objects.size(); @@ -146,7 +146,7 @@ class IDEADEV25515 { } public static final - List> SIMPLE_TYPES = + List> SIMPLE_TYPES = asList(String.class, Integer.class ,Long.class, Double.class, /*Date.class,*/ Boolean.class, Boolean.TYPE /*,String[].class */ /*,BigDecimal.class*/); @@ -179,3 +179,43 @@ public class MaximalType { class M extends MaximalType implements L{} class M2 extends MaximalType implements L{} ///////////// + + +class IDEA67676 { + interface I<T> {} + interface A extends I>{} + interface Com2 { + void foo(T t, U u); + } + interface Com1 { + void foo(T t); + } + + abstract class X { + abstract T foo(T x, T y); + + void bar(A x, A y) { + A, ? extends Com2>> f = foo(x, y); + f.hashCode(); + } + + void boo(A x, A y) { + A, ? extends Com2>> f = foo(x, y); + f.hashCode(); + } + + void baz(A x, A y) { + A>> f = foo(x, y); + f.hashCode(); + } + } + + abstract class A1 implements Com1 {} + abstract class B1 implements Com1 {} + + abstract class A2 implements Com2 {} + abstract class B2 implements Com2 {} + + abstract class A3 implements Com2 {} + abstract class B3 implements Com2 {} +} \ No newline at end of file From c8cc567c5219bc3bb26d0bdf8af55ffe480a2064 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 6 Aug 2013 20:43:25 +0200 Subject: [PATCH 55/62] do not open capture for upper level wildcards with equals constraint (IDEA-57439) --- .../source/resolve/PsiResolveHelperImpl.java | 2 +- .../genericsHighlighting/IDEA57311.java | 2 +- .../genericsHighlighting/IDEA57439.java | 43 +++++++++++++++++++ .../daemon/GenericsHighlightingTest.java | 1 + 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57439.java diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java index 1162f18a00e2..d24bfd9ff654 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java @@ -863,7 +863,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper { PsiType patternType, final ConstraintType constraintType, final int depth) { - if (arg instanceof PsiCapturedWildcardType) arg = ((PsiCapturedWildcardType)arg).getWildcard(); //reopen + if (arg instanceof PsiCapturedWildcardType && (depth < 2 || constraintType != ConstraintType.EQUALS)) arg = ((PsiCapturedWildcardType)arg).getWildcard(); //reopen if (patternType.equals(param)) { return processArgType(arg, constraintType, depth < 2); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57311.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57311.java index 2be9a4f1e4ff..9ed409cfc19f 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57311.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57311.java @@ -4,7 +4,7 @@ class A { } void bar(A x){ - baz(x.foo()); + baz(x.foo()); } void baz(A> x){} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57439.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57439.java new file mode 100644 index 000000000000..544d6c16a605 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57439.java @@ -0,0 +1,43 @@ +class A {} + +class B extends A> { + void bar(B b, B eb, B sb, B s) { + foo(b); + foo(eb); + foo(sb); + foo(s); + + foo1(b); + foo1(eb); + foo1(sb); + foo1(s); + + foo2(b); + foo2(eb); + foo2(sb); + foo2(s); + + foo3(b); + foo3(eb); + foo3(sb); + foo3(s); + + foo4(b); + foo4(eb); + foo4(sb); + foo4(s); + + foo5(b); + foo5(eb); + foo5(sb); + foo5(s); + } + + + void foo(A> x) {} + void foo1(A> x) {} + void foo2(A> x) {} + void foo3(A> x) {} + void foo4(A> x) {} + void foo5(A> x) {} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index 3abcc3c5536d..37ba2afb34a1 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -307,6 +307,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testIDEA109556() { doTest5(false); } public void testIDEA107440() { doTest5(false); } public void testIDEA57289() { doTest5(false); } + public void testIDEA57439() { doTest5(false); } public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); From 75b37b8dbf76178c3976022aa180d999b1fb19a6 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 6 Aug 2013 20:45:28 +0200 Subject: [PATCH 56/62] testdata for IDEA-57312 --- .../genericsHighlighting/IDEA57312.java | 11 +++++++++++ .../codeInsight/daemon/GenericsHighlightingTest.java | 1 + 2 files changed, 12 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57312.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57312.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57312.java new file mode 100644 index 000000000000..70be0d2c31ba --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA57312.java @@ -0,0 +1,11 @@ +class A { + A>> foo(){ + return null; + } + + void bar(A x){ + baz(x.foo()); + } + + void baz(A>> x){} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index 37ba2afb34a1..dda5aecf3a81 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -308,6 +308,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testIDEA107440() { doTest5(false); } public void testIDEA57289() { doTest5(false); } public void testIDEA57439() { doTest5(false); } + public void testIDEA57312() { doTest5(false); } public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); From 1817eba51e5ae8412203e96174405187f3129fab Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 6 Aug 2013 20:54:26 +0200 Subject: [PATCH 57/62] correct doc tag end offset calculation (IDEA-110166) --- .../completion/JavaDocCompletionContributor.java | 13 +++++++------ .../wordSelection/DocTagSelectioner.java | 12 +++++++----- .../completion/JavadocCompletionTest.groovy | 16 +++++++++++++++- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java index 45b0e26554dd..2259d2bcf23c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java @@ -18,15 +18,13 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.TailType; import com.intellij.codeInsight.completion.scope.CompletionElement; import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor; +import com.intellij.codeInsight.editorActions.wordSelection.DocTagSelectioner; import com.intellij.codeInsight.lookup.*; import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.SuppressionUtil; import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.CaretModel; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.EditorModificationUtil; -import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.editor.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; @@ -171,13 +169,16 @@ public class JavaDocCompletionContributor extends CompletionContributor { result.addElement(LookupElementBuilder.create(description).withInsertHandler(new InsertHandler() { @Override public void handleInsert(InsertionContext context, LookupElement item) { + if (context.getCompletionChar() != Lookup.REPLACE_SELECT_CHAR) return; + context.commitDocument(); PsiDocTag docTag = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiDocTag.class, false); if (docTag != null) { - int tagEnd = docTag.getTextRange().getEndOffset(); + Document document = context.getDocument(); + int tagEnd = DocTagSelectioner.getDocTagRange(docTag, document.getCharsSequence(), 0).getEndOffset(); int tail = context.getTailOffset(); if (tail < tagEnd) { - context.getDocument().deleteString(tail, tagEnd); + document.deleteString(tail, tagEnd); } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/DocTagSelectioner.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/DocTagSelectioner.java index c64d304249cb..d706a2d60ab0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/DocTagSelectioner.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/DocTagSelectioner.java @@ -36,7 +36,11 @@ public class DocTagSelectioner extends WordSelectioner { @Override public List select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) { List result = super.select(e, editorText, cursorOffset, editor); + result.add(getDocTagRange((PsiDocTag)e, editorText, cursorOffset)); + return result; + } + public static TextRange getDocTagRange(PsiDocTag e, CharSequence documentText, int minOffset) { TextRange range = e.getTextRange(); int endOffset = range.getEndOffset(); @@ -49,7 +53,7 @@ public class DocTagSelectioner extends WordSelectioner { int childStartOffset = child.getTextRange().getStartOffset(); - if (childStartOffset <= cursorOffset) { + if (childStartOffset <= minOffset) { break; } @@ -71,10 +75,8 @@ public class DocTagSelectioner extends WordSelectioner { endOffset = Math.min(childStartOffset, endOffset); } - startOffset = CharArrayUtil.shiftBackward(editorText, startOffset - 1, "* \t") + 1; + startOffset = CharArrayUtil.shiftBackward(documentText, startOffset - 1, "* \t") + 1; - result.add(new TextRange(startOffset, endOffset)); - - return result; + return new TextRange(startOffset, endOffset); } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy index a42fde0fe8ed..fedb91c8dfd6 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy @@ -221,6 +221,7 @@ class Foo { class Foo { /** * @param intParam so xxx + * @throws Foo */ void foo2(int intParam, Object param2) { } @@ -234,7 +235,20 @@ class Foo { myFixture.assertPreferredCompletionItems 0, 'some', 'some integer param' myFixture.lookup.currentItem = myFixture.lookupElements[1] myFixture.type('\t') - assert !myFixture.editor.document.text.contains('xxx') + myFixture.checkResult ''' +class Foo { + /** + * @param intParam some integer param + * @throws Foo + */ + void foo2(int intParam, Object param2) { } + + /** + * @param intParam some integer param + */ + void foo(int intParam, Object param2) { } +} +''' } public void "test see super class"() { From 9ebd7e0df04d72cc30ad78d915a6c55b7e6ab248 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 7 Aug 2013 11:46:48 +0400 Subject: [PATCH 58/62] test fixed --- .../impl/CodeInsightTestFixtureImpl.java | 2 +- .../intelliLang/ReferenceInjectionTest.java | 24 +++++++++++++++---- .../InjectedReferencesContributor.java | 7 +++++- .../InjectedReferencesInspection.java | 2 +- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index 142e23c898e5..31c7afcb8a93 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -667,7 +667,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig myFile.getName() + " at caret position, offset " + myEditor.getCaretModel().getOffset() + "\"" + - " psi structure: " + DebugUtil.psiToString(myFile, true); + " psi structure: " + DebugUtil.psiToString(myFile, true, true); return element; } diff --git a/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java b/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java index 46bebc508add..75fead477579 100644 --- a/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java +++ b/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java @@ -1,11 +1,16 @@ package org.intellij.plugins.intelliLang; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiReference; import com.intellij.psi.impl.PsiModificationTrackerImpl; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; import org.intellij.plugins.intelliLang.inject.InjectLanguageAction; import org.intellij.plugins.intelliLang.inject.UnInjectLanguageAction; import org.intellij.plugins.intelliLang.references.FileReferenceInjector; +import org.intellij.plugins.intelliLang.references.InjectedReferencesContributor; import org.intellij.plugins.intelliLang.references.InjectedReferencesInspection; import org.jdom.Element; @@ -28,8 +33,9 @@ public class ReferenceInjectionTest extends LightPlatformCodeInsightFixtureTestC assertFalse(new InjectLanguageAction().isAvailable(getProject(), myFixture.getEditor(), myFixture.getFile())); assertTrue(new UnInjectLanguageAction().isAvailable(getProject(), myFixture.getEditor(), myFixture.getFile())); - myFixture.configureByText("bar.xml", "http://foo.bar\" \n" + - " xxx=\"bar\"/>"); + myFixture.configureByText("bar.xml", + "http://foo.bar\" \n" + + " xxx=\"bar\"/>"); myFixture.testHighlighting(); UnInjectLanguageAction.invokeImpl(getProject(), myFixture.getEditor(), myFixture.getFile()); @@ -72,13 +78,21 @@ public class ReferenceInjectionTest extends LightPlatformCodeInsightFixtureTestC " return \"bar.xml\";\n" + " } \n" + "}"); - assertNull(myFixture.getReferenceAtCaretPosition()); + assertNull(getInjectedReferences()); InjectLanguageAction.invokeImpl(getProject(), myFixture.getEditor(), myFixture.getFile(), new FileReferenceInjector()); - assertNotNull(myFixture.getReferenceAtCaretPosition()); + assertNotNull(getInjectedReferences()); UnInjectLanguageAction.invokeImpl(getProject(), myFixture.getEditor(), myFixture.getFile()); - assertNull(myFixture.getReferenceAtCaretPosition()); + assertNull(getInjectedReferences()); + } + + private PsiReference[] getInjectedReferences() { + PsiElement element = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); + element = PsiTreeUtil.getParentOfType(element, PsiLanguageInjectionHost.class); + assertNotNull(element); + element.getReferences(); + return InjectedReferencesContributor.getInjectedReferences(element); } @Override diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java index 5694661988bc..69d781992881 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesContributor.java @@ -40,12 +40,17 @@ import java.util.List; */ public class InjectedReferencesContributor extends PsiReferenceContributor { - static final Key INJECTED_REFERENCES = Key.create("injected references"); + private static final Key INJECTED_REFERENCES = Key.create("injected references"); public static boolean isInjected(@Nullable PsiReference reference) { return reference != null && reference.getElement().getUserData(INJECTED_REFERENCES) != null; } + @Nullable + public static PsiReference[] getInjectedReferences(PsiElement element) { + return element.getUserData(INJECTED_REFERENCES); + } + @Override public void registerReferenceProviders(PsiReferenceRegistrar registrar) { registrar.registerReferenceProvider(PlatformPatterns.psiElement(), new PsiReferenceProvider() { diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesInspection.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesInspection.java index 3d0920724c5e..1f8f68249bb5 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesInspection.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/InjectedReferencesInspection.java @@ -35,7 +35,7 @@ public class InjectedReferencesInspection extends LocalInspectionTool { @Override public void visitElement(PsiElement element) { - PsiReference[] injected = element.getUserData(InjectedReferencesContributor.INJECTED_REFERENCES); + PsiReference[] injected = InjectedReferencesContributor.getInjectedReferences(element); if (injected != null) { for (PsiReference reference : injected) { if (reference.resolve() == null) { From 1f3e1c4946cb661e4bb798e51f070fc0ef2f2e3b Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 7 Aug 2013 11:50:29 +0400 Subject: [PATCH 59/62] cleanup --- .../plugins/intelliLang/inject/InjectLanguageAction.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java index 070cb2d36e25..6ff3d9856996 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java @@ -128,10 +128,9 @@ public class InjectLanguageAction implements IntentionAction { try { Language language = injectable.toLanguage(); for (LanguageInjectionSupport support : InjectorUtils.getActiveInjectionSupports()) { - if (!support.isApplicableTo(host)) continue; - if (!support.addInjectionInPlace(language, host)) continue; - ((PsiModificationTrackerImpl)PsiManager.getInstance(project).getModificationTracker()).incCounter(); - return; + if (support.isApplicableTo(host) && support.addInjectionInPlace(language, host)) { + return; + } } if (TemporaryPlacesRegistry.getInstance(project).getLanguageInjectionSupport().addInjectionInPlace(language, host)) { HintManager.getInstance().showInformationHint(editor, StringUtil.escapeXml(language.getDisplayName()) + " was temporarily injected"); @@ -142,6 +141,7 @@ public class InjectLanguageAction implements IntentionAction { FileContentUtil.reparseFiles(project, Collections.emptyList(), true); } else { + ((PsiModificationTrackerImpl)PsiManager.getInstance(project).getModificationTracker()).incCounter(); DaemonCodeAnalyzer.getInstance(project).restart(); } } From 1052a3edc5f613a4934fcd55230a32de02628f40 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 7 Aug 2013 11:57:34 +0400 Subject: [PATCH 60/62] [git] Start the background task from the EDT --- .../src/git4idea/branch/GitMergeOperation.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/src/git4idea/branch/GitMergeOperation.java b/plugins/git4idea/src/git4idea/branch/GitMergeOperation.java index fadba7dabc25..ba075a6ebe89 100644 --- a/plugins/git4idea/src/git4idea/branch/GitMergeOperation.java +++ b/plugins/git4idea/src/git4idea/branch/GitMergeOperation.java @@ -19,6 +19,7 @@ import com.intellij.dvcs.DvcsUtil; import com.intellij.notification.Notification; import com.intellij.notification.NotificationListener; import com.intellij.notification.NotificationType; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -159,8 +160,13 @@ class GitMergeOperation extends GitBranchOperation { switch (myDeleteOnMerge) { case DELETE: super.notifySuccess(message); - GitBrancher brancher = ServiceManager.getService(myProject, GitBrancher.class); - brancher.deleteBranch(myBranchToMerge, new ArrayList(getRepositories())); + ApplicationManager.getApplication().invokeLater(new Runnable() { // bg process needs to be started from the EDT + @Override + public void run() { + GitBrancher brancher = ServiceManager.getService(myProject, GitBrancher.class); + brancher.deleteBranch(myBranchToMerge, new ArrayList(getRepositories())); + } + }); break; case PROPOSE: String description = message + "
Delete " + myBranchToMerge + ""; From 7cae3485cc9562b5660f7ddedf84c46aae807c94 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 7 Aug 2013 12:17:15 +0400 Subject: [PATCH 61/62] IDEA-111474 Task management: Open Task dialog opens behind quick doc popup --- .../src/com/intellij/tasks/actions/GotoTaskAction.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/GotoTaskAction.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/GotoTaskAction.java index 906f27c19650..cdc20c5e5625 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/GotoTaskAction.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/GotoTaskAction.java @@ -1,15 +1,18 @@ package com.intellij.tasks.actions; +import com.intellij.codeInsight.documentation.DocumentationManager; import com.intellij.ide.actions.GotoActionBase; import com.intellij.ide.util.gotoByName.ChooseByNameBase; import com.intellij.ide.util.gotoByName.ChooseByNameItemProvider; import com.intellij.ide.util.gotoByName.ChooseByNamePopup; import com.intellij.ide.util.gotoByName.SimpleChooseByNameModel; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiManager; import com.intellij.tasks.LocalTask; @@ -163,8 +166,10 @@ public class GotoTaskAction extends GotoActionBase implements DumbAware { }, null, popup); } - public static void showOpenTaskDialog(final Project project, final Task task) { - SwingUtilities.invokeLater(new Runnable() { + private static void showOpenTaskDialog(final Project project, final Task task) { + JBPopup hint = DocumentationManager.getInstance(project).getDocInfoHint(); + if (hint != null) hint.cancel(); + ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { new OpenTaskDialog(project, task).show(); From fd582aadbf573144f1ebda6ef66f0cf830006bb9 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 7 Aug 2013 12:33:23 +0400 Subject: [PATCH 62/62] IDEA-111616 External System: Run Configurations: project selector passes selected project to default run configurations --- .../util/ExternalSystemApiUtil.java | 17 ++++++++++++++--- .../ExternalSystemTaskSettingsControl.java | 2 +- .../service/ui/ExternalProjectPathField.java | 3 +++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java index b2c18c6bd5b9..39016299b6be 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java @@ -405,11 +405,22 @@ public class ExternalSystemApiUtil { @NotNull public static String getProjectRepresentationName(@NotNull String targetProjectPath, @Nullable String rootProjectPath) { if (rootProjectPath == null) { - return new File(targetProjectPath).getParentFile().getName(); + File rootProjectDir = new File(targetProjectPath); + if (rootProjectDir.isFile()) { + rootProjectDir = rootProjectDir.getParentFile(); + } + return rootProjectDir.getName(); + } + File rootProjectDir = new File(rootProjectPath); + if (rootProjectDir.isFile()) { + rootProjectDir = rootProjectDir.getParentFile(); + } + File targetProjectDir = new File(targetProjectPath); + if (targetProjectDir.isFile()) { + targetProjectDir = targetProjectDir.getParentFile(); } - File rootProjectDir = new File(rootProjectPath).getParentFile(); StringBuilder buffer = new StringBuilder(); - for (File f = new File(targetProjectPath).getParentFile(); f != null && !FileUtil.filesEqual(f, rootProjectDir); f = f.getParentFile()) { + for (File f = targetProjectDir; f != null && !FileUtil.filesEqual(f, rootProjectDir); f = f.getParentFile()) { buffer.insert(0, f.getName()).insert(0, ":"); } buffer.insert(0, rootProjectDir.getName()); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskSettingsControl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskSettingsControl.java index 266b3bb5d33b..b5091d710cfc 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskSettingsControl.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskSettingsControl.java @@ -117,7 +117,7 @@ public class ExternalSystemTaskSettingsControl implements ExternalSystemSettings String path = myOriginalSettings.getExternalProjectPath(); if (StringUtil.isEmpty(path)) { - path = ExternalSystemApiUtil.getLastUsedExternalProjectPath(myExternalSystemId); + path = ""; } myProjectPathField.setText(path); myTasksTextField.setText(StringUtil.join(myOriginalSettings.getTaskNames(), " ")); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectPathField.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectPathField.java index 4e8e245f3433..bcf49e497ea0 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectPathField.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectPathField.java @@ -241,6 +241,9 @@ public class ExternalProjectPathField extends ComponentWithBrowseButton