From b1dcc7fb64389a1a779713a5bce2197c75217c4b Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Thu, 11 Oct 2012 21:50:16 +0400 Subject: [PATCH 01/51] cleanup --- .../src/com/intellij/openapi/fileTypes/InternalFileType.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/platform/core-api/src/com/intellij/openapi/fileTypes/InternalFileType.java b/platform/core-api/src/com/intellij/openapi/fileTypes/InternalFileType.java index fb61d44013f1..715af99d1f3d 100644 --- a/platform/core-api/src/com/intellij/openapi/fileTypes/InternalFileType.java +++ b/platform/core-api/src/com/intellij/openapi/fileTypes/InternalFileType.java @@ -15,8 +15,6 @@ */ package com.intellij.openapi.fileTypes; -import com.intellij.openapi.fileTypes.FileType; - /** * @author gregsh */ From 978a0a6c160e6ee2ca30d9cb502309bd75424b71 Mon Sep 17 00:00:00 2001 From: Shaverdova Elena Date: Thu, 11 Oct 2012 21:55:36 +0400 Subject: [PATCH 02/51] WI-13901 PHAR: PHAR urls are absolute in the project .iml file --- .../src/META-INF/PlatformExtensionPoints.xml | 1 + .../PathMacroExpendableProtocolBean.java | 26 +++++++++++++++++++ .../options/ReplacePathToMacroMap.java | 12 ++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 platform/projectModel-impl/src/com/intellij/application/options/PathMacroExpendableProtocolBean.java diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml index fbd4f6b0dc18..4e910b62ea30 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml @@ -139,6 +139,7 @@ + diff --git a/platform/projectModel-impl/src/com/intellij/application/options/PathMacroExpendableProtocolBean.java b/platform/projectModel-impl/src/com/intellij/application/options/PathMacroExpendableProtocolBean.java new file mode 100644 index 000000000000..86ce4cacf768 --- /dev/null +++ b/platform/projectModel-impl/src/com/intellij/application/options/PathMacroExpendableProtocolBean.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2012 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.application.options; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.util.xmlb.annotations.Attribute; + +public class PathMacroExpendableProtocolBean { + public static ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.pathMacroExpendableProtocol"); + + @Attribute("protocol") + public String protocol; +} diff --git a/platform/projectModel-impl/src/com/intellij/application/options/ReplacePathToMacroMap.java b/platform/projectModel-impl/src/com/intellij/application/options/ReplacePathToMacroMap.java index 2a895d8a486c..0068a417d4e1 100644 --- a/platform/projectModel-impl/src/com/intellij/application/options/ReplacePathToMacroMap.java +++ b/platform/projectModel-impl/src/com/intellij/application/options/ReplacePathToMacroMap.java @@ -17,6 +17,7 @@ package com.intellij.application.options; import com.intellij.openapi.components.PathMacroMap; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.StringBuilderSpinAllocator; import com.intellij.util.containers.ContainerUtil; @@ -37,7 +38,16 @@ public class ReplacePathToMacroMap extends PathMacroMap { private List myPathsIndex = null; private final Map myMacroMap = ContainerUtilRt.newLinkedHashMap(); - @NonNls private static final String[] PROTOCOLS = new String[]{"file", "jar"}; + @NonNls private static final String[] PROTOCOLS; + static { + List protocols = new ArrayList(); + protocols.add("file"); + protocols.add("jar"); + for (PathMacroExpendableProtocolBean bean : PathMacroExpendableProtocolBean.EP_NAME.getExtensions()) { + protocols.add(bean.protocol); + } + PROTOCOLS = ArrayUtil.toStringArray(protocols); + } public void addMacroReplacement(String path, String macroName) { addReplacement(quotePath(path), "$" + macroName + "$", true); From 03815ee42ce65189859114bed1b5d223d1400e84 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 11 Oct 2012 15:42:02 +0200 Subject: [PATCH 03/51] IDEA-92730 Invalid GroovyDoc breaks code completion --- .../groovy/highlighter/GroovyBraceMatcher.java | 4 +--- .../groovy/lang/formatter/EnterActionTest.groovy | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/highlighter/GroovyBraceMatcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/highlighter/GroovyBraceMatcher.java index b00587a4cc70..12315bbe4dbf 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/highlighter/GroovyBraceMatcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/highlighter/GroovyBraceMatcher.java @@ -33,8 +33,6 @@ import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*; import static org.jetbrains.plugins.groovy.lang.lexer.TokenSets.COMMENT_SET; /** - * Brace matcher for Groovy language - * * @author ilyas */ public class GroovyBraceMatcher implements PairedBraceMatcher { @@ -44,7 +42,7 @@ public class GroovyBraceMatcher implements PairedBraceMatcher { new BracePair(mLBRACK, mRBRACK, false), new BracePair(mLCURLY, mRCURLY, true), - new BracePair(mGDOC_INLINE_TAG_START, mGDOC_INLINE_TAG_END, true), + new BracePair(mGDOC_INLINE_TAG_START, mGDOC_INLINE_TAG_END, false), new BracePair(mGDOC_TAG_VALUE_LPAREN, mGDOC_TAG_VALUE_RPAREN, false), new BracePair(mGSTRING_BEGIN, mGSTRING_END, false), diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/EnterActionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/EnterActionTest.groovy index 99a7284de2a9..361d262ec905 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/EnterActionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/EnterActionTest.groovy @@ -325,5 +325,20 @@ print "\\ ''' } + public void "test enter after doc with wrong braces"() { + doTest ''' +/** + * {@link #z + */ +protected void z() { +}''', ''' +/** + * {@link #z + */ +protected void z() { + +}''' + } + } From adb780207acc3f344ce560f66174f5df17925028 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 11 Oct 2012 16:41:25 +0200 Subject: [PATCH 04/51] IDEA-89883 IDEA doesn't add closing "}" after typing "{" if "unbalanced" brackets appear in Javadoc --- .../lang/groovydoc/lexer/GroovyDocLexer.java | 37 +++++++++++++++++-- .../groovy/lang/GroovyEditingTest.groovy | 20 ++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/lexer/GroovyDocLexer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/lexer/GroovyDocLexer.java index 95aefa370e8c..6bfba48d83bf 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/lexer/GroovyDocLexer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/lexer/GroovyDocLexer.java @@ -16,7 +16,9 @@ package org.jetbrains.plugins.groovy.lang.groovydoc.lexer; +import com.intellij.lexer.Lexer; import com.intellij.lexer.LexerBase; +import com.intellij.lexer.LookAheadLexer; import com.intellij.lexer.MergingLexerAdapter; import com.intellij.psi.TokenType; import com.intellij.psi.tree.IElementType; @@ -36,11 +38,40 @@ public class GroovyDocLexer extends MergingLexerAdapter implements GroovyDocToke ); public GroovyDocLexer() { - super(new AsteriskStripperLexer(new _GroovyDocLexer()), - TOKENS_TO_MERGE); + super(new LookAheadLexer(new AsteriskStripperLexer(new _GroovyDocLexer())) { + @Override + protected void lookAhead(Lexer baseLexer) { + if (baseLexer.getTokenType() == mGDOC_INLINE_TAG_END) { + advanceAs(baseLexer, mGDOC_COMMENT_DATA); + return; + } + + if (baseLexer.getTokenType() == mGDOC_INLINE_TAG_START) { + int depth = 0; + while (true) { + IElementType type = baseLexer.getTokenType(); + if (type == null) { + break; + } + if (type == mGDOC_INLINE_TAG_START) { + depth++; + } + advanceLexer(baseLexer); + if (type == mGDOC_INLINE_TAG_END) { + depth--; + } + if (depth == 0) { + break; + } + } + return; + } + + super.lookAhead(baseLexer); + } + }, TOKENS_TO_MERGE); } - private static class AsteriskStripperLexer extends LexerBase { private final _GroovyDocLexer myFlexLexer; private CharSequence myBuffer; diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyEditingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyEditingTest.groovy index e3363395ef92..4475267f66df 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyEditingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyEditingTest.groovy @@ -60,4 +60,24 @@ public class GroovyEditingTest extends LightCodeInsightFixtureTestCase { myFixture.type('"') myFixture.checkResult('""""""') } + + public void "test pair brace after doc with mismatch"() { + myFixture.configureByText 'a.groovy', ''' +class Foo { + /** + * @param o closure to run in {@code ant.zip{ .. }} context + */ + void getProject( Object o ) +} +''' + myFixture.type('{') + myFixture.checkResult ''' +class Foo { + /** + * @param o closure to run in {@code ant.zip{ .. }} context + */ + void getProject( Object o ) {} +} +''' + } } \ No newline at end of file From 8e7bc5e89897f7088589222f310828a9590f2bce Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 11 Oct 2012 16:50:03 +0200 Subject: [PATCH 05/51] PsiType substitution validity assertions (EA-39474) --- .../com/intellij/psi/impl/PsiSubstitutorImpl.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java index 608eeccfa561..b21bc6bb3415 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java @@ -248,11 +248,16 @@ public class PsiSubstitutorImpl implements PsiSubstitutor { final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics(); final PsiClass aClass = resolveResult.getElement(); if (aClass == null) return classType; + assert classType.isValid(); assert aClass.isValid(); if (aClass instanceof PsiTypeParameter) { final PsiTypeParameter typeParameter = (PsiTypeParameter)aClass; if (containsInMap(typeParameter)) { - return substituteTypeParameter(typeParameter); + PsiType result = substituteTypeParameter(typeParameter); + if (result != null) { + assert result.isValid(); + } + return result; } else { return classType; @@ -262,8 +267,9 @@ public class PsiSubstitutorImpl implements PsiSubstitutor { if (!processClass(aClass, resolveResult.getSubstitutor(), hashMap)) { return null; } - return JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory() - .createType(aClass, createSubstitutor(hashMap), classType.getLanguageLevel()); + PsiClassType result = JavaPsiFacade.getElementFactory(aClass.getProject()).createType(aClass, createSubstitutor(hashMap), classType.getLanguageLevel()); + assert result.isValid(); + return result; } private PsiType substituteTypeParameter(final PsiTypeParameter typeParameter) { From 79a7af7d6ff1b71c7a982d618d36a37763940b9b Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 11 Oct 2012 16:54:32 +0200 Subject: [PATCH 06/51] uncomment and fix one dfa test --- .../inspection/dataFlow/SCR15406/src/CodeFlowTest.java | 3 +++ .../com/intellij/codeInspection/DataFlowInspectionTest.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/java/java-tests/testData/inspection/dataFlow/SCR15406/src/CodeFlowTest.java b/java/java-tests/testData/inspection/dataFlow/SCR15406/src/CodeFlowTest.java index 187d602f646e..f2953d7d90a3 100644 --- a/java/java-tests/testData/inspection/dataFlow/SCR15406/src/CodeFlowTest.java +++ b/java/java-tests/testData/inspection/dataFlow/SCR15406/src/CodeFlowTest.java @@ -1,3 +1,5 @@ +import org.jetbrains.annotations.NotNull; + public class CodeFlowTest { public static void main (String[] args) { String string; @@ -16,6 +18,7 @@ public class CodeFlowTest { exception.printStackTrace(); } + @NotNull private static String getString () throws SomeException { if (Math.random() < 0.5) throw new SomeException(); diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index 0d8517550dea..083c1c09391a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -116,6 +116,6 @@ public class DataFlowInspectionTest extends InspectionTestCase { public void testSwitchEnumCases() { doTest15(); } public void testTryWithResources() { doTest15(true); } - //public void testSCR15406() { doTest(); } // added by cdr, 2005 + public void testSCR15406() { doTest(); } //public void testIDEADEV11033() { doTest15(); } // added by max, 2007 } From 1599162ebd1f3f9e319fc56e8c0ad20f16d001e5 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 11 Oct 2012 20:14:45 +0200 Subject: [PATCH 07/51] don't let ProcessCanceledException out of indexer --- .../openapi/project/CacheUpdateRunner.java | 3 +- .../openapi/project/FileContentQueue.java | 51 ++++++++----------- 2 files changed, 22 insertions(+), 32 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateRunner.java b/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateRunner.java index 6b122d2f9f01..46e586cfc845 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateRunner.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateRunner.java @@ -215,13 +215,14 @@ class CacheUpdateRunner { if (myProject.isDisposed()) return; if (myInnerIndicator.isCanceled()) return; - final FileContent fileContent = myQueue.take(myInnerIndicator); + final FileContent fileContent = myQueue.take(); if (fileContent == null) { myFinished.set(Boolean.TRUE); return; } try { + myQueue.waitForOtherContentReleaseToPreventOOM(myInnerIndicator, fileContent); final Runnable action = new Runnable() { public void run() { myInnerIndicator.checkCanceled(); diff --git a/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.java b/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.java index ce7b78a3a9f2..7033f496f972 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.java @@ -139,47 +139,36 @@ public class FileContentQueue { } } - @Nullable - public FileContent take(@NotNull ProgressIndicator indicator) { - FileContent content = doTake(); - if (content != null) { - final long length = content.getLength(); - while (true) { + void waitForOtherContentReleaseToPreventOOM(ProgressIndicator indicator, FileContent content) { + final long length = content.getLength(); + while (true) { + indicator.checkCanceled(); + synchronized (this) { + boolean requestingLargeSize = length > LARGE_SIZE_REQUEST_THRESHOLD; + if (requestingLargeSize) { + myLargeSizeRequested = true; + } try { - indicator.checkCanceled(); - } - catch (ProcessCanceledException e) { - pushback(content); - throw e; - } - synchronized (this) { - boolean requestingLargeSize = length > LARGE_SIZE_REQUEST_THRESHOLD; - if (requestingLargeSize) { - myLargeSizeRequested = true; - } - try { - if (myLargeSizeRequested && !requestingLargeSize || - myTakenSize + length > Math.max(TAKEN_FILES_THRESHOLD, length)) - wait(300L); - else { - myTakenSize += length; - if (requestingLargeSize) { - myLargeSizeRequested = false; - } - return content; + if (myLargeSizeRequested && !requestingLargeSize || + myTakenSize + length > Math.max(TAKEN_FILES_THRESHOLD, length)) + wait(300L); + else { + myTakenSize += length; + if (requestingLargeSize) { + myLargeSizeRequested = false; } + return; } - catch (InterruptedException ignore) { + } + catch (InterruptedException ignore) { - } } } } - return content; } @Nullable - private FileContent doTake() { + FileContent take() { FileContent result; synchronized (this) { result = myPushbackBuffer.poll(); From 2573e83aee4a7ee5a02201c6d0cd09b042ec0588 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 11 Oct 2012 20:15:38 +0200 Subject: [PATCH 08/51] make DumbService control flow a bit clearer (imho) --- .../openapi/project/DumbServiceImpl.java | 118 ++++++++---------- 1 file changed, 54 insertions(+), 64 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java index e8d710a22114..ef45a30dba29 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java @@ -40,6 +40,7 @@ import com.intellij.util.io.storage.HeavyProcessLatch; import com.intellij.util.messages.MessageBus; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import javax.swing.*; @@ -299,7 +300,6 @@ public class DumbServiceImpl extends DumbService { public void run() { ProgressManager.getInstance().run(new Task.Backgroundable(myProject, IdeBundle.message("progress.indexing"), false) { - private final BlockingQueue> myActionQueue = new LinkedBlockingQueue>(); @Override public void run(@NotNull final ProgressIndicator indicator) { @@ -347,6 +347,10 @@ public class DumbServiceImpl extends DumbService { shutdownTracker.registerStopperThread(self); runAction(proxy, myAction); } + catch (RuntimeException e) { + LOG.debug(e); + throw e; + } finally { shutdownTracker.unregisterStopperThread(self); HeavyProcessLatch.INSTANCE.processFinished(); @@ -354,80 +358,66 @@ public class DumbServiceImpl extends DumbService { } private void runAction(ProgressIndicator indicator, CacheUpdateRunner updateRunner) { - do { - int count = 0; - try { - indicator.setIndeterminate(true); - indicator.setText(IdeBundle.message("progress.indexing.scanning")); - count = updateRunner.queryNeededFiles(indicator); + while (updateRunner != null) { + indicator.setIndeterminate(true); + indicator.setText(IdeBundle.message("progress.indexing.scanning")); + int count = updateRunner.queryNeededFiles(indicator); - myCurrentBaseTotal = count; - myTotalItems += count; + myCurrentBaseTotal = count; + myTotalItems += count; - indicator.setIndeterminate(false); - indicator.setText(IdeBundle.message("progress.indexing.updating")); - if (count > 0) { - updateRunner.processFiles(indicator, true); - } - updateRunner.updatingDone(); - } - finally { - myProcessedItems += count; - if (LOG.isDebugEnabled()) { - LOG.debug("Scheduling checkNextUpdateFromQueue; Thread: " + Thread.currentThread().getName()); - } - UIUtil.invokeLaterIfNeeded(new DumbAwareRunnable() { - public void run() { - checkNextUpdateFromQueue(); - } - }); - - // try to obtain the next action or terminate if no actions left - Ref ref = null; - do { - try { - ref = myActionQueue.poll(500, TimeUnit.MILLISECONDS); - } - catch (InterruptedException e) { - LOG.info(e); - } - updateRunner = ref != null? ref.get() : null; - if (myProject.isDisposed()) { - // just terminate the progress task - break; - } - } - while (ref == null); + indicator.setIndeterminate(false); + indicator.setText(IdeBundle.message("progress.indexing.updating")); + if (count > 0) { + updateRunner.processFiles(indicator, true); } + updateRunner.updatingDone(); + myProcessedItems += count; + + updateRunner = getNextUpdateRunner(); } - while (updateRunner != null); } - private void checkNextUpdateFromQueue() { - if (LOG.isDebugEnabled()) { - LOG.debug("Inside checkNextUpdateFromQueue, Thread: " + Thread.currentThread().getName()); + @Nullable + private CacheUpdateRunner getNextUpdateRunner() { + final BlockingQueue> actionQueue = new LinkedBlockingQueue>(); + UIUtil.invokeLaterIfNeeded(new DumbAwareRunnable() { + public void run() { + IndexUpdateRunnable nextRunnable = getNextUpdateFromQueue(); + try { + actionQueue.offer(nextRunnable == null ? NULL_ACTION : new Ref(nextRunnable.myAction)); + } + finally { + if (nextRunnable == null) { + updateFinished(); + } + } + } + }); + + // try to obtain the next action or terminate if no actions left + while (!myProject.isDisposed()) { + try { + Ref ref = actionQueue.poll(500, TimeUnit.MILLISECONDS); + if (ref != null) { + return ref.get(); + } + } + catch (InterruptedException e) { + LOG.info(e); + } } - IndexUpdateRunnable nextUpdateRunnable = null; + return null; + } + + @Nullable + private IndexUpdateRunnable getNextUpdateFromQueue() { try { - nextUpdateRunnable = myUpdatesQueue.isEmpty()? null : myUpdatesQueue.pullFirst(); - if (nextUpdateRunnable == null) { - // really terminate the task - myActionQueue.offer(NULL_ACTION); - } - else { - //run next dumb action - // run next action under already existing progress indicator - myActionQueue.offer(new Ref(nextUpdateRunnable.myAction)); - } + return myUpdatesQueue.isEmpty()? null : myUpdatesQueue.pullFirst(); } catch (Throwable e) { - myActionQueue.offer(NULL_ACTION); LOG.info(e); - } - finally { - if (nextUpdateRunnable == null) { - updateFinished(); - } + return null; } } }); From 53e279172051805bcbbc137939b1cc6cc66bd101 Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 11 Oct 2012 20:20:22 +0200 Subject: [PATCH 09/51] method ref completion: allow non static methods (IDEA-92705) --- .../scope/JavaCompletionProcessor.java | 34 +++++++++++-------- .../psi/scope/util/PsiScopesUtil.java | 2 +- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java index 2eee1b2de31a..375af91b5b90 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java @@ -199,6 +199,25 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme return true; } + final PsiElement elementParent = myElement.getParent(); + if (!(elementParent instanceof PsiMethodReferenceExpression) && checkStaticFlag(element)) return true; + + if (element instanceof PsiPackage && myScope instanceof PsiClass) { + if (!(elementParent instanceof PsiQualifiedReference && ((PsiQualifiedReference)elementParent).getQualifier() != null)) { + return true; + } + } + + if (satisfies(element, state) && isAccessible(element)) { + CompletionElement element1 = new CompletionElement((PsiNamedElement)element, state.get(PsiSubstitutor.KEY)); + if (myResultNames.add(element1.getUniqueId())) { + myResults.add(element1); + } + } + return true; + } + + private boolean checkStaticFlag(PsiElement element) { if (!(element instanceof PsiClass) && element instanceof PsiModifierListOwner) { PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)element; if (myStatic) { @@ -216,20 +235,7 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme } } } - final PsiElement elementParent = myElement.getParent(); - if (element instanceof PsiPackage && myScope instanceof PsiClass) { - if (!(elementParent instanceof PsiQualifiedReference && ((PsiQualifiedReference)elementParent).getQualifier() != null)) { - return true; - } - } - - if (satisfies(element, state) && isAccessible(element)) { - CompletionElement element1 = new CompletionElement((PsiNamedElement)element, state.get(PsiSubstitutor.KEY)); - if (myResultNames.add(element1.getUniqueId())) { - myResults.add(element1); - } - } - return true; + return false; } public boolean satisfies(@NotNull PsiElement element, @NotNull ResolveState state) { diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java b/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java index 2a1a6f65301d..c1fce0e27bc0 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java @@ -199,7 +199,7 @@ public class PsiScopesUtil { substitutor = substitutor.putAll((PsiClass)target, types); } } - else if (target instanceof PsiClass && !(ref instanceof PsiMethodReferenceExpression)) { + else if (target instanceof PsiClass) { processor.handleEvent(JavaScopeProcessorEvent.START_STATIC, null); } } From b8fb9f7f369c93c39885651c6dad3d5725e84723 Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 11 Oct 2012 20:56:02 +0200 Subject: [PATCH 10/51] method refs: do not insert ; in calls/exprs (IDEA-92713) --- .../codeInsight/completion/JavaCompletionUtil.java | 4 +++- java/java-psi-api/src/com/intellij/psi/LambdaUtil.java | 7 +++++-- .../completion/normal/MethodReferenceCallContext.java | 9 +++++++++ .../normal/MethodReferenceCallContext_after.java | 9 +++++++++ .../codeInsight/completion/Normal17CompletionTest.groovy | 1 + 5 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normal/MethodReferenceCallContext.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/MethodReferenceCallContext_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index e919ba12a4eb..4f59f860d868 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -792,7 +792,9 @@ public class JavaCompletionUtil { boolean insertAdditionalSemicolon = true; final PsiReferenceExpression referenceExpression = PsiTreeUtil.getTopmostParentOfType(context.getFile().findElementAt(context.getStartOffset()), PsiReferenceExpression.class); - if (referenceExpression != null) { + if (referenceExpression instanceof PsiMethodReferenceExpression && LambdaUtil.insertSemicolon(referenceExpression.getParent())) { + insertAdditionalSemicolon = false; + } else if (referenceExpression != null) { PsiElement parent = referenceExpression.getParent(); if (parent instanceof PsiMethodCallExpression) { parent = parent.getParent(); 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 d7543a365427..e7193fdb9354 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -566,13 +566,16 @@ public class LambdaUtil { if (lambdaExpression.getBody() instanceof PsiCodeBlock) { return true; } - final PsiElement parent = lambdaExpression.getParent(); - if (parent instanceof PsiExpressionList || parent instanceof PsiExpression) { + if (insertSemicolon(lambdaExpression.getParent())) { return false; } return true; } + public static boolean insertSemicolon(PsiElement parent) { + return parent instanceof PsiExpressionList || parent instanceof PsiExpression; + } + public static boolean isValidQualifier(PsiMethodReferenceExpression expression) { final PsiElement referenceNameElement = expression.getReferenceNameElement(); if (referenceNameElement instanceof PsiKeyword) { diff --git a/java/java-tests/testData/codeInsight/completion/normal/MethodReferenceCallContext.java b/java/java-tests/testData/codeInsight/completion/normal/MethodReferenceCallContext.java new file mode 100644 index 000000000000..a2c7cf44c34d --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/MethodReferenceCallContext.java @@ -0,0 +1,9 @@ +import java.util.*; + +class Test { + void aaa(Test p) { return 1; } + void test() { + c(Test::); + } + void c(Comparator c){} +} diff --git a/java/java-tests/testData/codeInsight/completion/normal/MethodReferenceCallContext_after.java b/java/java-tests/testData/codeInsight/completion/normal/MethodReferenceCallContext_after.java new file mode 100644 index 000000000000..bd2ff8a87ee2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/MethodReferenceCallContext_after.java @@ -0,0 +1,9 @@ +import java.util.*; + +class Test { + void aaa(Test p) { return 1; } + void test() { + c(Test::c); + } + void c(Comparator c){} +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/Normal17CompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/Normal17CompletionTest.groovy index 8f833b43222a..60b09a41d6b8 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/Normal17CompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/Normal17CompletionTest.groovy @@ -40,6 +40,7 @@ public class Normal17CompletionTest extends LightFixtureCompletionTestCase { public void testOnlyResourcesInResourceList4() { doTest() } public void testMethodReferenceNoStatic() { doTest() } + public void testMethodReferenceCallContext() { doTest() } public void testResourceParentInResourceList() { configureByFile(getTestName(false) + ".java") From 33a1ccd520e10b09b1862e82061d87567a39192a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Thu, 11 Oct 2012 20:22:21 +0200 Subject: [PATCH 11/51] @Nullable --- java/openapi/src/com/intellij/util/xml/DomJavaUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/openapi/src/com/intellij/util/xml/DomJavaUtil.java b/java/openapi/src/com/intellij/util/xml/DomJavaUtil.java index 200d963a5f6a..bb5d7344b73c 100644 --- a/java/openapi/src/com/intellij/util/xml/DomJavaUtil.java +++ b/java/openapi/src/com/intellij/util/xml/DomJavaUtil.java @@ -70,7 +70,7 @@ public class DomJavaUtil { } @Nullable - public static PsiClass findClass(String name, @NotNull DomElement element) { + public static PsiClass findClass(@Nullable String name, @NotNull DomElement element) { XmlElement xmlElement = element.getXmlElement(); if (xmlElement != null) { return findClass(name, xmlElement.getContainingFile(), element.getModule(), element.getResolveScope()); From 5138e414ca098240e5aa15c67ed8a1a4bd424283 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 11 Oct 2012 21:49:52 +0200 Subject: [PATCH 12/51] print compile server log in failing JpsModeTest --- .../plugins/groovy/compiler/GroovyCompilerTest.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy index 651130b345c7..639497debea8 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy @@ -207,7 +207,7 @@ public abstract class GroovyCompilerTest extends GroovyCompilerTestCase { } @Override - void runBare() { + void runTest() { def ideaLog = new File(TestLoggerFactory.testLogDir, "idea.log") def makeLog = new File(PathManager.systemPath, "compile-server/server.log") if (ideaLog.exists()) { @@ -218,7 +218,7 @@ public abstract class GroovyCompilerTest extends GroovyCompilerTestCase { } try { - super.runBare() + super.runTest() } catch (Throwable e) { if (ideaLog.exists()) { From dd33e8bbf805aae34a933975e3f1743e53b850dc Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 11 Oct 2012 22:36:40 +0200 Subject: [PATCH 13/51] log groovy-compiled files --- .../org/jetbrains/jps/incremental/groovy/GroovyBuilder.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java index 3c75cda92260..1162c7f33039 100644 --- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java +++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java @@ -73,6 +73,8 @@ public class GroovyBuilder extends ModuleLevelBuilder { if (toCompile.isEmpty()) { return ExitCode.NOTHING_DONE; } + LOG.info("forStubs=" + myForStubs); + LOG.info("toCompile: " + toCompile); Map finalOutputs = getCanonicalModuleOutputs(context, chunk); if (finalOutputs == null) { @@ -147,6 +149,7 @@ public class GroovyBuilder extends ModuleLevelBuilder { List compiled = new ArrayList(); for (GroovycOSProcessHandler.OutputItem item : handler.getSuccessfullyCompiled()) { + LOG.info("compiled=" + item); compiled.add(ensureCorrectOutput(context, chunk, item, generationOutputs, compilerOutput)); } From 31c08fab05706fb76791e4e9b37304e53b91fd1e Mon Sep 17 00:00:00 2001 From: Evgeny Zakrevsky Date: Fri, 12 Oct 2012 07:12:57 +0400 Subject: [PATCH 14/51] IDEA-68253 Issue trackers integration. Completion in TextFields. --- .../ui/TextFieldWithAutoCompletion.java | 11 ++-- .../src/com/intellij/ui/EditorTextField.java | 2 +- .../AndroidCreateLayoutFileAction.java | 2 +- .../actions/CreateResourceFileDialog.java | 2 +- .../android/logcat/EditLogFilterDialog.java | 4 +- .../tasks/config/BaseRepositoryEditor.java | 18 ++++-- .../tasks/actions/OpenTaskDialog.java | 2 +- .../tasks/generic/GenericWebRepository.java | 12 ++-- .../generic/GenericWebRepositoryEditor.java | 60 ++++++++++++++----- .../javaee/HtmlLanguageLevelForm.java | 2 +- 10 files changed, 78 insertions(+), 37 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java index 046b23c5253f..f17beff0cb43 100644 --- a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java +++ b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java @@ -52,13 +52,13 @@ public class TextFieldWithAutoCompletion extends LanguageTextField { public TextFieldWithAutoCompletion() { // For UI designer - this(null, null, false); + this(null, null, false, null); } public TextFieldWithAutoCompletion(final Project project, @Nullable final TextFieldWithAutoCompletionListProvider provider, - final boolean showAutocompletionIsAvailableHint) { - super(PlainTextLanguage.INSTANCE, project, ""); + final boolean showAutocompletionIsAvailableHint, @Nullable final String text) { + super(PlainTextLanguage.INSTANCE, project, text == null ? "" : text); myShowAutocompletionIsAvailableHint = showAutocompletionIsAvailableHint; @@ -70,8 +70,9 @@ public class TextFieldWithAutoCompletion extends LanguageTextField { public static TextFieldWithAutoCompletion create(final Project project, @NotNull final Collection items, @Nullable final Icon icon, - final boolean showAutocompletionIsAvailableHint) { - return new TextFieldWithAutoCompletion(project, new StringsCompletionProvider(items, icon), showAutocompletionIsAvailableHint); + final boolean showAutocompletionIsAvailableHint, @Nullable final String text) { + return new TextFieldWithAutoCompletion(project, new StringsCompletionProvider(items, icon), showAutocompletionIsAvailableHint, + text); } @Override diff --git a/platform/platform-impl/src/com/intellij/ui/EditorTextField.java b/platform/platform-impl/src/com/intellij/ui/EditorTextField.java index 1346c52c59e0..6bf4fb24d57e 100644 --- a/platform/platform-impl/src/com/intellij/ui/EditorTextField.java +++ b/platform/platform-impl/src/com/intellij/ui/EditorTextField.java @@ -246,7 +246,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, } } - public void setText(final String text) { + public void setText(@NotNull final String text) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { diff --git a/plugins/android/src/org/jetbrains/android/actions/AndroidCreateLayoutFileAction.java b/plugins/android/src/org/jetbrains/android/actions/AndroidCreateLayoutFileAction.java index 4415949d71fc..7d7bc1bf4e52 100644 --- a/plugins/android/src/org/jetbrains/android/actions/AndroidCreateLayoutFileAction.java +++ b/plugins/android/src/org/jetbrains/android/actions/AndroidCreateLayoutFileAction.java @@ -150,7 +150,7 @@ public class AndroidCreateLayoutFileAction extends CreateTypedResourceFileAction setTitle(AndroidBundle.message("new.typed.resource.dialog.title", "Layout")); final List tagNames = getSortedAllowedTagNames(facet); myRootElementField = new TextFieldWithAutoCompletion( - facet.getModule().getProject(), new TextFieldWithAutoCompletion.StringsCompletionProvider(tagNames, null), true); + facet.getModule().getProject(), new TextFieldWithAutoCompletion.StringsCompletionProvider(tagNames, null), true, null); myRootElementField.setText(myDefaultRootTag); myRootElementFieldWrapper.add(myRootElementField, BorderLayout.CENTER); myRootElementLabel.setLabelFor(myRootElementField); diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileDialog.java b/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileDialog.java index fd138795890c..60187f09ce26 100644 --- a/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileDialog.java +++ b/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileDialog.java @@ -213,7 +213,7 @@ public class CreateResourceFileDialog extends DialogWrapper { if (action != null) { final List allowedTagNames = action.getSortedAllowedTagNames(myFacet); myRootElementField = new TextFieldWithAutoCompletion( - myFacet.getModule().getProject(), new TextFieldWithAutoCompletion.StringsCompletionProvider(allowedTagNames, null), true); + myFacet.getModule().getProject(), new TextFieldWithAutoCompletion.StringsCompletionProvider(allowedTagNames, null), true, null); myRootElementField.setEnabled(allowedTagNames.size() > 1); myRootElementField.setText(!action.isChooseTagName() && myPredefinedResourceType != ResourceType.LAYOUT ? action.getDefaultRootTag() diff --git a/plugins/android/src/org/jetbrains/android/logcat/EditLogFilterDialog.java b/plugins/android/src/org/jetbrains/android/logcat/EditLogFilterDialog.java index 98df700dd881..438adb8adc62 100644 --- a/plugins/android/src/org/jetbrains/android/logcat/EditLogFilterDialog.java +++ b/plugins/android/src/org/jetbrains/android/logcat/EditLogFilterDialog.java @@ -77,7 +77,7 @@ class EditLogFilterDialog extends DialogWrapper { setItems(Arrays.asList(myUsedTags)); return super.getItems(prefix, cached, parameters); } - }, true); + }, true, null); myTagFieldWrapper.add(myTagField); myLogTagLabel.setLabelFor(myTagField); @@ -97,7 +97,7 @@ class EditLogFilterDialog extends DialogWrapper { final int pid2 = Integer.parseInt(item2); return Comparing.compare(pid1, pid2); } - }, true); + }, true, null); myPidFieldWrapper.add(myPidField); myLogLevelCombo.setModel(new EnumComboBoxModel(Log.LogLevel.class)); diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java index e68deba29fb8..dafe9ddde42c 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java @@ -67,6 +67,7 @@ public class BaseRepositoryEditor extends TaskReposito protected JBCheckBox myLoginAnonymouslyJBCheckBox; private boolean myApplying; + protected Project myProject; protected final T myRepository; private final Consumer myChangeListener; private final Document myDocument; @@ -74,6 +75,7 @@ public class BaseRepositoryEditor extends TaskReposito private JComponent myAnchor; public BaseRepositoryEditor(final Project project, final T repository, Consumer changeListener) { + myProject = project; myRepository = repository; myChangeListener = changeListener; @@ -115,12 +117,7 @@ public class BaseRepositoryEditor extends TaskReposito myComment.setText("Available placeholders: " + repository.getComment()); installListener(myAddCommitMessage); - myDocument.addDocumentListener(new com.intellij.openapi.editor.event.DocumentAdapter() { - @Override - public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) { - doApply(); - } - }); + installListener(myDocument); installListener(myURLText); installListener(myUserNameText); @@ -194,6 +191,15 @@ public class BaseRepositoryEditor extends TaskReposito }); } + protected void installListener(final Document document) { + document.addDocumentListener(new com.intellij.openapi.editor.event.DocumentAdapter() { + @Override + public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) { + doApply(); + } + }); + } + protected void doApply() { if (!myApplying) { try { diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java index 5897a393695e..82ea168abdc0 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java @@ -88,7 +88,7 @@ public class OpenTaskDialog extends DialogWrapper { mySelectedTask = task; taskChanged(); } - }, false); + }, false, null); myEditorPanel.add(myTaskName); myTaskName.getDocument().addDocumentListener(new DocumentAdapter() { @Override diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java index 644cc8b34cc7..0e028d5f42ab 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java @@ -10,6 +10,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xmlb.annotations.Tag; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.GetMethod; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -21,7 +22,7 @@ import java.util.regex.Pattern; * User: Evgeny.Zakrevsky * Date: 10/4/12 */ -@Tag("Web") +@Tag("Generic") public class GenericWebRepository extends BaseRepositoryImpl { private String myTasksListURL; private String myTaskPattern; @@ -131,16 +132,18 @@ public class GenericWebRepository extends BaseRepositoryImpl { return new GenericWebRepository(this); } + @NotNull public String getTasksListURL() { - return myTasksListURL; + return myTasksListURL == null ? "" : myTasksListURL; } public void setTasksListURL(final String tasksListURL) { myTasksListURL = tasksListURL; } + @NotNull public String getTaskPattern() { - return myTaskPattern; + return myTaskPattern == null ? "" : myTaskPattern; } public void setTaskPattern(final String taskPattern) { @@ -175,8 +178,9 @@ public class GenericWebRepository extends BaseRepositoryImpl { }; } + @NotNull public String getLoginURL() { - return myLoginURL; + return myLoginURL == null ? "" : myLoginURL; } public void setLoginURL(final String loginURL) { diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryEditor.java index 1623b838a1e3..66fee8398167 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryEditor.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryEditor.java @@ -1,14 +1,22 @@ package com.intellij.tasks.generic; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.Project; import com.intellij.tasks.config.BaseRepositoryEditor; +import com.intellij.ui.TextFieldWithAutoCompletion; import com.intellij.ui.components.JBLabel; import com.intellij.util.Consumer; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.FormBuilder; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import static com.intellij.tasks.generic.GenericWebRepository.*; + /** * User: Evgeny.Zakrevsky * Date: 10/4/12 @@ -16,10 +24,10 @@ import javax.swing.*; public class GenericWebRepositoryEditor extends BaseRepositoryEditor { private JBLabel myTasksListURLLabel; private JBLabel myTaskPatternLabel; - private JTextField myTasksListURLText; - private JTextField myTaskPatternText; + private TextFieldWithAutoCompletion myTasksListURLText; + private TextFieldWithAutoCompletion myTaskPatternText; private JBLabel myLoginURLLabel; - private JTextField myLoginURLText; + private TextFieldWithAutoCompletion myLoginURLText; public GenericWebRepositoryEditor(final Project project, final GenericWebRepository repository, @@ -48,26 +56,48 @@ public class GenericWebRepositoryEditor extends BaseRepositoryEditor Date: Fri, 12 Oct 2012 07:15:47 +0400 Subject: [PATCH 15/51] EA-39861 - VE: UrlClassLoader._defineClass --- .../tasks-api/src/com/intellij/tasks/TaskRepositoryType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java index c8a99d393f5f..ec8b2a0b71cd 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java @@ -51,7 +51,7 @@ public abstract class TaskRepositoryType { public abstract Class getRepositoryClass(); - public final boolean isSupported(int feature) { + public boolean isSupported(int feature) { return (getFeatures() & feature) != 0; } From 8fa36c368a727bb40039c21367e60013078f8a21 Mon Sep 17 00:00:00 2001 From: Evgeny Zakrevsky Date: Fri, 12 Oct 2012 08:52:24 +0400 Subject: [PATCH 16/51] Mantis support. Integration test. --- .../github/tasks/GitHubRepository.java | 1 + .../intellij/tasks/jira/JiraRepository.java | 1 + .../tasks/generic/GenericWebRepository.java | 16 ++---- .../lighthouse/LighthouseRepository.java | 1 + .../intellij/tasks/mantis/MantisProject.java | 12 ++++ .../tasks/mantis/MantisRepository.java | 23 ++++---- .../tasks/mantis/MantisRepositoryEditor.java | 3 +- .../pivotal/PivotalTrackerRepository.java | 2 + .../tasks/redmine/RedmineRepository.java | 1 + .../intellij/tasks/trac/TracRepository.java | 2 + .../tasks/youtrack/YouTrackRepository.java | 2 + .../com/intellij/tasks/TestRepository.java | 1 + .../integration/MantisIntegrationTest.java | 57 +++++++++++++++++++ 13 files changed, 99 insertions(+), 23 deletions(-) create mode 100644 plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/MantisIntegrationTest.java diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GitHubRepository.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GitHubRepository.java index 6feefea3c957..4095358e3a5b 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GitHubRepository.java +++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GitHubRepository.java @@ -319,6 +319,7 @@ public class GitHubRepository extends BaseRepositoryImpl { return matcher.find() ? matcher.group(1) : null; } + @Nullable @Override public Task findTask(String id) throws Exception { String path = "/repos/" + getRepoAuthor() + "/" + getRepoName() + "/issues/" + id; diff --git a/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java b/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java index 3bfb79ca56fb..01f8c0cbd6a4 100644 --- a/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java +++ b/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java @@ -173,6 +173,7 @@ public class JiraRepository extends BaseRepositoryImpl { return postMethod; } + @Nullable @Override public CancellableConnection createCancellableConnection() { PostMethod method = getLoginMethodFor4x(); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java index 0e028d5f42ab..88d99d5d757c 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java @@ -10,7 +10,6 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xmlb.annotations.Tag; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.GetMethod; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -24,9 +23,9 @@ import java.util.regex.Pattern; */ @Tag("Generic") public class GenericWebRepository extends BaseRepositoryImpl { - private String myTasksListURL; - private String myTaskPattern; - private String myLoginURL; + private String myTasksListURL = ""; + private String myTaskPattern = ""; + private String myLoginURL = ""; final static String SERVER_URL_PLACEHOLDER = "{serverUrl}"; final static String USERNAME_PLACEHOLDER = "{username}"; @@ -132,18 +131,16 @@ public class GenericWebRepository extends BaseRepositoryImpl { return new GenericWebRepository(this); } - @NotNull public String getTasksListURL() { - return myTasksListURL == null ? "" : myTasksListURL; + return myTasksListURL; } public void setTasksListURL(final String tasksListURL) { myTasksListURL = tasksListURL; } - @NotNull public String getTaskPattern() { - return myTaskPattern == null ? "" : myTaskPattern; + return myTaskPattern; } public void setTaskPattern(final String taskPattern) { @@ -178,9 +175,8 @@ public class GenericWebRepository extends BaseRepositoryImpl { }; } - @NotNull public String getLoginURL() { - return myLoginURL == null ? "" : myLoginURL; + return myLoginURL; } public void setLoginURL(final String loginURL) { diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/lighthouse/LighthouseRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/lighthouse/LighthouseRepository.java index fe8437749d59..835fc3ccf554 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/lighthouse/LighthouseRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/lighthouse/LighthouseRepository.java @@ -254,6 +254,7 @@ public class LighthouseRepository extends BaseRepositoryImpl { method.addRequestHeader("X-LighthouseToken", myAPIKey); } + @Nullable @Override public Task findTask(String id) throws Exception { final String[] split = id.split("\\-"); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisProject.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisProject.java index be024c2b8233..865f0313cd72 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisProject.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisProject.java @@ -1,5 +1,7 @@ package com.intellij.tasks.mantis; +import java.util.List; + /** * User: evgeny.zakrevsky * Date: 9/24/12 @@ -7,6 +9,8 @@ package com.intellij.tasks.mantis; public class MantisProject { public final static MantisProject ALL_PROJECTS = new MantisProject(0, "All Projects"); + private List myFilters; + private int id; private String name; @@ -35,6 +39,14 @@ public class MantisProject { this.name = name; } + public List getFilters() { + return myFilters; + } + + public void setFilters(final List filters) { + myFilters = filters; + } + @Override public boolean equals(final Object obj) { return obj != null && obj instanceof MantisProject && ((MantisProject)obj).getId() == getId(); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisRepository.java index 5169111293f9..f27af15a6ba8 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisRepository.java @@ -10,7 +10,6 @@ import com.intellij.tasks.mantis.model.*; import com.intellij.util.Function; import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.HashMap; import com.intellij.util.xmlb.annotations.Tag; import org.apache.axis.utils.StringUtils; import org.jetbrains.annotations.Nullable; @@ -21,8 +20,6 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.Set; /** * @author Dmitry Avdeev @@ -31,7 +28,7 @@ import java.util.Set; public class MantisRepository extends BaseRepositoryImpl { private final static String SOAP_API_LOCATION = "/api/soap/mantisconnect.php"; - private Map> myProject2FiltersCachedData; + private List myProjects; private MantisProject myProject; private MantisFilter myFilter; @@ -93,6 +90,7 @@ public class MantisRepository extends BaseRepositoryImpl { }); } + @Nullable @Override public Task findTask(String id) throws Exception { IssueData data = createSoap().mc_issue_get(getUsername(), getPassword(), BigInteger.valueOf(Integer.valueOf(id))); @@ -145,23 +143,23 @@ public class MantisRepository extends BaseRepositoryImpl { return task; } - public Set getProjects() throws Exception { - if (myProject2FiltersCachedData == null) { + public List getProjects() throws Exception { + if (myProjects == null) { refreshProjectAndFiltersData(); } - return myProject2FiltersCachedData.keySet(); + return myProjects; } public List getFilters(MantisProject project) throws Exception { - if (myProject2FiltersCachedData == null) { + if (myProjects == null) { refreshProjectAndFiltersData(); } - return myProject2FiltersCachedData.get(project); + return project.getFilters(); } public void refreshProjectAndFiltersData() throws Exception { final MantisConnectPortType soap = createSoap(); - myProject2FiltersCachedData = new HashMap>(); + myProjects = new ArrayList(); ProjectData[] projectDatas = soap.mc_projects_get_user_accessible(getUsername(), getPassword()); List projects = ContainerUtil.map(projectDatas, new Function() { @Override @@ -169,7 +167,7 @@ public class MantisRepository extends BaseRepositoryImpl { return new MantisProject(data.getId().intValue(), data.getName()); } }); - projects.add(MantisProject.ALL_PROJECTS); + projects.add(0, MantisProject.ALL_PROJECTS); String version = soap.mc_version(); for (MantisProject project : projects) { FilterData[] filterDatas = soap.mc_filter_get(getUsername(), getPassword(), BigInteger.valueOf(project.getId())); @@ -183,7 +181,8 @@ public class MantisRepository extends BaseRepositoryImpl { return new MantisFilter(data.getId().intValue(), data.getName()); } })); - myProject2FiltersCachedData.put(project, filters); + project.setFilters(filters); + myProjects.add(project); } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisRepositoryEditor.java index 2ef2bc809ca5..3871c1f3d7ac 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisRepositoryEditor.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/mantis/MantisRepositoryEditor.java @@ -3,6 +3,7 @@ package com.intellij.tasks.mantis; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.tasks.config.BaseRepositoryEditor; import com.intellij.ui.components.JBLabel; import com.intellij.util.Consumer; @@ -34,7 +35,7 @@ public class MantisRepositoryEditor extends BaseRepositoryEditor() { diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/MantisIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/MantisIntegrationTest.java new file mode 100644 index 000000000000..147efb34cc31 --- /dev/null +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/MantisIntegrationTest.java @@ -0,0 +1,57 @@ +package com.intellij.tasks.integration; + +import com.intellij.tasks.Task; +import com.intellij.tasks.TaskManagerTestCase; +import com.intellij.tasks.mantis.MantisFilter; +import com.intellij.tasks.mantis.MantisProject; +import com.intellij.tasks.mantis.MantisRepository; +import com.intellij.tasks.mantis.MantisRepositoryType; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.methods.GetMethod; + +import java.util.List; + +/** + * User: evgeny.zakrevsky + * Date: 10/12/12 + */ +public class MantisIntegrationTest extends TaskManagerTestCase { + public void testMantis12() throws Exception { + MantisRepository mantisRepository = new MantisRepository(new MantisRepositoryType()); + mantisRepository.setUrl("http://trackers-tests.labs.intellij.net:8142/"); + mantisRepository.setUsername("guest"); + mantisRepository.setPassword("guest"); + myManager.testConnection(mantisRepository); + + assertTrue(mantisRepository.getProjects().size() >= 2); + final MantisProject mantisProject = mantisRepository.getProjects().get(1); + assertEquals(mantisProject.getName(), "Mantis 1.2 project 1"); + mantisRepository.setProject(mantisProject); + + assertTrue(mantisProject.getFilters().size() >= 2); + final MantisFilter mantisFilter = mantisProject.getFilters().get(1); + assertEquals(mantisFilter.getName(), "Mantis 1.2 Filter 1"); + mantisRepository.setFilter(mantisFilter); + + final List issues = mantisRepository.getIssues("", 1, 0); + assertTrue(issues.size() >= 1); + final Task task = issues.get(0); + assertEquals(task.getId(), "1"); + assertEquals(task.getProject(), "Mantis 1.2 project 1"); + assertEquals(task.getNumber(), "1"); + assertEquals(task.getSummary(), "M12P1I1"); + + final Task task1 = mantisRepository.findTask("1"); + assertNotNull(task1); + assertEquals(task1.getId(), "1"); + assertEquals(task1.getProject(), "Mantis 1.2 project 1"); + assertEquals(task1.getNumber(), "1"); + assertEquals(task1.getSummary(), "M12P1I1"); + assertEquals(task1.getDescription(), "."); + + HttpClient client = new HttpClient(); + final GetMethod method = new GetMethod(task1.getIssueUrl()); + client.executeMethod(method); + assertEquals(method.getStatusCode(), 200); + } +} From c63d59257544712906f4bfc233f83c24141f20c9 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Thu, 11 Oct 2012 20:29:47 +0400 Subject: [PATCH 17/51] createSmartList uses THashMap --- .../util/src/com/intellij/util/containers/MultiMap.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/util/src/com/intellij/util/containers/MultiMap.java b/platform/util/src/com/intellij/util/containers/MultiMap.java index 5c1b9863a60e..74cb4a4b6aa5 100644 --- a/platform/util/src/com/intellij/util/containers/MultiMap.java +++ b/platform/util/src/com/intellij/util/containers/MultiMap.java @@ -17,6 +17,7 @@ package com.intellij.util.containers; import com.intellij.util.SmartList; +import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -239,6 +240,11 @@ public class MultiMap implements Serializable { protected Collection createCollection() { return new SmartList(); } + + @Override + protected Map> createMap() { + return new THashMap>(); + } }; } From 3041ebce05856a0b7efe645840fe1aa3af51daee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Fri, 12 Oct 2012 09:43:26 +0200 Subject: [PATCH 18/51] +codeinsight --- plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic index 45b82c0f7fba..ca4457786f5b 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic +++ b/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic @@ -60,6 +60,7 @@ closable closeable cmdline codebase +codeinsight codesign commandline conf From 4c3d084955d962e0b612c2b832de363517f053ef Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 10 Oct 2012 17:07:36 +0400 Subject: [PATCH 19/51] cleanup --- .../openapi/keymap/KeymapManager.java | 5 +++-- .../com/intellij/openapi/ui/ShadowAction.java | 19 ++++++++++++------- .../ui/switcher/QuickAccessSettings.java | 2 +- .../openapi/wm/impl/StripeButton.java | 15 +++++++++++---- .../com/intellij/util/ConcurrencyUtil.java | 2 +- .../util/src/com/intellij/util/Timed.java | 2 ++ 6 files changed, 30 insertions(+), 15 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/keymap/KeymapManager.java b/platform/platform-api/src/com/intellij/openapi/keymap/KeymapManager.java index 79165ee931dc..b47a197f0f02 100644 --- a/platform/platform-api/src/com/intellij/openapi/keymap/KeymapManager.java +++ b/platform/platform-api/src/com/intellij/openapi/keymap/KeymapManager.java @@ -17,6 +17,7 @@ package com.intellij.openapi.keymap; import com.intellij.openapi.application.ApplicationManager; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public abstract class KeymapManager { @@ -33,7 +34,7 @@ public abstract class KeymapManager { return ApplicationManager.getApplication().getComponent(KeymapManager.class); } - public abstract void addKeymapManagerListener(KeymapManagerListener listener); + public abstract void addKeymapManagerListener(@NotNull KeymapManagerListener listener); - public abstract void removeKeymapManagerListener(KeymapManagerListener listener); + public abstract void removeKeymapManagerListener(@NotNull KeymapManagerListener listener); } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/ShadowAction.java b/platform/platform-api/src/com/intellij/openapi/ui/ShadowAction.java index 3c15887fa8b3..ed9fc0c0c17f 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/ShadowAction.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/ShadowAction.java @@ -30,20 +30,20 @@ import javax.swing.*; public final class ShadowAction implements Disposable { - private AnAction myAction; + private final AnAction myAction; private AnAction myCopyFromAction; - private JComponent myComponent; + private final JComponent myComponent; - private KeymapManagerListener myKeymapManagerListener; + private final KeymapManagerListener myKeymapManagerListener; private ShortcutSet myShortcutSet; private String myActionId; - private Keymap.Listener myKeymapListener; + private final Keymap.Listener myKeymapListener; private Keymap myKeymap; private Presentation myPresentation; - private UiNotifyConnector myUiNotify; + private final UiNotifyConnector myUiNotify; public ShadowAction(AnAction action, AnAction copyFromAction, JComponent component, Presentation presentation) { this(action, copyFromAction, component); @@ -60,6 +60,7 @@ public final class ShadowAction implements Disposable { myAction.getTemplatePresentation().copyFrom(copyFromAction.getTemplatePresentation()); myKeymapListener = new Keymap.Listener() { + @Override public void onShortcutChanged(final String actionId) { if (myActionId == null || actionId.equals(myActionId)) { rebound(); @@ -68,16 +69,19 @@ public final class ShadowAction implements Disposable { }; myKeymapManagerListener = new KeymapManagerListener() { + @Override public void activeKeymapChanged(final Keymap keymap) { rebound(); } }; myUiNotify = new UiNotifyConnector(myComponent, new Activatable() { + @Override public void showNotify() { _connect(); } + @Override public void hideNotify() { disconnect(); } @@ -140,14 +144,15 @@ public final class ShadowAction implements Disposable { } + @Override public void dispose() { unregisterAll(); myUiNotify.dispose(); disconnect(); } - private static @Nullable - KeymapManager getKeymapManager() { + @Nullable + private static KeymapManager getKeymapManager() { if (ApplicationManager.getApplication().isDisposed()) return null; return KeymapManager.getInstance(); } diff --git a/platform/platform-api/src/com/intellij/ui/switcher/QuickAccessSettings.java b/platform/platform-api/src/com/intellij/ui/switcher/QuickAccessSettings.java index 0a1a305d4a2a..f806e29ce289 100644 --- a/platform/platform-api/src/com/intellij/ui/switcher/QuickAccessSettings.java +++ b/platform/platform-api/src/com/intellij/ui/switcher/QuickAccessSettings.java @@ -41,7 +41,7 @@ import java.util.HashSet; import java.util.Set; public class QuickAccessSettings implements ApplicationComponent, KeymapManagerListener, Disposable { - private Set myModifierVks = new HashSet(); + private final Set myModifierVks = new HashSet(); private Keymap myKeymap; @NonNls public static final String SWITCH_UP = "SwitchUp"; @NonNls public static final String SWITCH_DOWN = "SwitchDown"; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java index f99ab7513759..766b8921963d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java @@ -81,6 +81,7 @@ public final class StripeButton extends AnchoredButton implements ActionListener * excepting firing of the MNEMONIC_CHANGED_PROPERTY event. After that mnemonic * doesn't work via standard Swing rules (processing of Alt keystrokes). */ + @Override public void setMnemonic(final int mnemonic) { throw new UnsupportedOperationException("use setMnemonic2(int)"); } @@ -119,9 +120,10 @@ public final class StripeButton extends AnchoredButton implements ActionListener setRolloverEnabled(true); setOpaque(false); - enableEvents(MouseEvent.MOUSE_EVENT_MASK); + enableEvents(AWTEvent.MOUSE_EVENT_MASK); addMouseMotionListener(new MouseMotionAdapter() { + @Override public void mouseDragged(final MouseEvent e) { processDrag(e); } @@ -155,12 +157,12 @@ public final class StripeButton extends AnchoredButton implements ActionListener if (!component.isVisible()) continue; Rectangle r = component.getBounds(); if (anchor == ToolWindowAnchor.LEFT || anchor == ToolWindowAnchor.RIGHT) { - if (first && (max > r.y) || (!first && max < r.y)) { + if (first && max > r.y || !first && max < r.y) { max = r.y; c = component; } } else { - if (first && (max > r.x) || (!first && max < r.x)) { + if (first && max > r.x || !first && max < r.x) { max = r.x; c = component; } @@ -249,6 +251,7 @@ public final class StripeButton extends AnchoredButton implements ActionListener return root.getLayeredPane(); } + @Override protected void processMouseEvent(final MouseEvent e) { if (e.isPopupTrigger() && e.getComponent().isShowing()) { super.processMouseEvent(e); @@ -276,6 +279,7 @@ public final class StripeButton extends AnchoredButton implements ActionListener super.processMouseEvent(e); } + @Override public void actionPerformed(final ActionEvent e) { if (myPressedWhenSelected) { myDecorator.fireHidden(); @@ -301,6 +305,7 @@ public final class StripeButton extends AnchoredButton implements ActionListener popupMenu.getComponent().show(component, x, y); } + @Override public void updateUI() { setUI(StripeButtonUI.createUI(this)); Font font = UIUtil.getLabelFont(UIUtil.FontSize.SMALL); @@ -322,7 +327,7 @@ public final class StripeButton extends AnchoredButton implements ActionListener if (UISettings.getInstance().SHOW_TOOL_WINDOW_NUMBERS) { final int mnemonic = ActivateToolWindowAction.getMnemonicForToolWindow(toolWindowId); if (mnemonic != -1) { - text = ((char)mnemonic) + ": " + text; + text = (char)mnemonic + ": " + text; setMnemonic2(mnemonic); } else { @@ -345,12 +350,14 @@ public final class StripeButton extends AnchoredButton implements ActionListener } private final class MyPopupHandler extends PopupHandler { + @Override public void invokePopup(final Component component, final int x, final int y) { showPopup(component, x, y); } } private final class MyPropertyChangeListener implements PropertyChangeListener { + @Override public void propertyChange(final PropertyChangeEvent e) { final String name = e.getPropertyName(); if (ToolWindowEx.PROP_AVAILABLE.equals(name)) { diff --git a/platform/util/src/com/intellij/util/ConcurrencyUtil.java b/platform/util/src/com/intellij/util/ConcurrencyUtil.java index aa06a44156e6..1c1320cbaa0c 100644 --- a/platform/util/src/com/intellij/util/ConcurrencyUtil.java +++ b/platform/util/src/com/intellij/util/ConcurrencyUtil.java @@ -112,7 +112,7 @@ public class ConcurrencyUtil { } @NotNull - public static ScheduledThreadPoolExecutor newSingleScheduledThreadExecutor(@NotNull final String threadFactoryName, final int threadPriority) { + public static ScheduledThreadPoolExecutor newSingleScheduledThreadExecutor(@NonNls @NotNull final String threadFactoryName, final int threadPriority) { ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, new ThreadFactory() { public Thread newThread(final Runnable r) { final Thread thread = new Thread(r, threadFactoryName); diff --git a/platform/util/src/com/intellij/util/Timed.java b/platform/util/src/com/intellij/util/Timed.java index 197c216101b2..9d37d0a7560a 100644 --- a/platform/util/src/com/intellij/util/Timed.java +++ b/platform/util/src/com/intellij/util/Timed.java @@ -46,6 +46,7 @@ abstract class Timed implements Disposable { } } + @Override public synchronized void dispose() { final Object t = myT; myT = null; @@ -77,6 +78,7 @@ abstract class Timed implements Disposable { static { ScheduledExecutorService service = ConcurrencyUtil.newSingleScheduledThreadExecutor("timed reference disposer", Thread.MIN_PRIORITY + 1); service.scheduleWithFixedDelay(new Runnable() { + @Override public void run() { try { disposeTimed(); From e28b6c202eec9eda8c8b5997ee5e59c851ac84ae Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 10 Oct 2012 19:45:15 +0400 Subject: [PATCH 20/51] cleanup --- .../com/intellij/compiler/impl/javaCompiler/FileObject.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/FileObject.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/FileObject.java index e9483bcaa98d..4ce53a50ec1f 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/FileObject.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/FileObject.java @@ -16,6 +16,7 @@ package com.intellij.compiler.impl.javaCompiler; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import java.io.File; @@ -26,7 +27,7 @@ import java.io.IOException; * @author cdr */ public class FileObject { - private static final byte[] NOT_LOADED = new byte[0]; + private static final byte[] NOT_LOADED = ArrayUtil.EMPTY_BYTE_ARRAY; private final File myFile; private final byte[] myContent; From 8a3e220697a8a55e6dc6011e94d4d9ddc79589f1 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 10 Oct 2012 19:49:39 +0400 Subject: [PATCH 21/51] notnull --- .../psi/codeStyle/MinusculeMatcher.java | 34 +++++++++---------- .../src/com/intellij/util/text/Matcher.java | 3 +- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java b/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java index 1e337c32cd05..13702013cb01 100644 --- a/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java +++ b/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java @@ -21,13 +21,12 @@ import com.intellij.util.containers.FList; import com.intellij.util.text.CharArrayCharSequence; import com.intellij.util.text.CharArrayUtil; import com.intellij.util.text.Matcher; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Iterator; -import static com.intellij.psi.codeStyle.NameUtil.MatchingCaseSensitivity.*; - /** * @author peter */ @@ -52,7 +51,7 @@ public class MinusculeMatcher implements Matcher { myHasHumps = false; } - private static FList prependRange(FList ranges, int from, int length) { + private static FList prependRange(@NotNull FList ranges, int from, int length) { TextRange head = ranges.getHead(); if (head != null && head.getStartOffset() == from + length) { return ranges.getTail().prepend(new TextRange(from, head.getEndOffset())); @@ -60,7 +59,7 @@ public class MinusculeMatcher implements Matcher { return ranges.prepend(TextRange.from(from, length)); } - public int matchingDegree(String name) { + public int matchingDegree(@NotNull String name) { Iterable iterable = matchingFragments(name); if (iterable == null) return Integer.MIN_VALUE; @@ -110,7 +109,7 @@ public class MinusculeMatcher implements Matcher { return -fragmentCount + matchingCase * 20 + commonStart * 30 - startIndex + (prefixMatching ? 2 : middleWordStart ? 1 : 0) * 1000 - integral; } - public boolean isStartMatch(String name) { + public boolean isStartMatch(@NotNull String name) { Iterable fragments = matchingFragments(name); if (fragments != null) { Iterator iterator = fragments.iterator(); @@ -121,7 +120,7 @@ public class MinusculeMatcher implements Matcher { return false; } - private static boolean isStartMatch(String name, int startIndex) { + private static boolean isStartMatch(@NotNull String name, int startIndex) { for (int i = 0; i < startIndex; i++) { if (!NameUtil.isWordSeparator(name.charAt(i))) { return false; @@ -131,17 +130,17 @@ public class MinusculeMatcher implements Matcher { } @Override - public boolean matches(String name) { + public boolean matches(@NotNull String name) { return matchingFragments(name) != null; } @Nullable - public Iterable matchingFragments(String name) { + public Iterable matchingFragments(@NotNull String name) { return matchWildcards(name, 0, 0); } @Nullable - private FList matchWildcards(String name, int patternIndex, int nameIndex) { + private FList matchWildcards(@NotNull String name, int patternIndex, int nameIndex) { if (nameIndex < 0) { return null; } @@ -172,7 +171,7 @@ public class MinusculeMatcher implements Matcher { } @Nullable - private FList matchSkippingWords(String name, int patternIndex, int nameIndex, boolean allowSpecialChars) { + private FList matchSkippingWords(@NotNull String name, int patternIndex, int nameIndex, boolean allowSpecialChars) { boolean star = isPatternChar(patternIndex - 1, '*'); char p = myPattern[patternIndex]; while (true) { @@ -191,7 +190,7 @@ public class MinusculeMatcher implements Matcher { } @Nullable - private FList matchFragment(String name, int patternIndex, int nameIndex) { + private FList matchFragment(@NotNull String name, int patternIndex, int nameIndex) { if (!isFirstCharMatching(name, nameIndex, myPattern[patternIndex])) { return null; } @@ -200,7 +199,7 @@ public class MinusculeMatcher implements Matcher { int i = 1; while (nameIndex + i < name.length() && patternIndex + i < myPattern.length && - StringUtil.charsEqual(myPattern[patternIndex + i], name.charAt(nameIndex + i), myOptions != ALL)) { + StringUtil.charsEqual(myPattern[patternIndex + i], name.charAt(nameIndex + i), myOptions != NameUtil.MatchingCaseSensitivity.ALL)) { if (Character.isUpperCase(myPattern[patternIndex + i])) { if (i < minFragment) { return null; @@ -231,20 +230,20 @@ public class MinusculeMatcher implements Matcher { return null; } - private boolean isFirstCharMatching(String name, int nameIndex, char p) { + private boolean isFirstCharMatching(@NotNull String name, int nameIndex, char p) { return nameIndex < name.length() && StringUtil.charsEqual(p, name.charAt(nameIndex), - myOptions == FIRST_LETTER && nameIndex > 0 || myOptions == NONE); + myOptions == NameUtil.MatchingCaseSensitivity.FIRST_LETTER && nameIndex > 0 || + myOptions == NameUtil.MatchingCaseSensitivity.NONE); } private boolean isWildcard(int patternIndex) { return isPatternChar(patternIndex, ' ') || isPatternChar(patternIndex, '*'); } private boolean isPatternChar(int patternIndex, char c) { - if (patternIndex < 0 || patternIndex >= myPattern.length) return false; - return myPattern[patternIndex] == c; + return patternIndex >= 0 && patternIndex < myPattern.length && myPattern[patternIndex] == c; } - private int indexOfWordStart(String name, int patternIndex, int startFrom) { + private int indexOfWordStart(@NotNull String name, int patternIndex, int startFrom) { char p = myPattern[patternIndex]; if (p == '.' || NameUtil.isWordSeparator(p)) { return StringUtil.indexOfIgnoreCase(name, p, startFrom + 1); @@ -265,6 +264,7 @@ public class MinusculeMatcher implements Matcher { } } + @NonNls @Override public String toString() { return "MinusculeMatcher{" + diff --git a/platform/util/src/com/intellij/util/text/Matcher.java b/platform/util/src/com/intellij/util/text/Matcher.java index f501d1269798..229a9ecee4ae 100644 --- a/platform/util/src/com/intellij/util/text/Matcher.java +++ b/platform/util/src/com/intellij/util/text/Matcher.java @@ -1,11 +1,12 @@ package com.intellij.util.text; import com.intellij.psi.codeStyle.NameUtil; +import org.jetbrains.annotations.NotNull; /** * @author Konstantin Bulenkov */ @SuppressWarnings("ClassNameSameAsAncestorName") public interface Matcher extends NameUtil.Matcher { - boolean matches(String name); + boolean matches(@NotNull String name); } From eea94a4326acf8e8501bc7fe9651a16d64b2e6a7 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 11 Oct 2012 13:47:34 +0400 Subject: [PATCH 22/51] optimisation --- .../openapi/progress/impl/ProgressManagerImpl.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) 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 e83cb1623de2..2ffa08b1f294 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 @@ -219,11 +219,12 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ } public void executeProcessUnderProgress(@NotNull Runnable process, ProgressIndicator progress) throws ProcessCanceledException { - ProgressIndicator oldIndicator = myThreadIndicator.get(); + ProgressIndicator oldIndicator = null; - if (progress != null) myThreadIndicator.set(progress); + boolean set = progress != null && progress != (oldIndicator = myThreadIndicator.get()); + if (set) myThreadIndicator.set(progress); - final boolean modal = progress != null && progress.isModal(); + boolean modal = progress != null && progress.isModal(); if (modal) myCurrentModalProgressCount.incrementAndGet(); if (progress == null || progress instanceof ProgressWindow) myCurrentUnsafeProgressCount.incrementAndGet(); @@ -231,7 +232,9 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ process.run(); } finally { - myThreadIndicator.set(oldIndicator); + if (set) { + myThreadIndicator.set(oldIndicator); + } if (modal) myCurrentModalProgressCount.decrementAndGet(); if (progress == null || progress instanceof ProgressWindow) myCurrentUnsafeProgressCount.decrementAndGet(); From 638bf451078a02ea9f20989e3abad6c5321db5dd Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 11 Oct 2012 13:50:03 +0400 Subject: [PATCH 23/51] weak listeners mem leak --- .../actionSystem/impl/ActionToolbarImpl.java | 66 +++++++++++-- .../openapi/keymap/ex/KeymapManagerEx.java | 6 ++ .../keymap/ex/WeakKeymapManagerListener.java | 40 -------- .../keymap/impl/KeymapManagerImpl.java | 97 ++++++++++++++----- .../impl/WeakKeymapManagerListener.java | 53 ++++++++++ .../openapi/wm/impl/InternalDecorator.java | 35 ++++++- .../com/intellij/openapi/wm/impl/Stripe.java | 18 +++- 7 files changed, 232 insertions(+), 83 deletions(-) delete mode 100644 platform/platform-impl/src/com/intellij/openapi/keymap/ex/WeakKeymapManagerListener.java create mode 100644 platform/platform-impl/src/com/intellij/openapi/keymap/impl/WeakKeymapManagerListener.java diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java index ae00562d162d..c154b7558f04 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java @@ -31,7 +31,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.KeymapManagerListener; import com.intellij.openapi.keymap.ex.KeymapManagerEx; -import com.intellij.openapi.keymap.ex.WeakKeymapManagerListener; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.ui.popup.*; import com.intellij.openapi.util.ActionCallback; @@ -61,7 +60,7 @@ import java.util.List; public class ActionToolbarImpl extends JPanel implements ActionToolbar { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.actionSystem.impl.ActionToolbarImpl"); - private static List ourToolbars = new LinkedList(); + private static final List ourToolbars = new LinkedList(); public static void updateAllToolbarsImmediately() { for (ActionToolbarImpl toolbar : new ArrayList(ourToolbars)) { toolbar.updateActionsImmediately(); @@ -90,7 +89,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { private int myOrientation; private final ActionGroup myActionGroup; private final String myPlace; - @SuppressWarnings({"FieldCanBeLocal"}) private final MyKeymapManagerListener myKeymapManagerListener; + private final MyKeymapManagerListener myKeymapManagerListener; private List myNewVisibleActions; protected List myVisibleActions; private final PresentationFactory myPresentationFactory; @@ -125,8 +124,8 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { private boolean myReservePlaceAutoPopupIcon = true; private boolean myAddSeparatorFirst; - private WeakTimerListener myWeakTimerListener; - @SuppressWarnings({"FieldCanBeLocal"}) private ActionToolbarImpl.MyTimerListener myTimerListener; + private final WeakTimerListener myWeakTimerListener; + @SuppressWarnings({"FieldCanBeLocal"}) private final ActionToolbarImpl.MyTimerListener myTimerListener; public ActionToolbarImpl(final String place, @NotNull final ActionGroup actionGroup, final boolean horizontal, @@ -174,7 +173,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { updateActions(updateActionsNow, false, false); // - keymapManager.addKeymapManagerListener(new WeakKeymapManagerListener(keymapManager, myKeymapManagerListener)); + keymapManager.addWeakListener(myKeymapManagerListener); myTimerListener = new MyTimerListener(); myWeakTimerListener = new WeakTimerListener(actionManager, myTimerListener); // If the panel doesn't handle mouse event then it will be passed to its parent. @@ -193,7 +192,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { } private boolean doMacEnhancementsForMainToolbar() { - return (UIUtil.isUnderAquaLookAndFeel() && (ActionPlaces.MAIN_TOOLBAR.equals(myPlace) || myForceUseMacEnhancements)); + return UIUtil.isUnderAquaLookAndFeel() && (ActionPlaces.MAIN_TOOLBAR.equals(myPlace) || myForceUseMacEnhancements); } public void setForceUseMacEnhancements(boolean useMacEnhancements) { @@ -210,16 +209,20 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { ourToolbars.remove(this); myActionManager.removeTimerListener(myWeakTimerListener); myActionManager.removeTransparentTimerListener(myWeakTimerListener); + myKeymapManager.removeWeakListener(myKeymapManagerListener); } + @Override public JComponent getComponent() { return this; } + @Override public int getLayoutPolicy() { return myLayoutPolicy; } + @Override public void setLayoutPolicy(final int layoutPolicy) { if (layoutPolicy != NOWRAP_LAYOUT_POLICY && layoutPolicy != WRAP_LAYOUT_POLICY && layoutPolicy != AUTO_LAYOUT_POLICY) { throw new IllegalArgumentException("wrong layoutPolicy: " + layoutPolicy); @@ -227,6 +230,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { myLayoutPolicy = layoutPolicy; } + @Override protected void paintComponent(final Graphics g) { if (doMacEnhancementsForMainToolbar()) { final Rectangle r = getBounds(); @@ -308,6 +312,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { } final ActionButton actionButton = new ActionButton(action, presentation, place, minimumSize) { + @Override protected DataContext getDataContext() { return getToolbarDataContext(); } @@ -320,6 +325,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { return createToolbarButton(action, myMinimalMode ? myMinimalButtonLook : myDecorateButtons ? new MacToolbarDecoratorButtonLook() : myButtonLook, myPlace, myPresentationFactory.getPresentation(action), myMinimumButtonSize); } + @Override public void doLayout() { if (!isValid()) { calculateBounds(getSize(), myComponentBounds); @@ -332,6 +338,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { } } + @Override public void validate() { if (!isValid()) { calculateBounds(getSize(), myComponentBounds); @@ -359,6 +366,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { /** * @return maximum button height */ + @Override public int getMaxButtonHeight() { int height = 0; for (int i = 0; i < getComponentCount(); i++) { @@ -684,6 +692,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { } } + @Override public Dimension getPreferredSize() { final ArrayList bounds = new ArrayList(); calculateBounds(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE), bounds); @@ -716,6 +725,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { return new Dimension(dimension.width + i.left + i.right, dimension.height + i.top + i.bottom); } + @Override public Dimension getMinimumSize() { if (myLayoutPolicy == AUTO_LAYOUT_POLICY) { final Insets i = getInsets(); @@ -738,10 +748,12 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { } } + @Override public Dimension getPreferredSize() { return mySize; } + @Override protected void paintComponent(final Graphics g) { final Insets insets = getInsets(); if (UIUtil.isUnderAquaBasedLookAndFeel()) { @@ -768,6 +780,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { } private final class MyKeymapManagerListener implements KeymapManagerListener { + @Override public void activeKeymapChanged(final Keymap keymap) { final int componentCount = getComponentCount(); for (int i = 0; i < componentCount; i++) { @@ -781,10 +794,12 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { private final class MyTimerListener implements TimerListener { + @Override public ModalityState getModalityState() { return ModalityState.stateForComponent(ActionToolbarImpl.this); } + @Override public void run() { if (!isShowing()) { return; @@ -811,6 +826,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { } } + @Override public void adjustTheSameSize(final boolean value) { if (myAdjustTheSameSize == value) { return; @@ -819,6 +835,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { revalidate(); } + @Override public void setMinimumButtonSize(@NotNull final Dimension size) { myMinimumButtonSize = size; for (int i = getComponentCount() - 1; i >= 0; i--) { @@ -831,6 +848,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { revalidate(); } + @Override public void setOrientation(final int orientation) { if (SwingConstants.HORIZONTAL != orientation && SwingConstants.VERTICAL != orientation) { throw new IllegalArgumentException("wrong orientation: " + orientation); @@ -838,6 +856,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { myOrientation = orientation; } + @Override public void updateActionsImmediately() { ApplicationManager.getApplication().assertIsDispatchThread(); updateActions(true, false, false); @@ -845,6 +864,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { private void updateActions(boolean now, final boolean transparentOnly, final boolean forced) { final IdRunnable updateRunnable = new IdRunnable(this) { + @Override public void run() { if (!isVisible()) { return; @@ -902,6 +922,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { fm.doWhenFocusSettlesDown(updateRunnable); } else { UiNotifyConnector.doWhenFirstShown(this, new Runnable() { + @Override public void run() { fm.doWhenFocusSettlesDown(updateRunnable); } @@ -916,11 +937,13 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { return !myVisibleActions.isEmpty(); } + @Override public void setTargetComponent(final JComponent component) { myTargetComponent = component; if (myTargetComponent != null && myTargetComponent.isVisible()) { ApplicationManager.getApplication().invokeLater(new DumbAwareRunnable() { + @Override public void run() { updateActions(false, false, false); } @@ -928,6 +951,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { } } + @Override public DataContext getToolbarDataContext() { return getDataContext(); } @@ -936,6 +960,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { return myTargetComponent != null ? myDataManager.getDataContext(myTargetComponent) : ((DataManagerImpl)myDataManager).getDataContextTest(this); } + @Override protected void processMouseMotionEvent(final MouseEvent e) { super.processMouseMotionEvent(e); @@ -944,6 +969,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { } if (myAutoPopupRec != null && myAutoPopupRec.contains(e.getPoint())) { IdeFocusManager.getInstance(null).doWhenFocusSettlesDown(new Runnable() { + @Override public void run() { showAutoPopup(); } @@ -967,10 +993,12 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { } PopupToolbar popupToolbar = new PopupToolbar(myPlace, group, true, myDataManager, myActionManager, myKeymapManager, this) { + @Override protected void onOtherActionPerformed() { hidePopup(); } + @Override protected DataContext getDataContext() { return ActionToolbarImpl.this.getDataContext(); } @@ -994,6 +1022,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { .setCancelOnClickOutside(true) .setCancelOnOtherWindowOpen(true) .setCancelCallback(new Computable() { + @Override public Boolean compute() { final boolean toClose = myActionManager.isActionPopupStackEmpty(); if (toClose) { @@ -1003,6 +1032,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { } }) .setCancelOnMouseOutCallback(new MouseChecker() { + @Override public boolean check(final MouseEvent event) { return myAutoPopupRec != null && myActionManager.isActionPopupStackEmpty() && @@ -1011,6 +1041,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { }); builder.addListener(new JBPopupAdapter() { + @Override public void onClosed(LightweightWindowEvent event) { processClosed(); } @@ -1039,24 +1070,29 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { final Window window = SwingUtilities.getWindowAncestor(this); if (window != null) { final ComponentAdapter componentAdapter = new ComponentAdapter() { + @Override public void componentResized(final ComponentEvent e) { hidePopup(); } + @Override public void componentMoved(final ComponentEvent e) { hidePopup(); } + @Override public void componentShown(final ComponentEvent e) { hidePopup(); } + @Override public void componentHidden(final ComponentEvent e) { hidePopup(); } }; window.addComponentListener(componentAdapter); Disposer.register(popupToolbar, new Disposable() { + @Override public void dispose() { window.removeComponentListener(componentAdapter); } @@ -1091,7 +1127,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { } abstract static class PopupToolbar extends ActionToolbarImpl implements AnActionListener, Disposable { - private JComponent myParent; + private final JComponent myParent; public PopupToolbar(final String place, final ActionGroup actionGroup, @@ -1111,13 +1147,16 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { return parent != null ? parent : myParent; } + @Override public void dispose() { myActionManager.removeAnActionListener(this); } + @Override public void beforeActionPerformed(final AnAction action, final DataContext dataContext, AnActionEvent event) { } + @Override public void afterActionPerformed(final AnAction action, final DataContext dataContext, AnActionEvent event) { if (!myVisibleActions.contains(action)) { onOtherActionPerformed(); @@ -1126,19 +1165,23 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { protected abstract void onOtherActionPerformed(); + @Override public void beforeEditorTyping(final char c, final DataContext dataContext) { } } + @Override public void setReservePlaceAutoPopupIcon(final boolean reserve) { myReservePlaceAutoPopupIcon = reserve; } + @Override public void setSecondaryActionsTooltip(String secondaryActionsTooltip) { mySecondaryActions.getTemplatePresentation().setDescription(secondaryActionsTooltip); } + @Override public List getTargets(boolean onlyVisible, boolean originalProvider) { ArrayList result = new ArrayList(); @@ -1160,19 +1203,23 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { myButton = button; } + @Override public ActionCallback switchTo(boolean requestFocus) { myButton.click(); return new ActionCallback.Done(); } + @Override public boolean isVisible() { return myButton.isVisible(); } + @Override public RelativeRectangle getRectangle() { return new RelativeRectangle(myButton.getParent(), myButton.getBounds()); } + @Override public Component getComponent() { return myButton; } @@ -1183,14 +1230,17 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { } } + @Override public SwitchTarget getCurrentTarget() { return null; } + @Override public boolean isCycleRoot() { return false; } + @Override public List getActions(boolean originalProvider) { ArrayList result = new ArrayList(); diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/ex/KeymapManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/keymap/ex/KeymapManagerEx.java index 0dc7c02223a2..006bc0dcfd8e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/ex/KeymapManagerEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/ex/KeymapManagerEx.java @@ -17,8 +17,10 @@ package com.intellij.openapi.keymap.ex; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.KeymapManager; +import com.intellij.openapi.keymap.KeymapManagerListener; import com.intellij.openapi.keymap.impl.KeymapImpl; import com.intellij.openapi.options.SchemesManager; +import org.jetbrains.annotations.NotNull; import java.util.Set; @@ -40,4 +42,8 @@ public abstract class KeymapManagerEx extends KeymapManager { public abstract String getActionBinding(String actionId); public abstract SchemesManager getSchemesManager(); + + public abstract void addWeakListener(@NotNull KeymapManagerListener listener); + + public abstract void removeWeakListener(@NotNull KeymapManagerListener listenerToRemove); } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/ex/WeakKeymapManagerListener.java b/platform/platform-impl/src/com/intellij/openapi/keymap/ex/WeakKeymapManagerListener.java deleted file mode 100644 index 4ee509f2ed84..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/ex/WeakKeymapManagerListener.java +++ /dev/null @@ -1,40 +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.keymap.ex; - -import com.intellij.openapi.keymap.Keymap; -import com.intellij.openapi.keymap.KeymapManagerListener; - -import java.lang.ref.WeakReference; - -public final class WeakKeymapManagerListener implements KeymapManagerListener{ - private final KeymapManagerEx myKeymapManager; - private final WeakReference myRef; - - public WeakKeymapManagerListener(KeymapManagerEx keymapManager,KeymapManagerListener delegate){ - myKeymapManager=keymapManager; - myRef=new WeakReference(delegate); - } - - public void activeKeymapChanged(Keymap keymap){ - KeymapManagerListener delegate= myRef.get(); - if(delegate!=null){ - delegate.activeKeymapChanged(keymap); - }else{ - myKeymapManager.removeKeymapManagerListener(this); - } - } -} diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java index 1161729e9222..45840d8f5202 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java @@ -44,11 +44,10 @@ import java.util.*; roamingType = RoamingType.PER_PLATFORM, storages = { @Storage( - file = StoragePathMacros.APP_CONFIG + "/keymap.xml" + file = StoragePathMacros.APP_CONFIG + "/keymap.xml" )} ) public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStateComponent, ExportableApplicationComponent { - private static final Logger LOG = Logger.getInstance("#com.intellij.keymap.KeymapManager"); private final List myListeners = ContainerUtil.createEmptyCOWList(); @@ -65,21 +64,24 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat KeymapManagerImpl(DefaultKeymap defaultKeymap, SchemesManagerFactory factory) { mySchemesManager = factory.createSchemesManager( - "$ROOT_CONFIG$/keymaps", - new BaseSchemeProcessor(){ - public KeymapImpl readScheme(final Document schemeContent) throws InvalidDataException, IOException, JDOMException { - return readKeymap(schemeContent); - } + "$ROOT_CONFIG$/keymaps", + new BaseSchemeProcessor() { + @Override + public KeymapImpl readScheme(final Document schemeContent) throws InvalidDataException, IOException, JDOMException { + return readKeymap(schemeContent); + } - public Document writeScheme(final KeymapImpl scheme) throws WriteExternalException { - return new Document(scheme.writeExternal()); - } + @Override + public Document writeScheme(final KeymapImpl scheme) throws WriteExternalException { + return new Document(scheme.writeExternal()); + } - public boolean shouldBeSaved(final KeymapImpl scheme) { - return scheme.canModify(); - } - }, - RoamingType.PER_USER); + @Override + public boolean shouldBeSaved(final KeymapImpl scheme) { + return scheme.canModify(); + } + }, + RoamingType.PER_USER); Keymap[] keymaps = defaultKeymap.getKeymaps(); for (Keymap keymap : keymaps) { @@ -93,16 +95,19 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat ourKeymapManagerInitialized = true; } + @Override @NotNull public File[] getExportFiles() { - return new File[]{new File(PathManager.getOptionsPath()+File.separatorChar+"keymap.xml"),getKeymapDirectory(true)}; + return new File[]{new File(PathManager.getOptionsPath() + File.separatorChar + "keymap.xml"), getKeymapDirectory(true)}; } + @Override @NotNull public String getPresentableName() { return KeyMapBundle.message("key.maps.name"); } + @Override public Keymap[] getAllKeymaps() { List answer = new ArrayList(); for (Keymap keymap : mySchemesManager.getAllSchemes()) { @@ -118,32 +123,39 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat return keymaps.toArray(new Keymap[keymaps.size()]); } + @Override @Nullable public Keymap getKeymap(String name) { - return mySchemesManager.findSchemeByName( name); + return mySchemesManager.findSchemeByName(name); } + @Override public Keymap getActiveKeymap() { return mySchemesManager.getCurrentScheme(); } + @Override public void setActiveKeymap(Keymap activeKeymap) { mySchemesManager.setCurrentSchemeName(activeKeymap == null ? null : activeKeymap.getName()); fireActiveKeymapChanged(); } + @Override public void bindShortcuts(String sourceActionId, String targetActionId) { myBoundShortcuts.put(targetActionId, sourceActionId); } + @Override public Set getBoundActions() { return myBoundShortcuts.keySet(); } + @Override public String getActionBinding(String actionId) { return myBoundShortcuts.get(actionId); } + @Override public SchemesManager getSchemesManager() { return mySchemesManager; } @@ -170,6 +182,7 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat return "keymap"; } + @Override public Element getState() { Element result = new Element("component"); try { @@ -181,6 +194,7 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat return result; } + @Override public void loadState(final Element state) { try { readExternal(state); @@ -190,7 +204,7 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat } } - public void readExternal(Element element) throws InvalidDataException{ + public void readExternal(Element element) throws InvalidDataException { Element child = element.getChild(ACTIVE_KEYMAP); if (child != null) { myActiveKeymapName = child.getAttributeValue(NAME_ATTRIBUTE); @@ -204,7 +218,7 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat } } - public void writeExternal(Element element) throws WriteExternalException{ + public void writeExternal(Element element) throws WriteExternalException { if (mySchemesManager.getCurrentScheme() != null) { Element e = new Element(ACTIVE_KEYMAP); Keymap currentScheme = mySchemesManager.getCurrentScheme(); @@ -215,11 +229,11 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat } } - private void load(){ + private void load() { mySchemesManager.loadSchemes(); } - private KeymapImpl readKeymap(Document document) throws JDOMException,InvalidDataException, IOException{ + private KeymapImpl readKeymap(Document document) throws JDOMException, InvalidDataException, IOException { if (document == null) throw new InvalidDataException(); Element root = document.getRootElement(); if (root == null || !KEYMAP.equals(root.getName())) { @@ -251,20 +265,53 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat } } - public void addKeymapManagerListener(KeymapManagerListener listener) { + @Override + public void addKeymapManagerListener(@NotNull KeymapManagerListener listener) { + pollQueue(); myListeners.add(listener); } - public void removeKeymapManagerListener(KeymapManagerListener listener) { + private void pollQueue() { + // assume it is safe to remove elements during iteration, as is the case with the COWAL + for (KeymapManagerListener listener : myListeners) { + if (listener instanceof WeakKeymapManagerListener && ((WeakKeymapManagerListener)listener).isDead()) { + myListeners.remove(listener); + } + } + } + + @Override + public void removeKeymapManagerListener(@NotNull KeymapManagerListener listener) { + pollQueue(); myListeners.remove(listener); } + @Override + public void addWeakListener(@NotNull KeymapManagerListener listener) { + addKeymapManagerListener(new WeakKeymapManagerListener(this, listener)); + } + + @Override + public void removeWeakListener(@NotNull KeymapManagerListener listenerToRemove) { + // assume it is safe to remove elements during iteration, as is the case with the COWAL + for (KeymapManagerListener listener : myListeners) { + if (listener instanceof WeakKeymapManagerListener && ((WeakKeymapManagerListener)listener).isWrapped(listenerToRemove)) { + myListeners.remove(listener); + } + } + } + + @Override @NotNull public String getComponentName() { return "KeymapManager"; } - public void initComponent() {} + @Override + public void initComponent() { + } - public void disposeComponent() {} + @Override + public void disposeComponent() { + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/WeakKeymapManagerListener.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/WeakKeymapManagerListener.java new file mode 100644 index 000000000000..d3fea3bf520a --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/WeakKeymapManagerListener.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2012 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.keymap.impl; + +import com.intellij.openapi.keymap.Keymap; +import com.intellij.openapi.keymap.KeymapManagerListener; +import com.intellij.openapi.keymap.ex.KeymapManagerEx; +import org.jetbrains.annotations.NotNull; + +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; + +class WeakKeymapManagerListener implements KeymapManagerListener { + private final KeymapManagerEx myKeymapManager; + private final Reference myRef; + + WeakKeymapManagerListener(@NotNull KeymapManagerEx keymapManager, @NotNull KeymapManagerListener delegate) { + myKeymapManager = keymapManager; + myRef = new WeakReference(delegate); + } + + public boolean isDead() { + return myRef.get() == null; + } + + public boolean isWrapped(@NotNull KeymapManagerListener listener) { + return myRef.get() == listener; + } + + @Override + public void activeKeymapChanged(Keymap keymap) { + KeymapManagerListener delegate = myRef.get(); + if (delegate == null) { + myKeymapManager.removeKeymapManagerListener(this); + } + else { + delegate.activeKeymapChanged(keymap); + } + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java index 4038a7da2fdf..5c9dcb4f17c0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java @@ -22,7 +22,6 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.KeymapManagerListener; import com.intellij.openapi.keymap.ex.KeymapManagerEx; -import com.intellij.openapi.keymap.ex.WeakKeymapManagerListener; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Queryable; @@ -79,7 +78,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa * Catches all event from tool window and modifies decorator's appearance. */ private final ToolWindowHandler myToolWindowHandler; - private final WeakKeymapManagerListener myWeakKeymapManagerListener; + private final MyKeymapManagerListener myWeakKeymapManagerListener; @NonNls private static final String HIDE_ACTIVE_WINDOW_ACTION_ID = "HideActiveWindow"; @NonNls private static final String TOGGLE_PINNED_MODE_ACTION_ID = "TogglePinnedMode"; @NonNls private static final String TOGGLE_DOCK_MODE_ACTION_ID = "ToggleDockMode"; @@ -115,6 +114,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa return isFocused(); } + @Override protected void hideToolWindow() { fireHidden(); } @@ -132,8 +132,8 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa MyKeymapManagerListener keymapManagerListener = new MyKeymapManagerListener(); final KeymapManagerEx keymapManager = KeymapManagerEx.getInstanceEx(); - myWeakKeymapManagerListener = new WeakKeymapManagerListener(keymapManager, keymapManagerListener); - keymapManager.addKeymapManagerListener(myWeakKeymapManagerListener); + myWeakKeymapManagerListener = keymapManagerListener; + keymapManager.addWeakListener(keymapManagerListener); init(); @@ -204,6 +204,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa myToolWindow.getContentUI().setType(myInfo.getContentUiType()); } + @Override public void calcData(DataKey key, DataSink sink) { if (PlatformDataKeys.TOOL_WINDOW.equals(key)) { sink.put(PlatformDataKeys.TOOL_WINDOW, myToolWindow); @@ -221,7 +222,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa final void dispose() { removeAll(); myToolWindow.removePropertyChangeListener(myToolWindowHandler); - KeymapManagerEx.getInstanceEx().removeKeymapManagerListener(myWeakKeymapManagerListener); + KeymapManagerEx.getInstanceEx().removeWeakListener(myWeakKeymapManagerListener); Disposer.dispose(myHeader); myHeader = null; @@ -322,6 +323,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa // Add listeners registerKeyboardAction(new ActionListener() { + @Override public void actionPerformed(final ActionEvent e) { ToolWindowManager.getInstance(myProject).activateEditorComponent(); } @@ -340,6 +342,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa myWindow = window; } + @Override public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { g.setColor(UIUtil.getPanelBackground()); doPaintBorder(c, g, x, y, width, height); @@ -373,6 +376,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa myWindow.getAnchor() == ToolWindowAnchor.TOP; } + @Override public Insets getBorderInsets(final Component c) { UISettings settings = UISettings.getInstance(); @@ -434,6 +438,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa return false; } + @Override public boolean isBorderOpaque() { return false; } @@ -542,6 +547,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa return myHeader.getPreferredSize().height; } + @Override protected final void processComponentEvent(final ComponentEvent e) { super.processComponentEvent(e); if (ComponentEvent.COMPONENT_RESIZED == e.getID()) { @@ -581,6 +587,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa myAnchor = anchor; } + @Override public final void actionPerformed(final AnActionEvent e) { fireAnchorChanged(myAnchor); } @@ -591,10 +598,12 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa copyFrom(ActionManager.getInstance().getAction(TOGGLE_PINNED_MODE_ACTION_ID)); } + @Override public final boolean isSelected(final AnActionEvent event) { return !myInfo.isAutoHide(); } + @Override public final void setSelected(final AnActionEvent event, final boolean flag) { fireAutoHideChanged(!myInfo.isAutoHide()); } @@ -605,10 +614,12 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa copyFrom(ActionManager.getInstance().getAction(TOGGLE_DOCK_MODE_ACTION_ID)); } + @Override public final boolean isSelected(final AnActionEvent event) { return myInfo.isDocked(); } + @Override public final void setSelected(final AnActionEvent event, final boolean flag) { if (myInfo.isDocked()) { fireTypeChanged(ToolWindowType.SLIDING); @@ -624,10 +635,12 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa copyFrom(ActionManager.getInstance().getAction(TOGGLE_FLOATING_MODE_ACTION_ID)); } + @Override public final boolean isSelected(final AnActionEvent event) { return myInfo.isFloating(); } + @Override public final void setSelected(final AnActionEvent event, final boolean flag) { if (myInfo.isFloating()) { fireTypeChanged(myInfo.getInternalType()); @@ -643,10 +656,12 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa copyFrom(ActionManager.getInstance().getAction(TOGGLE_SIDE_MODE_ACTION_ID)); } + @Override public final boolean isSelected(final AnActionEvent event) { return myInfo.isSplit(); } + @Override public final void setSelected(final AnActionEvent event, final boolean flag) { fireSideStatusChanged(flag); } @@ -665,10 +680,12 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa getTemplatePresentation().setText(UIBundle.message("tool.window.hide.action.name")); } + @Override public final void actionPerformed(final AnActionEvent e) { fireHidden(); } + @Override public final void update(final AnActionEvent event) { final Presentation presentation = event.getPresentation(); presentation.setEnabled(myInfo.isVisible()); @@ -702,6 +719,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa setBorder(new DividerBorder()); } + @Override protected final void processMouseMotionEvent(final MouseEvent e) { super.processMouseMotionEvent(e); if (MouseEvent.MOUSE_DRAGGED == e.getID()) { @@ -745,6 +763,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa } } + @Override protected final void processMouseEvent(final MouseEvent e) { super.processMouseEvent(e); final ToolWindowAnchor anchor = myInfo.getAnchor(); @@ -776,6 +795,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa } private final class DividerBorder implements Border { + @Override public final void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { final ToolWindowAnchor anchor = myInfo.getAnchor(); final boolean isVertical = anchor == ToolWindowAnchor.TOP || anchor == ToolWindowAnchor.BOTTOM; @@ -809,6 +829,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa } } + @Override public final Insets getBorderInsets(final Component c) { if (c instanceof MyDivider) { return new Insets(1, 1, 1, 1); @@ -816,6 +837,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa return new Insets(0, 0, 0, 0); } + @Override public final boolean isBorderOpaque() { return true; } @@ -826,6 +848,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa * Updates tooltips. */ private final class MyKeymapManagerListener implements KeymapManagerListener { + @Override public final void activeKeymapChanged(final Keymap keymap) { if (myHeader != null) { myHeader.updateTooltips(); @@ -837,6 +860,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa * Synchronizes decorator with IdeToolWindow changes. */ private final class ToolWindowHandler implements PropertyChangeListener { + @Override public final void propertyChange(final PropertyChangeEvent e) { final String name = e.getPropertyName(); if (ToolWindowEx.PROP_TITLE.equals(name)) { @@ -848,6 +872,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa } } + @Override public void putInfo(@NotNull Map info) { info.put("toolWindowTitle", myToolWindow.getTitle()); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java index 41fa58e83e8d..b6e70fea5acc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java @@ -21,7 +21,6 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.KeymapManagerListener; import com.intellij.openapi.keymap.ex.KeymapManagerEx; -import com.intellij.openapi.keymap.ex.WeakKeymapManagerListener; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.wm.ToolWindowAnchor; @@ -44,7 +43,7 @@ import java.util.List; final class Stripe extends JPanel{ private final int myAnchor; private final ArrayList myButtons = new ArrayList(); - private final WeakKeymapManagerListener myWeakKeymapManagerListener; + private final MyKeymapManagerListener myWeakKeymapManagerListener; private final MyUISettingsListener myUISettingsListener; private Dimension myPrefSize; @@ -63,7 +62,7 @@ final class Stripe extends JPanel{ setOpaque(true); myManager = manager; myAnchor = anchor; - myWeakKeymapManagerListener=new WeakKeymapManagerListener(KeymapManagerEx.getInstanceEx(), new MyKeymapManagerListener()); + myWeakKeymapManagerListener=new MyKeymapManagerListener(); myUISettingsListener=new MyUISettingsListener(); setBorder(new AdaptiveBorder()); } @@ -130,19 +129,21 @@ final class Stripe extends JPanel{ /** * Invoked when enclosed frame is being shown. */ + @Override public void addNotify(){ super.addNotify(); updateText(); updateState(); - KeymapManagerEx.getInstanceEx().addKeymapManagerListener(myWeakKeymapManagerListener); + KeymapManagerEx.getInstanceEx().addWeakListener(myWeakKeymapManagerListener); UISettings.getInstance().addUISettingsListener(myUISettingsListener,myDisposable); } /** * Invoked when enclosed frame is being disposed. */ + @Override public void removeNotify(){ - KeymapManagerEx.getInstanceEx().removeKeymapManagerListener(myWeakKeymapManagerListener); + KeymapManagerEx.getInstanceEx().removeWeakListener(myWeakKeymapManagerListener); Disposer.dispose(myDisposable); super.removeNotify(); } @@ -166,11 +167,13 @@ final class Stripe extends JPanel{ return Collections.unmodifiableList(myButtons); } + @Override public void invalidate() { myPrefSize = null; super.invalidate(); } + @Override public void doLayout() { if (!myFinishingDrop) { myLastLayoutData = recomputeBounds(true, getSize()); @@ -432,6 +435,7 @@ final class Stripe extends JPanel{ return myAnchor == SwingConstants.TOP || myAnchor == SwingConstants.BOTTOM; } + @Override public Dimension getPreferredSize() { if (myPrefSize == null) { myPrefSize = recomputeBounds(false, null).size; @@ -473,6 +477,7 @@ final class Stripe extends JPanel{ myManager.setSideToolAndAnchor(info.getId(), ToolWindowAnchor.get(myAnchor), myLastLayoutData.dragInsertPosition, myLastLayoutData.dragToSide); myManager.invokeLater(new Runnable() { + @Override public void run() { resetDrop(); } @@ -515,12 +520,14 @@ final class Stripe extends JPanel{ } private final class MyKeymapManagerListener implements KeymapManagerListener { + @Override public void activeKeymapChanged(final Keymap keymap){ updateText(); } } private final class MyUISettingsListener implements UISettingsListener{ + @Override public void uiSettingsChanged(final UISettings source){ updateText(); updateState(); @@ -572,6 +579,7 @@ final class Stripe extends JPanel{ return myCachedBg; } + @Override protected void paintComponent(final Graphics g) { super.paintComponent(g); if (!myFinishingDrop && isDroppingButton() && myDragButton.getParent() != this) { From 8308b21d1b5dbd2e65bd84c7d20b52d223f67017 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 11 Oct 2012 14:36:31 +0400 Subject: [PATCH 24/51] performance --- .../impl/id/PlatformIdTableBuilding.java | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java b/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java index 835f9263ef0d..c691dc5abb2d 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java @@ -210,33 +210,32 @@ public abstract class PlatformIdTableBuilding { @Override @NotNull public Map map(final FileContent inputData) { - final CharSequence chars = inputData.getContentAsText(); - + String chars = inputData.getContentAsText().toString(); // matching strings is faster than HeapCharBuffer final IndexPattern[] indexPatterns = IndexPatternUtil.getIndexPatterns(); - if (indexPatterns.length > 0) { - final OccurrenceConsumer occurrenceConsumer = new OccurrenceConsumer(null, true); - for (IndexPattern indexPattern : indexPatterns) { - Pattern pattern = indexPattern.getPattern(); - if (pattern != null) { - Matcher matcher = pattern.matcher(chars); - while (matcher.find()) { - if (matcher.start() != matcher.end()) { - occurrenceConsumer.incTodoOccurrence(indexPattern); - } + if (indexPatterns.length <= 0) { + return Collections.emptyMap(); + } + OccurrenceConsumer occurrenceConsumer = new OccurrenceConsumer(null, true); + for (IndexPattern indexPattern : indexPatterns) { + Pattern pattern = indexPattern.getPattern(); + if (pattern != null) { + Matcher matcher = pattern.matcher(chars); + while (matcher.find()) { + if (matcher.start() != matcher.end()) { + occurrenceConsumer.incTodoOccurrence(indexPattern); } } } - Map map = new HashMap(); - for (IndexPattern indexPattern : indexPatterns) { - final int count = occurrenceConsumer.getOccurrenceCount(indexPattern); - if (count > 0) { - map.put(new TodoIndexEntry(indexPattern.getPatternString(), indexPattern.isCaseSensitive()), count); - } - } - return map; } - return Collections.emptyMap(); + Map map = new HashMap(); + for (IndexPattern indexPattern : indexPatterns) { + final int count = occurrenceConsumer.getOccurrenceCount(indexPattern); + if (count > 0) { + map.put(new TodoIndexEntry(indexPattern.getPatternString(), indexPattern.isCaseSensitive()), count); + } + } + return map; } } From 12f94419d9e497456df70b99903bf04ab4d1f2cc Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 11 Oct 2012 18:29:08 +0400 Subject: [PATCH 25/51] cleanup --- .../core-api/src/com/intellij/util/indexing/FileContent.java | 1 + .../src/com/intellij/util/indexing/FileContentImpl.java | 1 + 2 files changed, 2 insertions(+) diff --git a/platform/core-api/src/com/intellij/util/indexing/FileContent.java b/platform/core-api/src/com/intellij/util/indexing/FileContent.java index 68a468861858..d491870151f7 100644 --- a/platform/core-api/src/com/intellij/util/indexing/FileContent.java +++ b/platform/core-api/src/com/intellij/util/indexing/FileContent.java @@ -39,6 +39,7 @@ public interface FileContent extends UserDataHolder { byte[] getContent(); + @NotNull CharSequence getContentAsText(); Project getProject(); diff --git a/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java b/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java index 69e3885feec9..a29935a0c049 100644 --- a/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java +++ b/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java @@ -179,6 +179,7 @@ public final class FileContentImpl extends UserDataHolderBase implements FileCon return myContent; } + @NotNull @Override public CharSequence getContentAsText() { if (myFileType.isBinary()) { From 237b2fc4c26077d94117656f3b91d622bd4f5672 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 11 Oct 2012 18:31:25 +0400 Subject: [PATCH 26/51] NPE --- .../psi/impl/smartPointers/InjectedSelfElementInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java index f4a0db2a0ab2..bf6c314cc572 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java @@ -83,7 +83,7 @@ class InjectedSelfElementInfo extends SelfElementInfo { } }; - PsiDocumentManager documentManager = PsiDocumentManager.getInstance(hostFile.getProject()); + PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject()); Document document = documentManager.getDocument(hostFile); if (document != null && documentManager.isUncommited(document)) { for (DocumentWindow documentWindow : InjectedLanguageUtil.getCachedInjectedDocuments(hostFile)) { From 4edd2978d5309af5d338567bcdd079da2b171426 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 11 Oct 2012 19:28:40 +0400 Subject: [PATCH 27/51] annotations --- .../javax/swing/annotations.xml | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/java/jdkAnnotations/javax/swing/annotations.xml b/java/jdkAnnotations/javax/swing/annotations.xml index 4bfc74161eff..bdeda007bbcc 100644 --- a/java/jdkAnnotations/javax/swing/annotations.xml +++ b/java/jdkAnnotations/javax/swing/annotations.xml @@ -385,4 +385,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 074c7563865c3ed1b6b41cd64a7a4816d28e8c35 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 12 Oct 2012 10:52:07 +0200 Subject: [PATCH 28/51] method refs: shorten class names in qualifiers supported (IDEA-92724) --- .../intellij/psi/impl/source/codeStyle/ReferenceAdjuster.java | 3 ++- .../afterConstructorReceiverNonStaticInner.java | 2 +- .../afterConstructorReceiverStaticInner.java | 2 +- .../quickFix/lambda2methodReference/afterConstructorRef1.java | 2 +- .../quickFix/lambda2methodReference/afterConstructorRef2.java | 2 +- .../quickFix/lambda2methodReference/afterConstructorRef3.java | 2 +- .../quickFix/lambda2methodReference/afterConstructorRef4.java | 2 +- .../quickFix/lambda2methodReference/afterConstructorRef6.java | 2 +- 8 files changed, 9 insertions(+), 8 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ReferenceAdjuster.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ReferenceAdjuster.java index 5e079580c74a..e7c9b3e162b5 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ReferenceAdjuster.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ReferenceAdjuster.java @@ -52,7 +52,8 @@ public class ReferenceAdjuster { public TreeElement process(TreeElement element, boolean addImports, boolean uncompleteCode) { IElementType elementType = element.getElementType(); if (elementType == JavaElementType.JAVA_CODE_REFERENCE || elementType == JavaElementType.REFERENCE_EXPRESSION) { - if (elementType == JavaElementType.JAVA_CODE_REFERENCE || element.getTreeParent().getElementType() == JavaElementType.REFERENCE_EXPRESSION || uncompleteCode) { + final IElementType parentElementType = element.getTreeParent().getElementType(); + if (elementType == JavaElementType.JAVA_CODE_REFERENCE || parentElementType == JavaElementType.REFERENCE_EXPRESSION || parentElementType == JavaElementType.METHOD_REF_EXPRESSION || uncompleteCode) { final PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement)SourceTreeToPsiMap.treeElementToPsi(element); final PsiReferenceParameterList parameterList = ref.getParameterList(); if (parameterList != null) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorReceiverNonStaticInner.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorReceiverNonStaticInner.java index 04af3b2fa334..56cc62b97441 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorReceiverNonStaticInner.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorReceiverNonStaticInner.java @@ -8,6 +8,6 @@ class NonStaticInner { Inner m(NonStaticInner rec); } static { - I1 i1 = NonStaticInner.Inner::new; + I1 i1 = Inner::new; } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorReceiverStaticInner.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorReceiverStaticInner.java index b99db4b80cdd..beb01f17f3c1 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorReceiverStaticInner.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorReceiverStaticInner.java @@ -12,6 +12,6 @@ class StaticInner { static { - I1 i1 = StaticInner.Inner::new; + I1 i1 = Inner::new; } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef1.java index eb3bd0e1509a..561290224bf2 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef1.java @@ -22,7 +22,7 @@ class NonStaticInner3 { } { - I1 b1 = NonStaticInner3.Foo::new; + I1 b1 = Foo::new; I2 b2 = () -> new Foo(); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef2.java index f771f036e039..48061d008298 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef2.java @@ -23,7 +23,7 @@ class NonStaticInner3 { { I1 b1 = (i) -> new Foo(i); - I2 b2 = NonStaticInner3.Foo::new; + I2 b2 = Foo::new; } { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef3.java index b1fa835ba3b7..ae02fa4df561 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef3.java @@ -27,7 +27,7 @@ class NonStaticInner3 { } { - I3 b1 = NonStaticInner3.Foo::new; + I3 b1 = Foo::new; I4 b2 = (rec) -> rec.new Foo(); } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef4.java index 815046ba0c70..159685e69b9c 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef4.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef4.java @@ -28,6 +28,6 @@ class NonStaticInner3 { { I3 b1 = (rec, i) -> rec.new Foo(i); - I4 b2 = NonStaticInner3.Foo::new; + I4 b2 = Foo::new; } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef6.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef6.java index 1130ebf97d27..8b55c0faf470 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef6.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodReference/afterConstructorRef6.java @@ -8,6 +8,6 @@ class NonStaticInner3 { } { - I1 b2 = NonStaticInner3.Foo::new; + I1 b2 = Foo::new; } } \ No newline at end of file From bb3c1c7ea24b641d0add8cb6c722566d3b3e9d03 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 12 Oct 2012 11:00:48 +0200 Subject: [PATCH 29/51] ignore deleted files on export inspection results (IDEA-92759) --- .../codeInspection/deadCode/UnusedDeclarationInspection.java | 1 + .../intellij/codeInspection/ex/DescriptorProviderInspection.java | 1 + .../com/intellij/codeInspection/reference/RefManagerImpl.java | 1 + 3 files changed, 3 insertions(+) diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java index 64eaa91db3af..ac1728c039c7 100644 --- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java @@ -644,6 +644,7 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool { if (!getIgnoredRefElements().contains(refEntity) && filter.accepts((RefJavaElement)refEntity)) { if (refEntity instanceof RefImplicitConstructor) refEntity = ((RefImplicitConstructor)refEntity).getOwnerClass(); Element element = refEntity.getRefManager().export(refEntity, parentNode, -1); + if (element == null) return; @NonNls Element problemClassElement = new Element(InspectionsBundle.message("inspection.export.results.problem.element.tag")); if (refEntity instanceof RefElement) { diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorProviderInspection.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorProviderInspection.java index 12812e249899..a68882eb589b 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorProviderInspection.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorProviderInspection.java @@ -282,6 +282,7 @@ public abstract class DescriptorProviderInspection extends InspectionTool implem @NonNls String problemText = StringUtil.replace(StringUtil.replace(template, "#ref", psiElement != null ? ProblemDescriptionNode.extractHighlightedText(description, psiElement): "") , " #loc ", " "); Element element = refEntity.getRefManager().export(refEntity, parentNode, line); + if (element == null) return; @NonNls Element problemClassElement = new Element(InspectionsBundle.message("inspection.export.results.problem.element.tag")); problemClassElement.addContent(getDisplayName()); if (refEntity instanceof RefElement){ diff --git a/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java index ff4ec6e20672..f76678a95fc4 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java @@ -212,6 +212,7 @@ public class RefManagerImpl extends RefManager { final RefElement refElement = (RefElement)refEntity; final SmartPsiElementPointer pointer = refElement.getPointer(); PsiFile psiFile = pointer.getContainingFile(); + if (psiFile == null) return null; Element fileElement = new Element("file"); Element lineElement = new Element("line"); From 65edccd1aa0d31c9c52e71728ddaccf65939ad8b Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 12 Oct 2012 11:13:50 +0200 Subject: [PATCH 30/51] junit: add test icon for suites (IDEA-92737) --- .../impl/src/com/intellij/execution/junit/JUnitUtil.java | 9 +++++++++ .../com/intellij/execution/junit/JUnit3Framework.java | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java index 495068807e25..fb674a0dba51 100644 --- a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java +++ b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java @@ -239,6 +239,15 @@ public class JUnitUtil { return testMethod; } + @Nullable + public static PsiMethod findSuiteMethod(PsiClass clazz) { + final PsiMethod[] suiteMethods = clazz.findMethodsByName(SUITE_METHOD_NAME, false); + for (PsiMethod method : suiteMethods) { + if (isSuiteMethod(method)) return method; + } + return null; + } + public static class TestMethodFilter implements Condition { private final PsiClass myClass; diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnit3Framework.java b/plugins/junit/src/com/intellij/execution/junit/JUnit3Framework.java index 9f58dfa00bc2..2bebb05b5cff 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnit3Framework.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnit3Framework.java @@ -54,7 +54,10 @@ public class JUnit3Framework extends JavaTestFramework { } public boolean isTestClass(PsiClass clazz, boolean canBePotential) { - return JUnitUtil.isJUnit3TestClass(clazz); + if (JUnitUtil.isJUnit3TestClass(clazz)) { + return true; + } + return JUnitUtil.findSuiteMethod(clazz) != null; } @Override From 99bdd04fed32c81f630df24b13669e01ae51c9a2 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 12 Oct 2012 11:28:32 +0200 Subject: [PATCH 31/51] testng: support pattern for sets asserts "expected [] but got []" (IDEA-92770) --- .../src/com/theoryinpractice/testng/model/TestProxy.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java index 1b6ed0bcad14..7e2bf65d91d3 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java +++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java @@ -45,6 +45,8 @@ public class TestProxy extends AbstractTestProxy { Pattern.compile("(.*)expected same with:\\<(.*)\\> but was:\\<(.*)\\>.*", Pattern.DOTALL); @NonNls public static final Pattern EXPECTED_BUT_WAS_PATTERN = Pattern.compile("(.*)expected:\\<(.*)\\> but was:\\<(.*)\\>.*", Pattern.DOTALL); + @NonNls public static final Pattern EXPECTED_BUT_WAS_SET_PATTERN = + Pattern.compile("(.*)expected \\[(.*)\\] but got \\[(.*)\\].*", Pattern.DOTALL); @NonNls public static final Pattern EXPECTED_NOT_SAME_BUT_WAS_PATTERN = Pattern.compile("(.*)expected not same with:\\<(.*)\\> but was same:\\<(.*)\\>.*", Pattern.DOTALL); private final List results = new ArrayList(); @@ -344,6 +346,9 @@ public class TestProxy extends AbstractTestProxy { if (!matcher.matches()) { matcher = EXPECTED_BUT_WAS_PATTERN.matcher(s); } + if (!matcher.matches()) { + matcher = EXPECTED_BUT_WAS_SET_PATTERN.matcher(s); + } if (!matcher.matches()) { matcher = EXPECTED_NOT_SAME_BUT_WAS_PATTERN.matcher(s); } From 2f20db7f44b63bc92f56fa8e8d473c954d359273 Mon Sep 17 00:00:00 2001 From: "Kirill.Likhodedov" Date: Fri, 12 Oct 2012 13:23:45 +0400 Subject: [PATCH 32/51] GitBranchWorkerTest: use system line separators when comparing text --- .../git4idea/branch/GitBranchWorkerTest.groovy | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy index 43497f755090..daf3d5854843 100644 --- a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy +++ b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.ui.DialogWrapper import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vcs.FilePathImpl import com.intellij.openapi.vcs.changes.Change import com.intellij.openapi.vcs.changes.CurrentContentRevision @@ -349,13 +350,13 @@ class GitBranchWorkerTest { assertCurrentBranch("feature"); cd myUltimate def actual = cat(localChanges[0]) - assertEquals("Content doesn't match", -"""line with branch changes + def expectedContent = """line with branch changes common content common content common content line with master changes -""", actual) +""" + assertEquals("Content doesn't match", StringUtil.convertLineSeparators(expectedContent, File.separator), actual) } @Test @@ -365,13 +366,13 @@ line with master changes cd myUltimate def actual = cat(localChanges[0]) - assertEquals("Content doesn't match", -"""line with branch changes + def expectedContent = """line with branch changes common content common content common content line with master changes -""", actual) +""" + assertEquals("Content doesn't match", StringUtil.convertLineSeparators(expectedContent, File.separator), actual) } Collection agree_to_smart_operation(String operation, String expectedSuccessMessage) { From 9147f810fe182fdb54f3a5814b2ae6c0f263b4e5 Mon Sep 17 00:00:00 2001 From: "Kirill.Likhodedov" Date: Fri, 12 Oct 2012 14:15:41 +0400 Subject: [PATCH 33/51] GitBranchWorkerTest: use "/" to calculate relative path: all paths are taken from VirtualFile here. --- .../git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy index daf3d5854843..f6de0f451e6e 100644 --- a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy +++ b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy @@ -289,7 +289,7 @@ class GitBranchWorkerTest { assertTrue "Untracked files dialog was not shown", untrackedFiles != null assertEquals "Incorrect set of untracked files was shown in the dialog", untracked, - untrackedFiles.collect { FileUtil.getRelativePath(myCommunity.root.path, it.path, File.separatorChar) } + untrackedFiles.collect { FileUtil.getRelativePath(myCommunity.root.path, it.path, '/'.toCharacter()) } } @Test @@ -323,7 +323,7 @@ class GitBranchWorkerTest { assertEquals "Incorrect set of local changes was shown in the dialog", localChanges, changes.collect({ - FileUtil.getRelativePath(myUltimate.root.path, it.afterRevision.file.path, File.separatorChar) } + FileUtil.getRelativePath(myUltimate.root.path, it.afterRevision.file.path, '/'.toCharacter()) } ).sort() } } From 1c2c629ba85b8f4ee00cefeb4ed874be053d06ce Mon Sep 17 00:00:00 2001 From: "Kirill.Likhodedov" Date: Fri, 12 Oct 2012 14:38:24 +0400 Subject: [PATCH 34/51] GitBranchWorkerTest: better fix of line separators (occasionally mixed line separator and file separator) --- .../tests/git4idea/branch/GitBranchWorkerTest.groovy | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy index f6de0f451e6e..683623b834a0 100644 --- a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy +++ b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy @@ -27,6 +27,7 @@ import com.intellij.openapi.vcs.changes.Change import com.intellij.openapi.vcs.changes.CurrentContentRevision import com.intellij.openapi.vfs.VirtualFile import com.intellij.testFramework.vcs.MockChangeListManager +import com.intellij.util.LineSeparator import git4idea.PlatformFacade import git4idea.commands.Git import git4idea.config.GitVersion @@ -356,7 +357,7 @@ common content common content line with master changes """ - assertEquals("Content doesn't match", StringUtil.convertLineSeparators(expectedContent, File.separator), actual) + assertEquals("Content doesn't match", StringUtil.convertLineSeparators(expectedContent, LineSeparator.CRLF.separatorString), actual) } @Test @@ -372,7 +373,7 @@ common content common content line with master changes """ - assertEquals("Content doesn't match", StringUtil.convertLineSeparators(expectedContent, File.separator), actual) + assertEquals("Content doesn't match", StringUtil.convertLineSeparators(expectedContent, LineSeparator.CRLF.separatorString), actual) } Collection agree_to_smart_operation(String operation, String expectedSuccessMessage) { From b2732390ac87de052ae8f5d9357067f759065400 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 12 Oct 2012 12:42:52 +0200 Subject: [PATCH 35/51] log javac errors --- .../src/org/jetbrains/jps/incremental/java/JavaBuilder.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index e20faab40b96..61e96768fc05 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -1138,8 +1138,10 @@ public class JavaBuilder extends ModuleLevelBuilder { final JavaFileObject source = diagnostic.getSource(); final File sourceFile = source != null ? Utils.convertToFile(source.toUri()) : null; final String srcPath = sourceFile != null ? FileUtil.toSystemIndependentName(sourceFile.getPath()) : null; + String message = diagnostic.getMessage(Locale.US); + LOG.info(message); myContext.processMessage( - new CompilerMessage(BUILDER_NAME, kind, diagnostic.getMessage(Locale.US), srcPath, diagnostic.getStartPosition(), + new CompilerMessage(BUILDER_NAME, kind, message, srcPath, diagnostic.getStartPosition(), diagnostic.getEndPosition(), diagnostic.getPosition(), diagnostic.getLineNumber(), diagnostic.getColumnNumber())); } From 3065bf791ed6b707c13c9fe37ebb1be2ae332e70 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 12 Oct 2012 12:58:40 +0200 Subject: [PATCH 36/51] let everyone see the exception preventing from exiting dumb mode --- .../src/com/intellij/openapi/project/DumbServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java index ef45a30dba29..eabc98414002 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java @@ -348,7 +348,7 @@ public class DumbServiceImpl extends DumbService { runAction(proxy, myAction); } catch (RuntimeException e) { - LOG.debug(e); + LOG.error(e); throw e; } finally { @@ -373,7 +373,7 @@ public class DumbServiceImpl extends DumbService { } updateRunner.updatingDone(); myProcessedItems += count; - + updateRunner = getNextUpdateRunner(); } } From 6f35743c634b5f1e860aca6145d8cfcd807497aa Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Fri, 12 Oct 2012 15:02:02 +0400 Subject: [PATCH 37/51] configurable packaging assets from library dependencies --- .../compiler/AndroidResourcesPackagingCompiler.java | 10 ++++++---- .../android/compiler/ResourcesValidityState.java | 12 ++++++++---- .../android/facet/AndroidFacetConfiguration.java | 2 ++ .../android/facet/AndroidFacetEditorTab.form | 10 +++++++++- .../android/facet/AndroidFacetEditorTab.java | 9 ++++++++- .../android/maven/AndroidFacetImporterBase.java | 2 +- 6 files changed, 34 insertions(+), 11 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidResourcesPackagingCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidResourcesPackagingCompiler.java index e583dbaafca3..5926f0358b0b 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidResourcesPackagingCompiler.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidResourcesPackagingCompiler.java @@ -102,11 +102,13 @@ public class AndroidResourcesPackagingCompiler implements ClassPostProcessingCom if (assetsDir != null) { result.add(FileUtil.toSystemDependentName(assetsDir.getPath())); } - for (AndroidFacet depFacet : AndroidUtils.getAllAndroidDependencies(facet.getModule(), true)) { - final VirtualFile depAssetsDir = AndroidRootUtil.getAssetsDir(depFacet); + if (facet.getConfiguration().PACK_ASSETS_FROM_LIBRARIES) { + for (AndroidFacet depFacet : AndroidUtils.getAllAndroidDependencies(facet.getModule(), true)) { + final VirtualFile depAssetsDir = AndroidRootUtil.getAssetsDir(depFacet); - if (depAssetsDir != null) { - result.add(FileUtil.toSystemDependentName(depAssetsDir.getPath())); + if (depAssetsDir != null) { + result.add(FileUtil.toSystemDependentName(depAssetsDir.getPath())); + } } } } diff --git a/plugins/android/src/org/jetbrains/android/compiler/ResourcesValidityState.java b/plugins/android/src/org/jetbrains/android/compiler/ResourcesValidityState.java index b838b8ee827d..65c601323f96 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/ResourcesValidityState.java +++ b/plugins/android/src/org/jetbrains/android/compiler/ResourcesValidityState.java @@ -20,6 +20,7 @@ import com.intellij.openapi.compiler.ValidityState; import com.intellij.openapi.module.Module; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.android.facet.AndroidFacet; +import org.jetbrains.android.facet.AndroidFacetConfiguration; import org.jetbrains.android.facet.AndroidRootUtil; import org.jetbrains.android.sdk.AndroidPlatform; import org.jetbrains.android.util.AndroidUtils; @@ -46,7 +47,8 @@ public class ResourcesValidityState implements ValidityState { return; } - AndroidPlatform platform = facet.getConfiguration().getAndroidPlatform(); + final AndroidFacetConfiguration configuration = facet.getConfiguration(); + AndroidPlatform platform = configuration.getAndroidPlatform(); IAndroidTarget target = platform != null ? platform.getTarget() : null; myAndroidTargetName = target != null ? target.getFullName() : ""; @@ -75,9 +77,11 @@ public class ResourcesValidityState implements ValidityState { if (depResDir != null) { collectFiles(depResDir); } - final VirtualFile depAssetDir = AndroidRootUtil.getAssetsDir(depFacet); - if (depAssetDir != null) { - collectFiles(depAssetDir); + if (configuration.PACK_ASSETS_FROM_LIBRARIES) { + final VirtualFile depAssetDir = AndroidRootUtil.getAssetsDir(depFacet); + if (depAssetDir != null) { + collectFiles(depAssetDir); + } } } } diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java index 254d6b90beb2..0febbe48859d 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java @@ -62,6 +62,8 @@ public class AndroidFacetConfiguration implements FacetConfiguration { public String ASSETS_FOLDER_RELATIVE_PATH = "/" + SdkConstants.FD_ASSETS; public String LIBS_FOLDER_RELATIVE_PATH = "/" + SdkConstants.FD_NATIVE_LIBS; + public boolean PACK_ASSETS_FROM_LIBRARIES = false; + public List RES_OVERLAY_FOLDERS = Arrays.asList("/res-overlay"); public boolean USE_CUSTOM_APK_RESOURCE_FOLDER = false; diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.form b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.form index c576dd02c28f..b6bd1c9eb9e3 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.form +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.form @@ -123,7 +123,7 @@ - + @@ -156,6 +156,14 @@ + + + + + + + + diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java index 05db7204ce54..e464c58c4e98 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java @@ -98,6 +98,7 @@ public class AndroidFacetEditorTab extends FacetEditorTab { private JBLabel myProguardConfigFileLabel; private TextFieldWithBrowseButton myProguardConfigFileTextField; private JCheckBox myIncludeSystemProguardFileCheckBox; + private JBCheckBox myIncludeAssetsFromLibraries; public AndroidFacetEditorTab(FacetEditorContext context, AndroidFacetConfiguration androidFacetConfiguration) { final Project project = context.getProject(); @@ -315,6 +316,9 @@ public class AndroidFacetEditorTab extends FacetEditorTab { if (myConfiguration.PACK_TEST_CODE != myIncludeTestCodeAndCheckBox.isSelected()) { return true; } + if (myConfiguration.PACK_ASSETS_FROM_LIBRARIES != myIncludeAssetsFromLibraries.isSelected()) { + return true; + } if (checkRelativePath(myConfiguration.PROGUARD_CFG_PATH, myProguardConfigFileTextField.getText())) { return true; @@ -433,6 +437,8 @@ public class AndroidFacetEditorTab extends FacetEditorTab { myConfiguration.PACK_TEST_CODE = myIncludeTestCodeAndCheckBox.isSelected(); + myConfiguration.PACK_ASSETS_FROM_LIBRARIES = myIncludeAssetsFromLibraries.isSelected(); + String absProguardPath = myProguardConfigFileTextField.getText().trim(); if (absProguardPath.length() == 0) { if (myRunProguardCheckBox.isSelected()) { @@ -560,11 +566,12 @@ public class AndroidFacetEditorTab extends FacetEditorTab { myGenerateUnsignedApk.setSelected(myConfiguration.GENERATE_UNSIGNED_APK); myIncludeTestCodeAndCheckBox.setSelected(myConfiguration.PACK_TEST_CODE); + myIncludeAssetsFromLibraries.setSelected(myConfiguration.PACK_ASSETS_FROM_LIBRARIES); updateAptPanel(); final boolean lib = myConfiguration.LIBRARY_PROJECT; - myAssetsFolderField.setEnabled(!lib); + myIncludeAssetsFromLibraries.setEnabled(!lib); } @Nullable diff --git a/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java b/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java index 5e4340a2847f..2b6d23ca47e8 100644 --- a/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java +++ b/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java @@ -36,7 +36,6 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.PathUtil; @@ -120,6 +119,7 @@ public abstract class AndroidFacetImporterBase extends FacetImporter Date: Fri, 12 Oct 2012 15:03:13 +0400 Subject: [PATCH 38/51] fix order in asset packaging (app assets should override lib ones) --- .../src/org/jetbrains/android/compiler/tools/AndroidApt.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/android/common/src/org/jetbrains/android/compiler/tools/AndroidApt.java b/plugins/android/common/src/org/jetbrains/android/compiler/tools/AndroidApt.java index 37fba94dbb60..1e2287dd4ae1 100644 --- a/plugins/android/common/src/org/jetbrains/android/compiler/tools/AndroidApt.java +++ b/plugins/android/common/src/org/jetbrains/android/compiler/tools/AndroidApt.java @@ -306,7 +306,8 @@ public final class AndroidApt { } else { tempDir = FileUtil.createTempDirectory("android_combined_assets", "tmp"); - for (String assetDir : nonEmptyAssetDirs) { + for (int i = nonEmptyAssetDirs.length - 1; i >= 0; i--) { + final String assetDir = nonEmptyAssetDirs[i]; FileUtil.copyDir(new File(assetDir), tempDir, assetsFilter); } args.add("-A"); From ad4c99cc232206eb697ccb3b2321a66fff0c8312 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Fri, 12 Oct 2012 15:04:08 +0400 Subject: [PATCH 39/51] support configurable asset packaging in external build mode --- .../jps/android/AndroidPackagingBuilder.java | 33 +++++++++++-------- .../model/JpsAndroidModuleExtension.java | 2 ++ .../impl/JpsAndroidModuleExtensionImpl.java | 5 +++ .../impl/JpsAndroidModuleProperties.java | 2 ++ 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidPackagingBuilder.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidPackagingBuilder.java index fca96bda9677..fb8135121a43 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidPackagingBuilder.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidPackagingBuilder.java @@ -249,10 +249,12 @@ public class AndroidPackagingBuilder extends TargetBuilder module2state, - @NotNull AndroidFileSetStorage storage) throws IOException { + @NotNull AndroidFileSetStorage storage, + boolean withDependencies) throws IOException { final AndroidFileSetState moduleState = module2state.get(module); final AndroidFileSetState savedState = storage.getState(module.getName()); if (savedState == null || !savedState.equalsTo(moduleState)) { return false; } - for (JpsAndroidModuleExtension libExtension : AndroidJpsUtil.getAllAndroidDependencies(module, true)) { - final JpsModule libModule = libExtension.getModule(); - final AndroidFileSetState currentLibState = module2state.get(libModule); - final AndroidFileSetState savedLibState = storage.getState(libModule.getName()); + if (withDependencies) { + for (JpsAndroidModuleExtension libExtension : AndroidJpsUtil.getAllAndroidDependencies(module, true)) { + final JpsModule libModule = libExtension.getModule(); + final AndroidFileSetState currentLibState = module2state.get(libModule); + final AndroidFileSetState savedLibState = storage.getState(libModule.getName()); - if (savedLibState == null || !savedLibState.equalsTo(currentLibState)) { - return false; + if (savedLibState == null || !savedLibState.equalsTo(currentLibState)) { + return false; + } } } return true; @@ -557,11 +562,13 @@ public class AndroidPackagingBuilder extends TargetBuilder Date: Fri, 12 Oct 2012 15:07:05 +0400 Subject: [PATCH 40/51] IDEA-90594 --- .../SelectedFileEditorProvider.java | 32 +++++ .../fileEditor/impl/EditorComposite.java | 3 +- .../impl/FileEditorManagerImpl.java | 14 +- .../src/META-INF/PlatformExtensionPoints.xml | 3 + .../android-designer/src/META-INF/plugin.xml | 11 ++ .../AndroidSelectedFileEditorProvider.java | 122 ++++++++++++++++++ .../AndroidCreateLayoutFileAction.java | 62 --------- 7 files changed, 182 insertions(+), 65 deletions(-) create mode 100644 platform/platform-api/src/com/intellij/openapi/fileEditor/SelectedFileEditorProvider.java create mode 100644 plugins/android-designer/src/com/intellij/android/designer/AndroidSelectedFileEditorProvider.java diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/SelectedFileEditorProvider.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/SelectedFileEditorProvider.java new file mode 100644 index 000000000000..991d9bf26f9e --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/SelectedFileEditorProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2012 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.fileEditor; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.Nullable; + +/** + * @author Alexander Lobas + */ +public interface SelectedFileEditorProvider { + ExtensionPointName EP_SELECTED_FILE_EDITOR_PROVIDER = + new ExtensionPointName("com.intellij.selectedFileEditorProvider"); + + @Nullable + FileEditorProvider getSelectedProvider(Project project, VirtualFile file); +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java index bedb82bbca22..14dca00e485d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java @@ -30,7 +30,6 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.FocusWatcher; -import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.PrevNextActionsDescriptor; import com.intellij.ui.SideBorder; import com.intellij.ui.TabbedPaneWrapper; @@ -226,7 +225,7 @@ public abstract class EditorComposite implements Disposable { } private void fireSelectedEditorChanged(final FileEditor oldSelectedEditor, final FileEditor newSelectedEditor){ - if (!myFileEditorManager.isInsideChange() && !Comparing.equal(oldSelectedEditor, newSelectedEditor)) { + if ((!EventQueue.isDispatchThread() || !myFileEditorManager.isInsideChange()) && !Comparing.equal(oldSelectedEditor, newSelectedEditor)) { myFileEditorManager.notifyPublisher(new Runnable() { @Override public void run() { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index a187e8dda185..5f81013f3880 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java @@ -796,7 +796,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec } // Restore selected editor - final FileEditorProvider selectedProvider = editorHistoryManager.getSelectedProvider(file); + final FileEditorProvider selectedProvider = getSelectedFileEditorProvider(editorHistoryManager, file); if (selectedProvider != null) { final FileEditor[] _editors = newSelectedComposite.getEditors(); final FileEditorProvider[] _providers = newSelectedComposite.getProviders(); @@ -866,6 +866,18 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec return Pair.create(editors, providers); } + @Nullable + private FileEditorProvider getSelectedFileEditorProvider(EditorHistoryManager editorHistoryManager, VirtualFile file) { + for (SelectedFileEditorProvider selectedEditorProvider : Extensions + .getExtensions(SelectedFileEditorProvider.EP_SELECTED_FILE_EDITOR_PROVIDER)) { + FileEditorProvider provider = selectedEditorProvider.getSelectedProvider(myProject, file); + if (file != null) { + return provider; + } + } + return editorHistoryManager.getSelectedProvider(file); + } + @Override public ActionCallback notifyPublisher(final Runnable runnable) { final IdeFocusManager focusManager = IdeFocusManager.getInstance(myProject); diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml index 4e910b62ea30..476f08afae68 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml @@ -25,6 +25,9 @@ + + diff --git a/plugins/android-designer/src/META-INF/plugin.xml b/plugins/android-designer/src/META-INF/plugin.xml index a5c6f97edf36..ce299312b62e 100644 --- a/plugins/android-designer/src/META-INF/plugin.xml +++ b/plugins/android-designer/src/META-INF/plugin.xml @@ -13,6 +13,11 @@ + + + + @@ -20,6 +25,12 @@ serviceImplementation="com.intellij.android.designer.model.ViewsMetaManager"/> + + + com.intellij.android.designer.AndroidSelectedFileEditorProvider$MyEditorListener + + + diff --git a/plugins/android-designer/src/com/intellij/android/designer/AndroidSelectedFileEditorProvider.java b/plugins/android-designer/src/com/intellij/android/designer/AndroidSelectedFileEditorProvider.java new file mode 100644 index 000000000000..a7ace5a2dc31 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/AndroidSelectedFileEditorProvider.java @@ -0,0 +1,122 @@ +/* + * Copyright 2000-2012 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.android.designer; + +import com.intellij.openapi.components.*; +import com.intellij.openapi.fileEditor.*; +import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager; +import com.intellij.openapi.fileEditor.impl.EditorHistoryManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.startup.StartupManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.xmlb.XmlSerializerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Alexander Lobas + */ +public class AndroidSelectedFileEditorProvider implements SelectedFileEditorProvider { + @Nullable + @Override + public FileEditorProvider getSelectedProvider(Project project, VirtualFile openedFile) { + if (!AndroidDesignerEditorProvider.acceptLayout(project, openedFile)) { + return null; + } + + String editorTypeId = MyState.getInstance(project).editorTypeId; + if (editorTypeId != null) { + return FileEditorProviderManager.getInstance().getProvider(editorTypeId); + } + + return null; + } + + public static class MyEditorListener implements ProjectComponent { + private final Project myProject; + + public MyEditorListener(Project project) { + myProject = project; + } + + @Override + public void projectOpened() { + StartupManager.getInstance(myProject).registerPostStartupActivity(new Runnable() { + public void run() { + myProject.getMessageBus().connect(myProject) + .subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerListener() { + @Override + public void fileOpened(FileEditorManager source, VirtualFile file) { + } + + @Override + public void fileClosed(FileEditorManager source, VirtualFile file) { + } + + @Override + public void selectionChanged(FileEditorManagerEvent event) { + VirtualFile file = event.getNewFile(); + if (file != null && AndroidDesignerEditorProvider.acceptLayout(myProject, file)) { + FileEditorProvider provider = EditorHistoryManager.getInstance(myProject).getSelectedProvider(file); + if (provider != null) { + MyState.getInstance(myProject).editorTypeId = provider.getEditorTypeId(); + } + } + } + }); + } + }); + } + + @Override + public void projectClosed() { + } + + @Override + public void initComponent() { + } + + @Override + public void disposeComponent() { + } + + @NotNull + @Override + public String getComponentName() { + return "AndroidLayoutSelectedEditorListener"; + } + } + + @State(name = "AndroidLayoutSelectedEditor", storages = {@Storage(file = StoragePathMacros.WORKSPACE_FILE)}) + public static class MyState implements PersistentStateComponent { + public String editorTypeId; + + @Nullable + @Override + public MyState getState() { + return this; + } + + @Override + public void loadState(MyState state) { + XmlSerializerUtil.copyBean(state, this); + } + + public static MyState getInstance(Project project) { + return ServiceManager.getService(project, MyState.class); + } + } +} \ No newline at end of file diff --git a/plugins/android/src/org/jetbrains/android/actions/AndroidCreateLayoutFileAction.java b/plugins/android/src/org/jetbrains/android/actions/AndroidCreateLayoutFileAction.java index 7d7bc1bf4e52..40f75e1c9a23 100644 --- a/plugins/android/src/org/jetbrains/android/actions/AndroidCreateLayoutFileAction.java +++ b/plugins/android/src/org/jetbrains/android/actions/AndroidCreateLayoutFileAction.java @@ -17,37 +17,25 @@ package org.jetbrains.android.actions; import com.android.resources.ResourceFolderType; -import com.android.resources.ResourceType; import com.intellij.CommonBundle; -import com.intellij.facet.ProjectFacetManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.fileEditor.FileEditorProvider; -import com.intellij.openapi.fileEditor.impl.EditorHistoryManager; -import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.InputValidator; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; -import com.intellij.psi.xml.XmlFile; import com.intellij.ui.TextFieldWithAutoCompletion; import com.intellij.ui.components.JBLabel; -import com.intellij.util.containers.HashSet; import org.jetbrains.android.dom.layout.AndroidLayoutUtil; import org.jetbrains.android.facet.AndroidFacet; -import org.jetbrains.android.facet.AndroidRootUtil; import org.jetbrains.android.util.AndroidBundle; -import org.jetbrains.android.util.AndroidCommonUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.util.List; -import java.util.Set; /** * @author Eugene.Kudelevsky @@ -79,62 +67,12 @@ public class AndroidCreateLayoutFileAction extends CreateTypedResourceFileAction return doCreateAndNavigate(newName, directory, rootTag, false); } - @Override - protected void doNavigate(XmlFile file) { - final Project project = file.getProject(); - final String preferredEditorProviderId = computePreferredEditorForLayoutFiles(project); - super.doNavigate(file); - - if (preferredEditorProviderId != null) { - final FileEditorManager manager = FileEditorManager.getInstance(project); - if (manager instanceof FileEditorManagerImpl) { - final VirtualFile vFile = file.getVirtualFile(); - if (vFile != null) { - ((FileEditorManagerImpl)manager).setSelectedEditor(vFile, preferredEditorProviderId); - } - } - } - } - @NotNull @Override public List getAllowedTagNames(@NotNull AndroidFacet facet) { return AndroidLayoutUtil.getPossibleRoots(facet); } - @Nullable - private static String computePreferredEditorForLayoutFiles(Project project) { - final EditorHistoryManager manager = EditorHistoryManager.getInstance(project); - final Set resourceDirs = new HashSet(); - final List facets = ProjectFacetManager.getInstance(project).getFacets(AndroidFacet.ID); - - for (AndroidFacet facet : facets) { - final VirtualFile resourceDir = AndroidRootUtil.getResourceDir(facet); - if (resourceDir != null) { - resourceDirs.add(resourceDir); - } - } - - final VirtualFile[] files = manager.getFiles(); - for (int i = files.length - 1; i >= 0; i--) { - final VirtualFile file = files[i]; - final VirtualFile parent = file.getParent(); - - if (parent != null) { - final String resType = AndroidCommonUtils.getResourceTypeByDirName(parent.getName()); - - if (ResourceType.LAYOUT.getName().equals(resType) && resourceDirs.contains(parent.getParent())) { - final FileEditorProvider provider = manager.getSelectedProvider(file); - - if (provider != null) { - return provider.getEditorTypeId(); - } - } - } - } - return null; - } - public class MyDialog extends DialogWrapper { private final InputValidator myValidator; From 87e571bfd3f699279060b1d9d01de8bee6a39c88 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 12 Oct 2012 15:09:39 +0400 Subject: [PATCH 41/51] saving separate modules --- .../SaveProjectAsTemplateAction.java | 19 ++++++++++- .../SaveProjectAsTemplateDialog.form | 30 ++++++++++++----- .../SaveProjectAsTemplateDialog.java | 33 +++++++++++++++++++ 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateAction.java b/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateAction.java index ba630a86130a..f1d813c8a764 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateAction.java +++ b/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateAction.java @@ -17,6 +17,8 @@ package com.intellij.platform.templates; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.io.FileUtil; @@ -24,6 +26,7 @@ import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.io.ZipUtil; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.FileFilter; @@ -50,7 +53,8 @@ public class SaveProjectAsTemplateAction extends AnAction { try { file.getParentFile().mkdirs(); stream = new ZipOutputStream(new FileOutputStream(file)); - VirtualFile dir = project.getBaseDir(); + + VirtualFile dir = getDirectoryToSave(project, dialog.getModuleToSave()); String description = dialog.getDescription(); if (descriptionFile == null) { stream.putNextEntry(new ZipEntry(dir.getName() + "/" + ArchivedProjectTemplate.DESCRIPTION_PATH)); @@ -80,6 +84,19 @@ public class SaveProjectAsTemplateAction extends AnAction { } } + private static VirtualFile getDirectoryToSave(Project project, @Nullable String moduleName) { + if (moduleName == null) { + return project.getBaseDir(); + } + else { + Module module = ModuleManager.getInstance(project).findModuleByName(moduleName); + assert module != null : "Can't find module " + moduleName; + VirtualFile moduleFile = module.getModuleFile(); + assert moduleFile != null; + return moduleFile.getParent(); + } + } + @Override public void update(AnActionEvent e) { Project project = getEventProject(e); diff --git a/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateDialog.form b/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateDialog.form index 90ac6dd5d2c8..ebcd02909d82 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateDialog.form +++ b/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateDialog.form @@ -1,16 +1,16 @@
- + - + - + @@ -19,12 +19,12 @@ - + - + @@ -32,7 +32,7 @@ - + @@ -40,12 +40,26 @@ - - + + + + + + + + + + + + + + + + diff --git a/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateDialog.java b/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateDialog.java index 6bb5c68e5724..bd7278ef5a1d 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateDialog.java +++ b/java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateDialog.java @@ -17,19 +17,26 @@ package com.intellij.platform.templates; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.ValidationInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.CollectionComboBoxModel; import com.intellij.ui.EditorTextField; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; /** * @author Dmitry Avdeev @@ -37,13 +44,32 @@ import java.io.IOException; */ public class SaveProjectAsTemplateDialog extends DialogWrapper { + private static final String WHOLE_PROJECT = ""; private JPanel myPanel; private JTextField myName; private EditorTextField myDescription; + private JComboBox myModuleCombo; + private JLabel myModuleLabel; protected SaveProjectAsTemplateDialog(@NotNull Project project, @Nullable VirtualFile descriptionFile) { super(project); + setTitle("Save Project As Template"); + Module[] modules = ModuleManager.getInstance(project).getModules(); + if (modules.length < 2) { + myModuleLabel.setVisible(false); + myModuleCombo.setVisible(false); + } + else { + List items = new ArrayList(ContainerUtil.map(modules, new Function() { + @Override + public String fun(Module module) { + return module.getName(); + } + })); + items.add(WHOLE_PROJECT); + myModuleCombo.setModel(new CollectionComboBoxModel(items, WHOLE_PROJECT)); + } myDescription.setFileType(FileTypeManager.getInstance().getFileTypeByExtension(".html")); if (descriptionFile != null) { try { @@ -95,5 +121,12 @@ public class SaveProjectAsTemplateDialog extends DialogWrapper { return myDescription.getText(); } + @Nullable + String getModuleToSave() { + String item = (String)myModuleCombo.getSelectedItem(); + if (item == null || item.equals(WHOLE_PROJECT)) return null; + return item; + } + private final static Logger LOG = Logger.getInstance(SaveProjectAsTemplateDialog.class); } From ece982e28774b7912b6abca69306968eec610c8c Mon Sep 17 00:00:00 2001 From: Evgeny Zakrevsky Date: Fri, 12 Oct 2012 14:50:02 +0400 Subject: [PATCH 42/51] IDEA-68253 Issue trackers integration. Search query placeholder used. --- .../com/intellij/tasks/generic/GenericWebRepository.java | 9 ++++++--- .../tasks/generic/GenericWebRepositoryEditor.java | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java index 88d99d5d757c..81d45a1d2de7 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java @@ -1,6 +1,7 @@ package com.intellij.tasks.generic; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.tasks.Task; import com.intellij.tasks.TaskRepositoryType; import com.intellij.tasks.actions.TaskSearchSupport; @@ -32,6 +33,7 @@ public class GenericWebRepository extends BaseRepositoryImpl { final static String PASSWORD_PLACEHOLDER = "{password}"; final static String ID_PLACEHOLDER = "{id}"; final static String SUMMARY_PLACEHOLDER = "{summary}"; + final static String QUERY_PLACEHOLDER = "{query}"; final static String DESCRIPTION_PLACEHOLDER = "{description}"; final static String PAGE_PLACEHOLDER = "{page}"; @@ -56,7 +58,7 @@ public class GenericWebRepository extends BaseRepositoryImpl { if (!isLoginAnonymously()) login(httpClient); - final GetMethod getMethod = new GetMethod(getFullTasksUrl()); + final GetMethod getMethod = new GetMethod(getFullTasksUrl(query != null ? query : "")); httpClient.executeMethod(getMethod); if (getMethod.getStatusCode() != 200) throw new Exception("Cannot get tasks: HTTP status code " + getMethod.getStatusCode()); final String response = getMethod.getResponseBodyAsString(Integer.MAX_VALUE); @@ -104,9 +106,10 @@ public class GenericWebRepository extends BaseRepositoryImpl { return vars; } - private String getFullTasksUrl() { + private String getFullTasksUrl(final String query) { return getTasksListURL() - .replaceAll(placeholder2regexp(SERVER_URL_PLACEHOLDER), getUrl()); + .replaceAll(placeholder2regexp(SERVER_URL_PLACEHOLDER), getUrl()) + .replaceAll(StringUtil.escapePattern(QUERY_PLACEHOLDER), query); } private String getFullLoginUrl() { diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryEditor.java index 66fee8398167..6e476417564f 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryEditor.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryEditor.java @@ -83,7 +83,7 @@ public class GenericWebRepositoryEditor extends BaseRepositoryEditor Date: Fri, 12 Oct 2012 15:13:17 +0400 Subject: [PATCH 43/51] IDEA-68253 Issue trackers integration. Search query placeholder bug. --- .../src/com/intellij/tasks/generic/GenericWebRepository.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java index 81d45a1d2de7..ce3e3ae73338 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java @@ -1,7 +1,6 @@ package com.intellij.tasks.generic; import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.tasks.Task; import com.intellij.tasks.TaskRepositoryType; import com.intellij.tasks.actions.TaskSearchSupport; @@ -109,7 +108,7 @@ public class GenericWebRepository extends BaseRepositoryImpl { private String getFullTasksUrl(final String query) { return getTasksListURL() .replaceAll(placeholder2regexp(SERVER_URL_PLACEHOLDER), getUrl()) - .replaceAll(StringUtil.escapePattern(QUERY_PLACEHOLDER), query); + .replaceAll(placeholder2regexp(QUERY_PLACEHOLDER), query); } private String getFullLoginUrl() { From 547a2b1e8d6403edb104403d193558553250aa93 Mon Sep 17 00:00:00 2001 From: Evgeny Zakrevsky Date: Fri, 12 Oct 2012 15:19:11 +0400 Subject: [PATCH 44/51] library --- plugins/tasks/tasks-core/lib/wsdl4j-1.4.jar | Bin 0 -> 113174 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 plugins/tasks/tasks-core/lib/wsdl4j-1.4.jar diff --git a/plugins/tasks/tasks-core/lib/wsdl4j-1.4.jar b/plugins/tasks/tasks-core/lib/wsdl4j-1.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..49cc2c6eb83aa71935deb98bc1c0cb334af8a95a GIT binary patch literal 113174 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 z z11?Y)+Fy-_9TC_@Zch-$Z=DvlsA2?Wtb~!(G=v3kc7?I~;!r$s{WA!$W7`uS2M$8C z#oF%`R{kRh5qlHf>Ol#kbfTR|6YdtW0%3Gkgl-YjB;RRUp=py@yVn~BM!Ps zHIXjm0+6a(Eyos8{nwU1Pq(`EF<`;!4MJG=m^X0MbzaHuBJQ`Bl^Dq<+wE4~HrM^h z?2aDaeeQ;(UK*EDwLfl|BfO#jAnaGekF7epC=ujG4x5WsXHX@f;EQk?+kLbwW z+3%DDG63A+Y+Bua1!47rb&%Z;ctP85Wx@ekVL5W9iB@<>yX-)xO) zsoDWf;rPTX$4ncS?L2&lit;2zGoAcH#u&__{Dymn88)TIg~sMqNrBFSos|-{x-W=jGH&%E+Te6TD4P;GT|yH`L)-bC4so2WySV=lCU{u)b!w9lzTU3!kArB zbkSP(G_4$24P!iXMeXB0DahtcDZ0Y(KZO(JICv+ue=7~(VFj~@6H@6#_^9*qAqYP{ zOD#~G5VfuI3kmsnbFi|_2xo-PjdC;_dpE4Jt3rL6`q`R7MM+uEBpr^4DQq59WRkq`@-M%F3fIJB1Rd9Cet-ks zQX4sFx?RS5isj{bS8Nn+miFi@x!*mm)_gc$HVo$%*YidqZ_Cegp-0?s0#nudtYTXg;_^*xw1$* zd#0v(_9iDQjKp;y2u;C)sGGCval3uYSo;>iF4WD<(RP z#L9g*dqF`}r`a5F?>Pv{H3(+FsE3jKT4?LL>_R>2uefw|wiO)&wEKpC9uEa2|()THZRp|O)OKBSnW~^OnZHZtlv1iZ#^l0snni85R8#f8Pz7Cb&LYPK*olNa;JW7-? z0#Yw{skAINORz)ByB037KYFmHFz!lH;F#Dt!JQhoJhADX=Ud>CCJKv1%rk*T<{ho` zF9D94#pVFYV!<|F$Evf*N?{F7 zV#8tqGg%c!TBB5Ok@MKTvxxE7U0P{u>6{frZ|dQjq??{GJ;WNv->G~Aoa%StqNJS6mf9i3n> z!a1t$gxYt|uyMyzZ<7`q8g(_-9qkV5!$xoxFfSHe9zASv2xZUHL~6|-bXb@9Er3d@ z(-ia=4=HOb=T_#UEqT}G{l|XSvo}`ICDbF7fD*=i=3LF^(0*;7()!%b^3^{gy+GvHPuQ; zqb$^?@^-0i``N-8GhIt!+D$@FnEvp4Tk&VfKs~YVb4Q31Y_%!tMnap)jj<3+UDSb9^3o?d#4pf>aF)&un z74O%N`_(uKjzIy$-C?N6u|8!~w+pF&6>ErL0FF=5i5*y(J+sarb7cL{n5G zhXS#YjZa#QHjo?mI3yk0LGQ6osHdY44s)F)TNzJEjttFe$1Mg3S4D~YnYm7VaSZ+6 zGK#+Hp#^}qxG=E3*u(g2;GyL=Fz@((-s+0{&5G=Q{51c)Qku~A)+VsReM8dmu(S$$ zml@9zAu}_b?5nosV`rM;M1u*dB`s6Q!vHD2PR|a0gJH&}W$4MS;-(Dd#!fV)&>Fpx za@Dr0+Ow;A@#(qt#@|YNITYkmHMRSDkAL&-W%KIJf6K4!t*+y|4{LsB3(b%gq=9D0 z2m+_r=|S(|j8ZPd;Di$|KEw4SU0|cmky(oWh-}px$O@l|xNi@448Jc4cZ|4i4nGgS zuL(bo@RA<5lX(6#5GV00KA38rL8XgbHiw3w0&!=RAH5Ibm{K8{uEJXNM>4n zQ(E1xw1yERg2kAVs~C}F5axr^m!KfH&V=XqPte5rdc`(7 zPxW@geNhmtgHT)xeQTJ_{)Gwj{^bW~qh4C*yB!Z`qk#$d?t!@{FOI231h3j4=3RIA z?w~lDR$@oh3(ii3zF@DeAfp`v_<&Gkx_cy{itUzGnLhGXiN5odCMoC4AmMFD_}B0j zC$UCh5Fz|)v?tv?zS3K43*9}8P|4U-y_6zS>-YXVd-&m^4p-1 zC-+-(GHBLY1@d4KMGXVt7;E%s87sp0*KDMp88K736n*u3&msXSSjeSe05{EZatG$j zyYN8VwFX=y)`|L$^|QP5qn~+_ojvC9qC;<3^^~+F*-Sz+*Fj%V*-tJ@(utPP2{t&D zihi3HsI<7vO`8tgC=U25Ro$N1ZCG&?`?Bje-{6fp!K6$HS>lDn6F|p2#wW1Y&3=#F zG%t`Nro#EQs~C8`o;5Dx$|K;T!y%9!9p>uy7QXSzn2* zRkePcLf?t4+z`87ub{U>sn{g2BVrU<&*n8{W>aMP0J;)}G;K9yXW7QYtgIekgp4xO ztJ@S>myQ%Lv$}y(s#y46>TI)AI5Zkc0>>;q!*ysy727az$4J~@?60Dc=u_q`n>Cym&WW2?eeqXP z()yyMwm*|vQzH3ZBKt+5TEYGWG5j_5v4*JqN5?SwZMXxz%6tB%J`v{dnY(w+Y&2wB zP3p2rh_fVPvB?OnKti6)WOmK5G#2ei9ESY``@?kmB58>P8%hEl{@IHvK%ty%kW!Nui=EFUSo4&pm(t=*x<2U_d&xp zEHb^Aud=kw+pR{_*)UjeWsZ7v1p7LRH)xaov>0esOK@6_j6HCks3U;E|xn!q@Dw!0m^#Cn;%Qe4ki%K}u_!IlLnAYEkyh=SmmeZg7|+#cD;7Vk=E$ zHOa%3EgMIFeE=$(GU2v}Tzt5k-aO+(bLO{_c~IwFR~lTO$#r!4sLImP^w^YTkknbV zgjGtz+7XYDyWD;4?)-xH`K|B1vvZ}Hh}0)Br5>8gP_sSc!FZ9X+vVT+;x?<*?$q8xLHR{*u6rK@ z4#Zh!+ zgYbuHVF>Xh{;84wT9sjBz#dwfBjr6{g#SA%8CU-d(4%lOm0zTUSz7l6OX{~We{iW( z5nOcnEFvClhM&?KPwQfM)mWvIMub_GL<@03-jP;tL)l~@+WF42JO~$CxmT1uPkMEs zmzRhrTDrmwbeXB~h714GWj#a}BHS5eW>h);AmjnW+yLGcK|8_+Z_rL%%^0 zX}&aAqxGur*9mFwnzP0=r1um!nEMh*=yQ)bS=l3LR1eYOAqX(4EhpnSA&sE()Qll~ zU@E|&1=5GtlnI?D)2LZTVU$5vIxQG0R3BvynxIzQu0S~WKYJ{J7;(cI#wP1{*?dzW zKW)E#(0$iSJErpW5g+UQcV_%|-*mZ^3L+7vo$yQ+j5s48W5ZyU#YS%~zLEnuvn8(> zY+F;&Y7a*$*0ZP!TC>`icK%w{$Nfm35CAXgPr&c>{m-Qe^Z!Yyq6}^z{%b-R^B3Zq*H%J3aC8nR@c!=CkeZjgTU*+t%oIU@gZBYN0w!s`B^slzz@WH2fZY#j= zH3&@~ctwIH;s!HAJWv*r9Ks66j%G>uLnb{fKH)n`Pzbmg0fuBR9Kt8(vqz(}58Otx zSkWuTx&pJ13n8$fd{n9m$gt3py>PRHsm$I90@o7~2EwDCS}Au)!LK#w4UwbDfmc%) zHRI_+n7DDyIzwatbAe!BuP9=E{HT$GE!EUVmU$_&L!_IOii3)}8pQo8KCKubKs)*6 zXbMudEq17ty&C%>?fP~ox4nXvDi^l~zatt7FGLZi9EFW%u-=%aq81|OaCK1oSjr)s zE}9`)jK#;(#E}znCGa%E)PHalz`eBCilTZhWyF^{RK5RY&dW`;P<$iOP*2AIq{qe0 z!04zgJF8P;-EQef?Vhs>@b@Yp_W|O=ijpjjD{t1~W(bZb^CeEX0LD;dZ7TuUDmMzN z4Xgm&Eo5zj=d)_+ZXas_&YUb&g${Pv($ch~!@c|Za7HDhi61j}$_+XI$@&1!1obB6 z?GGwDl@D13)q9bfWTih_$=G}(v=QsRB!(8L*W|H>w7D*=djv*pq@EfodRHvAwYY9m zp+G6Bxh#j$x#NSHth?vj(W?ipux}w7Z5r3j*HM}yq z7P&nB29QraSGTV2l$0FdIz&QVm8-N*@@WPvKXwe|WqWcIMh!(meZVcgRzeT{AXkoq z5|#sid9Y*v5jmgD@_psX5RsQBst?A9m_;$)Tifw1i~b@$@$qQa4uEmcH}5MPQiQ)ag!YB@ZtJgl+mWbsi-C$S=Rowzq3yPRM)7HV@ z+`Oq!@|uv}UO^PTX~Kg@!kvTtHg@gz_&#}Pzt>=3RkJk?L$t+Z@01z$&I-6x>!aEY z8WRnidcQ(~=aoaD*R=yICvgP&|f|L4iPdt zDY#LH_}fO|?-shsj!y1>_3RS=@h+sQg_Vt~n~V29kTTWUp89%Am_kd@ck!Wp%Qe+J z&L`Tfa&i;t&|XpF3n23KyEa|nLsYT$*{-`ydYf6dLFVdH0GCZ_QtL{k zO#9uYZ*kYYVf<#2+m`Qhz|T13>~sDt{_`CE)}8f+mUVcI@4;2cAU!reJ;3?Mg#m6i zb^o2keITN6GDwQ;SsRc$a-oJBK-E8G0ruYXB+I18S6HZ$C+U8ZW=pV8rAAMaPnEl% zhYMirbELShhU!V$zC(K!2@;mQpoV*8=rf|YuY~%Nw0(~DEEe=d_JSGim9g&&B?KBN znhq6e3&Nt6^$JVHE4I?+J}u;-Fq$UtAz&9IAr5M&ZR6p$D!vE+R?LUX^A!FF&Q zh(p@!cD#Ln~^H#C~ zu17lI15cfT@z1_8w}KQyI#A9ed7_+FQ8!Hd+#?h){d~bV@w3{7wo=Mip;+Lkwu>P_ z(K-#i>}+g61LDS@F{7lY$%K+u%*=%{Fa)~!PwE9*q@zzO&BHegK5_bD#YiQXJrlntVp*T7%>su4)qAY2Vh{0vJnj$z2@QZ zDMF0N(6Ne-*&c}i8>V+y&<@e8hub)EeSesdzCDGT2 z35q8;R5#x1CVomvIEI4`%BKl*|G8)SidSfEt+TPMubZja1g;#H;j(C%0}Y=0#i@QO zM3;89e(xL%{h7VkScT1x8$Rr6E3}n4MwOj;OEv4#^_PmkWix%8YU$CNVoxS|Di?yXnMAg&Y9DS z$U zu*gmeLT;e*Z>g|eOMI9f6}$2*4VP!MWy>pxb}zpgdD;~S!p!jsw;Ij;^r~OcM*B8} z*fzTm)_b`9wjYUE=J7)moQT}sDPPA+-V31I6U3y7V3|KJ!Nl}Tz7~@23acQ_6qXzW zs9m?x`YdAz+C=8CN+5qLfRUe>D>-0QyUwHa0b&T6MxL=qcz!G3SD4u-IjEv-AI8|Q zip*h?*q5K_0$Ag|xRLA2T{gU{Nm7PHy1sL-E(JkfeYd#gIDu<9VsXbhqA^51E7{Kq zd@1DaPyVRYoE;RMl8zP0M_~F)x@V9j>;|uT^*tr^`c7q+M-FE=Bt^hPKMdPppEA@` zm*&VR{W2`UX!4=I%AB6@;Te{5NJo?aUGp-e^nqN0q%2`cIn{m& zbSf3?{?JiV+I;XI!77er2l2oYF%c}~8-=kB#gX;|U71x8u37W*y(|={gbFTTA(>Qs zCpRICWqF1D?J!APcOadgu8ny+P@x?J2ZyofOlm?yr8y_6p>9W{Yc0%twWPccHJ;uZ zO_jr%FP2*h(88>=$*<^F86uYG&bgA(S>V#WarwgNUcn$X7`-4MwqVk$HeMOI(5Sp1 zV$vDpN4}4#=`L8^KF1t!>)%VRLx3xfnS=YDupl~)Oo@lsLW6s{0{h8g=E=j`JgSaO zgJ+S6&@?)Z)M)Slr_x8Lx_#V;n$PLh=ZImFt^^*rvWpLqEdb@gB8%8ugSkk9`LaWt zpW(n+=R~mt-qT7sjC2T@)M(;?RMVZjx_zxje-F_+RZrcb;=8SMn8^?_xl#XviRKNN z?u}}X-rmV=D`N$lhIW%)7-Y2YS3kymWbG{RP*YP4FEky@O0Nuz$OsLP30^;Nj)G-gQzrFyQupW$a#M&tfu8_qst@z6$=yMx)A934U;(;(M;UzsL}=cz5g-%nFoU3HpWp8@vkoowug8{5!Q!^zTYxs6%li%+3J=rVxMru@gj9 zq=ud8pZ^ubuiuwPLyu3uT<)%+*<*UUP`XFByz(2w&V!N*fyTJm&(^;=^quj$wjsLK z7kfWGW*Yf}zWf=qHkgoYtb)6jC*r^BUjEKv@z*QGYDyyiJLKel0zIj9F{y!Nr}}=WC=Lc>#oz<2;m<%d zK``lPzf!?QiH>l7_?$jvWgvx^I z&Pr+E!h}olvr9v}s#li|P0Hff0$nl2nrPSA6-oNEbmEG&Q;T9unRl#-J@3$Po&&z0 z@Sek`J6xPVE3W8NwQ9b)+pnTjdmgFmbX4G9~FPYzIy|>I(_r z_4cV~O{tp%P+ms9zwn9nWHF@vOCsYRrv?5xw$xIZToJQ1HbEo8M_uUgeC%={X9fct z;)e8`T#{Hr3YP2D)Er6zai8mYNxF`1DT}n($iPKHHmP|ci)4Vdu&Cr)l{XbEf$vae3ijqC%+$!48o0!$^0`h`M-%_)sg& zDYhhehJ;)5Pn?G`j%VmU=NlVQI^h2eIr;DB```Bme}kMf)+13V|3m_ku*KvaMM-t= znA=c*`!D2V*lQWl{|-6nxcT~k-Htk36I6@&gH~JfA__uGL?&>!Zme$T5^|VNDwcdo zWg7*Io0N!U{Fr2xxr-ZyDMCC%b|4`T6fn@Q%)&(Zhmyq;MC3;n<|~K;^r!V-4WH_~lP7bwzk&~KW!k28U5G}6XqDHzT&Zc|Q&AXTk2I~GMz9nY9 zJ{6?DhPTvq>PHp9zWL{BHW38En4QVpDTs6-{JF+#88;> z^gQ-^_Fx@})tmP`+rJ4?n^iJ?5@unN{H=Xrw=(4cbhB_xqDefR17?2|S`qz{^9$qL z#kc+6k&`*$*+!jQ`e>~Wik_Z0wQ^s2Q8JRtWMF^rK=(P>0LIS1Q5;)sOkF9}g-)9B ze?d+<+L+mT^EM>NFjoHnhf96Lqec5LiB3P_{;dCwaLuv@*Zqy2Gn`*mn&=M9Ral*N zjjqp8P-0Z%46+FQlf$WW!j)WeupM*S4RIahu6`6rJbb`R9L;AwhwsN8<_-~Ig#R)| zJ?ny*3wvm9$YhQm$xH1h9jnRKfCyQnU4hc6poa0$=7iKhQlK`yh6Do8;@6Wk?atgo zDGT6MM4?!|^zo)-0qC9TAC;Qn*v)*tW&%SM!r5G~@^N^sh`?OkO1b@JiOtf-#_kcs zrHn^^#>_1KGo%X9{d1W94X!CwRWAkT?l}b33AQeQxNQIdmqW?fDM9*J{a1>o?dF86Y++OA5%`yaH*nvJ^Oz{PX6bO^WTw^ z$$yy^hu`#cGg6)8XvsBEI*swCz54K>lSKzbq1*VtnF}WQbdGWvWv?s9dy{$8^ch@Y z{|hnR97=my&R~BY-`nTOv)4Owr7v#}ujq`eF$E!?(Q4#cNkOq8!zuzXrUH@sD)LeZ zQDVSi9@Fl_DALGrpd6elB|!5Uft}=s1}Z+rrZUuP+~{;XmZka-xj^zIR0Rt;TfHe? zFbo?!P7-UJ2`&PTS@QqmIY9l?eRee-U0Ee1`zyj7&{qptzG z`)953mF7`*`tfO3rtTwNK$9Hk)%N}qKTT#vaax<+OiNpHr!>=Ls+(nSJ~!d_(szY1 z#x|eh9DP^5OpTtNpEyykB^xd{iTJS5WGfO%8|CRxgs|-*R-=Q>Q)-AH+>Qa0eS?gEu5a`VlUP{$2hyw)xSA2oIPysp zU8*3>2>3etG)}Y1Dt{-rk|AUPhqe!+bNYI<)<~7`KO;x;Ub(wGxYP1uGCO}TI-Y(P zZ8=%~Y1qv=Eg6_{q-Gj#-AuQMCPv-%87VFzzw%*iRu1-68?isY{neA0Z>F4h^QX)3 z^aRpb_}&eWVbneIXZ!wMyOqm^WgF@eb)wbND$d@}SucuvKGYGVI0{y^(U!5;JlG@@s)xaIcX{Rd zp0Z5II+}t2vAcb`oPmjVRr41Z07$0-KrZx-Inw@N&yQhvxQ{c-6|wR28O_)uP|n3e z`z&|^=$x-?=}YHAMrn5u@bve?#Nl0nf%*ifv1q&^9c4qTd?^>K?Xfdrw=u}ykTHW6 zT3gqci~QDicK24;RKD?jeBhb+P9GCsaq-v0Zfxx7s2A*gJo>-(KK}dn@!u8sKR6C6 z3d>m9tFwP{uUwxF7Z<6GF{Rb%rb5Du!GcV|@JEnk0w2p>B{YREzJn>y^T@9%U`hUj z4ogMgIyt$%^oLt{F8>db!zm7snGPH)s?^p<&{9#ZE8da9RKoNt-p&W>v|pjIL14A9 zSf3|60ki~k4TO>icohvDfM~#Cb}*2Q)9y?iNwb+czk$QFV~B{inb69MRE*Xjm6W5TWrYF+@y(~0(=+etEhp(S{<1GNP(Elro3AK& z0KIr~OaCCDjTP~U?MZ|cTo}$>9_)_Cl}buXc7>w3k5e@DbK$)x0(>qr_7Zy)TH4zs zzS#fr2aJ@7D~MYI$DIML=;|IOZKk6xV*|s9dOC)QYw&-fvh;5Wq=3nXrn=D3d0jf* z9-eQqvzTagvXp1PaFU}>f6=fRAnF7;T174l5PqO|^E}4jw8!z%9F?Dnorux$FKTnt zi+u@sLWESnUJ!59wbI9GR$Gxa_3%lsW;^)txQ_OG5W->&%`^l>$*6{v9DmhxBA=0; z33X*5n$+TbM)H}ELhe$^Vr{?CHKnz2*+Y6pW-rLGO=R?H(9||D-_am^_Pfo86?enN zpfxBdh#mvlCa6)Tu5U6HrHFz^kFjS5VuvQPRng+J{yPqq2R^i!6LuF>dAgiJ^N4Am zeZKH!r}G`5S4baw!u1;`(bM$>XP9o;U5c6=IGXCLiE`tu5uNi@n9uwUb{}^>sI8+& zl7CVD_8G6Jg^cGY94|(7h9{YHLD)97=IA!Hl{uJ6aW>%)_NblOYelf{@(d0}BZjWi z)*Gi_XF5pHaYax(`g1&TvWGqpItwN^(4JwY^AmFfmk(4Ey22D3-W-XtE-4xsUZX1$Q=qq8>;Weo2d2#g7;dGlZ z`{efWL+Hm-P=F*3Q1Tl3ddqn*{LFY7R_-Sfc~Q&hwk75enLjB+;oKcN z74o~E$nUE0Kq8Sh86lXsvkQXygqi?1iOHjQqFHiZuj~R8C^Jkwlu834(Qfzs#FLt_YtaI@Gck~uAbf0HE)#LWg365p%DTFIzd zj~WYQ3Hs)22tJ)TOm1!&byyE^c520|#B0Q>vE*%61i`@nR*9Bm#TshveVdVwhabZ;Xd0iO#&nsREnb;Ccox(2%#&PMP|jry0Z-AwDVl~UNLW#)EID3 zH`M=;)8krNiP$%mng4?OldUBRafP$AD3e(B zQA?%KtsCT`m)@vlz$2-HTq2)5h9!2^V+NTLl%K8FIbiSU+#v76f0RoKz1YU@;U%7i z$booNw0xaEJeH?yuGy_A`{}InOTw3F}I3U#>2pu2HgJFDPolw#~m90VWlp zTR$y4(44_ts2}VczGDV;$L&&dMyxKbzmxfx%(!caqXhMgc?P qs&>n+tyr?+|*K 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 literal 0 HcmV?d00001 From 2ecbc06b3ed2d1b030ea7071092904c6e2dac932 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 12 Oct 2012 13:23:41 +0200 Subject: [PATCH 45/51] Save timestamps after updating --- .../jetbrains/jps/incremental/storage/TimestampStorage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampStorage.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampStorage.java index be8c788cc25c..49761fe47a36 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampStorage.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampStorage.java @@ -78,7 +78,8 @@ public class TimestampStorage extends AbstractStateStorage Date: Fri, 12 Oct 2012 13:24:25 +0200 Subject: [PATCH 46/51] only log debugging info in groovy compiler tests --- .../jetbrains/jps/incremental/java/JavaBuilder.java | 4 +++- .../jps/incremental/groovy/GroovyBuilder.java | 10 +++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index 61e96768fc05..d17bb14d22b8 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -1139,7 +1139,9 @@ public class JavaBuilder extends ModuleLevelBuilder { final File sourceFile = source != null ? Utils.convertToFile(source.toUri()) : null; final String srcPath = sourceFile != null ? FileUtil.toSystemIndependentName(sourceFile.getPath()) : null; String message = diagnostic.getMessage(Locale.US); - LOG.info(message); + if (Utils.IS_TEST_MODE) { + LOG.info(message); + } myContext.processMessage( new CompilerMessage(BUILDER_NAME, kind, message, srcPath, diagnostic.getStartPosition(), diagnostic.getEndPosition(), diagnostic.getPosition(), diagnostic.getLineNumber(), diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java index 1162c7f33039..f442add9f798 100644 --- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java +++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java @@ -73,8 +73,10 @@ public class GroovyBuilder extends ModuleLevelBuilder { if (toCompile.isEmpty()) { return ExitCode.NOTHING_DONE; } - LOG.info("forStubs=" + myForStubs); - LOG.info("toCompile: " + toCompile); + if (Utils.IS_TEST_MODE) { + LOG.info("forStubs=" + myForStubs); + LOG.info("toCompile: " + toCompile); + } Map finalOutputs = getCanonicalModuleOutputs(context, chunk); if (finalOutputs == null) { @@ -149,7 +151,9 @@ public class GroovyBuilder extends ModuleLevelBuilder { List compiled = new ArrayList(); for (GroovycOSProcessHandler.OutputItem item : handler.getSuccessfullyCompiled()) { - LOG.info("compiled=" + item); + if (Utils.IS_TEST_MODE) { + LOG.info("compiled=" + item); + } compiled.add(ensureCorrectOutput(context, chunk, item, generationOutputs, compilerOutput)); } From eecadea82ae5e99a7c94e384072017f70e12eb9f Mon Sep 17 00:00:00 2001 From: Evgeny Zakrevsky Date: Fri, 12 Oct 2012 15:34:08 +0400 Subject: [PATCH 47/51] IDEA-92849 Too small fonts on toolwindow buttons and in push dialog --- platform/util/src/com/intellij/util/ui/UIUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index bfbef578ada2..02756dc3a005 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -415,9 +415,9 @@ public class UIUtil { int defSize = getLabelFont().getSize(); switch (size) { case SMALL: - return Math.max(defSize - 2f, 10f); + return Math.max(defSize - 2f, 11f); case MINI: - return Math.max(defSize - 4f, 8f); + return Math.max(defSize - 4f, 9f); default: return defSize; } From 12f77aaa9ee92b03cb4426e28ebaca6fd879f702 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 12 Oct 2012 13:37:17 +0200 Subject: [PATCH 48/51] fix mapping --- .../jps/incremental/storage/SourceToOutputMappingImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/SourceToOutputMappingImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/SourceToOutputMappingImpl.java index cd7f702c56a9..c3a922b9f5e1 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/SourceToOutputMappingImpl.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/SourceToOutputMappingImpl.java @@ -27,7 +27,7 @@ public class SourceToOutputMappingImpl implements SourceToOutputMapping { @Override public void setOutput(@NotNull String srcPath, @NotNull String outputPath) throws IOException { - myMapping.update(outputPath, outputPath); + myMapping.update(srcPath, outputPath); } @Override From 5bfd96ed0d165a583defcc26c6e46d801b45d01e Mon Sep 17 00:00:00 2001 From: nik Date: Fri, 12 Oct 2012 15:44:34 +0400 Subject: [PATCH 49/51] external compiler: added interface for registering src-to-output mapping, build logging generalized --- .../jps/builders/BuildOutputConsumer.java | 11 ++++ .../logging/ProjectBuilderLoggerBase.java | 48 ++++++++++++++ .../logging/ProjectBuilderLoggerImpl.java | 20 ++++++ .../logging}/BuildLoggingManager.java | 17 ++--- .../logging/ProjectBuilderLogger.java | 17 +++++ .../jetbrains/jps/cmdline/BuildRunner.java | 1 + .../jps/cmdline/ProjectDescriptor.java | 2 +- .../jps/incremental/CompileContext.java | 1 + .../jps/incremental/CompileContextImpl.java | 1 + .../jps/incremental/FSOperations.java | 7 ++- .../jps/incremental/IncProjectBuilder.java | 63 ++++++++++++++----- .../jps/incremental/ProjectBuilderLogger.java | 11 ---- .../incremental/ProjectBuilderLoggerImpl.java | 38 ----------- .../jps/incremental/TargetBuilder.java | 9 +-- .../artifacts/ArtifactSourceFilesState.java | 7 +-- .../artifacts/IncArtifactBuilder.java | 5 +- .../jps/incremental/java/JavaBuilder.java | 21 ++----- .../incremental/java/JavaBuilderLogger.java | 9 --- .../java/JavaBuilderLoggerImpl.java | 20 ------ .../incremental/storage/BuildDataManager.java | 3 +- .../data/b.txt | 0 .../jetbrains/ether/IncrementalTestCase.java | 42 +++---------- .../jps/builders/JpsBuildTestCase.java | 1 + .../artifacts/ArtifactBuilderTestCase.java | 7 +-- .../jps/android/AndroidDexBuilder.java | 7 ++- .../jps/android/AndroidPackagingBuilder.java | 7 ++- 26 files changed, 192 insertions(+), 183 deletions(-) create mode 100644 jps/jps-builders/src/org/jetbrains/jps/builders/BuildOutputConsumer.java create mode 100644 jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerBase.java create mode 100644 jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerImpl.java rename jps/jps-builders/src/org/jetbrains/jps/{incremental => builders/logging}/BuildLoggingManager.java (63%) create mode 100644 jps/jps-builders/src/org/jetbrains/jps/builders/logging/ProjectBuilderLogger.java delete mode 100644 jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectBuilderLogger.java delete mode 100644 jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectBuilderLoggerImpl.java delete mode 100644 jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilderLogger.java delete mode 100644 jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilderLoggerImpl.java delete mode 100644 jps/jps-builders/testData/output/artifactIncludesArchiveArtifact/data/b.txt diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildOutputConsumer.java b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildOutputConsumer.java new file mode 100644 index 000000000000..a1c290e74903 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildOutputConsumer.java @@ -0,0 +1,11 @@ +package org.jetbrains.jps.builders; + +import java.io.IOException; +import java.util.Collection; + +/** + * @author nik + */ +public interface BuildOutputConsumer { + void registerOutputFile(String outputFilePath, Collection sourceFiles) throws IOException; +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerBase.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerBase.java new file mode 100644 index 000000000000..3fcbe62d5a1a --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerBase.java @@ -0,0 +1,48 @@ +package org.jetbrains.jps.builders.impl.logging; + +import com.intellij.openapi.util.io.FileUtil; +import org.jetbrains.jps.builders.logging.ProjectBuilderLogger; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Set; + +/** + * @author nik + */ +public abstract class ProjectBuilderLoggerBase implements ProjectBuilderLogger { + @Override + public void logDeletedFiles(Collection outputs) { + if (outputs.isEmpty()) return; + final String[] buffer = new String[outputs.size()]; + int i = 0; + for (final String o : outputs) { + buffer[i++] = o; + } + Arrays.sort(buffer); + logLine("Cleaning output files:"); + for (final String o : buffer) { + logLine(o); + } + logLine("End of files"); + } + + @Override + public void logCompiledFiles(Set files, String builderName, final String description) throws IOException { + logLine(description); + final String[] buffer = new String[files.size()]; + int i = 0; + for (final File f : files) { + buffer[i++] = FileUtil.toSystemIndependentName(f.getCanonicalPath()); + } + Arrays.sort(buffer); + for (final String s : buffer) { + logLine(s); + } + logLine("End of files"); + } + + protected abstract void logLine(String message); +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerImpl.java new file mode 100644 index 000000000000..7bce8fe56b39 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/logging/ProjectBuilderLoggerImpl.java @@ -0,0 +1,20 @@ +package org.jetbrains.jps.builders.impl.logging; + +import com.intellij.openapi.diagnostic.Logger; + +/** + * @author nik + */ +public class ProjectBuilderLoggerImpl extends ProjectBuilderLoggerBase { + private static final Logger LOG = Logger.getInstance(ProjectBuilderLoggerImpl.class); + + @Override + public boolean isEnabled() { + return LOG.isDebugEnabled(); + } + + @Override + protected void logLine(final String message) { + LOG.debug(message); + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildLoggingManager.java b/jps/jps-builders/src/org/jetbrains/jps/builders/logging/BuildLoggingManager.java similarity index 63% rename from jps/jps-builders/src/org/jetbrains/jps/incremental/BuildLoggingManager.java rename to jps/jps-builders/src/org/jetbrains/jps/builders/logging/BuildLoggingManager.java index b57023012cae..267efc22454d 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildLoggingManager.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/logging/BuildLoggingManager.java @@ -1,24 +1,22 @@ -package org.jetbrains.jps.incremental; +package org.jetbrains.jps.builders.logging; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.builders.impl.logging.ProjectBuilderLoggerImpl; import org.jetbrains.jps.incremental.artifacts.ArtifactBuilderLogger; import org.jetbrains.jps.incremental.artifacts.ArtifactBuilderLoggerImpl; -import org.jetbrains.jps.incremental.java.JavaBuilderLogger; -import org.jetbrains.jps.incremental.java.JavaBuilderLoggerImpl; /** * @author nik */ public class BuildLoggingManager { - public static final BuildLoggingManager DEFAULT = new BuildLoggingManager(new ArtifactBuilderLoggerImpl(), new JavaBuilderLoggerImpl(), + public static final BuildLoggingManager DEFAULT = new BuildLoggingManager(new ArtifactBuilderLoggerImpl(), new ProjectBuilderLoggerImpl()); private ArtifactBuilderLogger myArtifactBuilderLogger; - private JavaBuilderLogger myJavaBuilderLogger; private final ProjectBuilderLogger myProjectLogger; - public BuildLoggingManager(@NotNull ArtifactBuilderLogger artifactBuilderLogger, @NotNull JavaBuilderLogger logger, @NotNull ProjectBuilderLogger projectLogger) { + public BuildLoggingManager(@NotNull ArtifactBuilderLogger artifactBuilderLogger, + @NotNull ProjectBuilderLogger projectLogger) { myArtifactBuilderLogger = artifactBuilderLogger; - myJavaBuilderLogger = logger; myProjectLogger = projectLogger; } @@ -27,11 +25,6 @@ public class BuildLoggingManager { return myArtifactBuilderLogger; } - @NotNull - public JavaBuilderLogger getJavaBuilderLogger() { - return myJavaBuilderLogger; - } - @NotNull public ProjectBuilderLogger getProjectBuilderLogger() { return myProjectLogger; diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/logging/ProjectBuilderLogger.java b/jps/jps-builders/src/org/jetbrains/jps/builders/logging/ProjectBuilderLogger.java new file mode 100644 index 000000000000..db217f9c7818 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/logging/ProjectBuilderLogger.java @@ -0,0 +1,17 @@ +package org.jetbrains.jps.builders.logging; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Set; + +/** + * @author nik + */ +public interface ProjectBuilderLogger { + boolean isEnabled(); + + void logDeletedFiles(Collection paths); + + void logCompiledFiles(Set files, String builderName, String description) throws IOException; +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java index 28d397acd634..c5f7c9d4e979 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java @@ -15,6 +15,7 @@ import org.jetbrains.jps.builders.impl.BuildDataPathsImpl; import org.jetbrains.jps.builders.impl.BuildRootIndexImpl; import org.jetbrains.jps.builders.impl.BuildTargetIndexImpl; import org.jetbrains.jps.builders.java.dependencyView.Callbacks; +import org.jetbrains.jps.builders.logging.BuildLoggingManager; import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.incremental.*; import org.jetbrains.jps.incremental.fs.BuildFSState; diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ProjectDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ProjectDescriptor.java index 7454ac156ea5..098aeaf3a3a6 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ProjectDescriptor.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ProjectDescriptor.java @@ -2,7 +2,7 @@ package org.jetbrains.jps.cmdline; import org.jetbrains.jps.builders.BuildRootIndex; import org.jetbrains.jps.builders.BuildTargetIndex; -import org.jetbrains.jps.incremental.BuildLoggingManager; +import org.jetbrains.jps.builders.logging.BuildLoggingManager; import org.jetbrains.jps.incremental.CompilerEncodingConfiguration; import org.jetbrains.jps.incremental.fs.BuildFSState; import org.jetbrains.jps.incremental.storage.BuildDataManager; diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java index 3dd40df94d5b..1c559f9da881 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.ModuleChunk; import org.jetbrains.jps.ProjectPaths; import org.jetbrains.jps.api.CanceledStatus; +import org.jetbrains.jps.builders.logging.BuildLoggingManager; import org.jetbrains.jps.cmdline.ProjectDescriptor; import org.jetbrains.jps.model.java.compiler.ProcessorConfigProfile; import org.jetbrains.jps.model.module.JpsModule; diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContextImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContextImpl.java index 9acb359678eb..853fa414bfe4 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContextImpl.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContextImpl.java @@ -8,6 +8,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.*; import org.jetbrains.jps.api.CanceledStatus; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; +import org.jetbrains.jps.builders.logging.BuildLoggingManager; import org.jetbrains.jps.cmdline.ProjectDescriptor; import org.jetbrains.jps.incremental.messages.BuildMessage; import org.jetbrains.jps.incremental.messages.FileDeletedEvent; diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java index 05b519556582..3ddcc71ab079 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java @@ -22,6 +22,7 @@ import org.jetbrains.jps.model.module.JpsModule; import java.io.File; import java.io.IOException; +import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -128,12 +129,12 @@ public class FSOperations { } static void markDirtyFiles(CompileContext context, - ModuleBuildTarget target, + BuildTarget target, Timestamps timestamps, boolean forceMarkDirty, @Nullable THashSet currentFiles) throws IOException { final ModuleExcludeIndex rootsIndex = context.getProjectDescriptor().getModuleExcludeIndex(); - markDirtyFiles(context, target, timestamps, forceMarkDirty, currentFiles, - new HashSet(rootsIndex.getModuleExcludes(target.getModule()))); + Set excludes = target instanceof ModuleBuildTarget ? new HashSet(rootsIndex.getModuleExcludes(((ModuleBuildTarget)target).getModule())) : Collections.emptySet(); + markDirtyFiles(context, target, timestamps, forceMarkDirty, currentFiles, excludes); } static void markDirtyFiles(CompileContext context, BuildTarget target, Timestamps timestamps, boolean forceMarkDirty, @Nullable THashSet currentFiles, final Set excludes) throws IOException { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index 9d535ea6c616..6a4837db0175 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -25,6 +25,7 @@ import org.jetbrains.jps.builders.java.JavaBuilderUtil; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor; import org.jetbrains.jps.builders.java.dependencyView.Callbacks; +import org.jetbrains.jps.builders.logging.ProjectBuilderLogger; import org.jetbrains.jps.builders.storage.SourceToOutputMapping; import org.jetbrains.jps.cmdline.BuildRunner; import org.jetbrains.jps.cmdline.ProjectDescriptor; @@ -525,8 +526,7 @@ public class IncProjectBuilder { BuildTarget target = targets.iterator().next(); if (target instanceof ModuleBuildTarget) { - ModuleBuildTarget moduleBuildTarget = (ModuleBuildTarget)target; - return runModuleLevelBuilders(context, new ModuleChunk(Collections.singleton(moduleBuildTarget))); + return runModuleLevelBuilders(context, new ModuleChunk(Collections.singleton((ModuleBuildTarget)target))); } else { try { @@ -563,7 +563,9 @@ public class IncProjectBuilder { } }; //noinspection unchecked - ((TargetBuilder)builder).build(target, context, holder); + BuildOutputConsumerImpl outputConsumer = new BuildOutputConsumerImpl(target, context); + ((TargetBuilder)builder).build(target, holder, outputConsumer, context); + outputConsumer.fireFileGeneratedEvent(); context.checkCanceled(); } } @@ -757,9 +759,7 @@ public class IncProjectBuilder { FSOperations.processFilesToRecompile(context, chunk, processor); } }; - if (!context.isProjectRebuild()) { - deleteOutputsOfDirtyFiles(context, dirtyFilesHolder); - } + deleteOutputsOfDirtyFiles(context, dirtyFilesHolder); BUILDER_CATEGORY_LOOP: for (BuilderCategory category : BuilderCategory.values()) { @@ -833,6 +833,10 @@ public class IncProjectBuilder { private static > void deleteOutputsOfDirtyFiles(final CompileContext context, DirtyFilesHolder dirtyFilesHolder) throws ProjectBuildException { + if (context.isProjectRebuild()) { + return; + } + final BuildDataManager dataManager = context.getProjectDescriptor().dataManager; try { ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger(); @@ -958,13 +962,12 @@ public class IncProjectBuilder { final Timestamps timestamps = pd.timestamps.getStorage(); final BuildTargetConfiguration configuration = pd.getTargetsState().getTargetConfiguration(target); if (context.isProjectRebuild() || configuration.isTargetDirty() || context.getScope().isRecompilationForced(target)) { + clearOutputFiles(context, target); FSOperations.markDirtyFiles(context, target, timestamps, true, null, Collections.emptySet()); configuration.save(); } - else if (context.isMake()) { - if (pd.fsState.markInitialScanPerformed(target)) { - FSOperations.markDirtyFiles(context, target, timestamps, false, null, Collections.emptySet()); - } + else if (pd.fsState.markInitialScanPerformed(target)) { + FSOperations.markDirtyFiles(context, target, timestamps, false, null, Collections.emptySet()); } } @@ -992,19 +995,21 @@ public class IncProjectBuilder { forceMarkDirty = true; } } - initModuleFSState(context, target, forceMarkDirty); + initTargetFSState(context, target, forceMarkDirty); + updateOutputRootsLayout(context, target); } } else { // forced compilation mode if (context.getScope().isRecompilationForced(target)) { - initModuleFSState(context, target, true); + initTargetFSState(context, target, true); + updateOutputRootsLayout(context, target); } } } } - private static void initModuleFSState(CompileContext context, ModuleBuildTarget target, final boolean forceMarkDirty) throws IOException { + private static void initTargetFSState(CompileContext context, BuildTarget target, final boolean forceMarkDirty) throws IOException { final ProjectDescriptor pd = context.getProjectDescriptor(); final Timestamps timestamps = pd.timestamps.getStorage(); final THashSet currentFiles = new THashSet(FileUtil.FILE_HASHING_STRATEGY); @@ -1022,8 +1027,6 @@ public class IncProjectBuilder { fsState.registerDeleted(target, file, timestamps); } } - - updateOutputRootsLayout(context, target); } private static void updateOutputRootsLayout(CompileContext context, ModuleBuildTarget target) throws IOException { @@ -1119,4 +1122,34 @@ public class IncProjectBuilder { }); } + private static class BuildOutputConsumerImpl implements BuildOutputConsumer { + private final BuildTarget myTarget; + private final CompileContext myContext; + private FileGeneratedEvent myFileGeneratedEvent; + private File myOutputDir; + + public BuildOutputConsumerImpl(BuildTarget target, CompileContext context) { + myTarget = target; + myContext = context; + myFileGeneratedEvent = new FileGeneratedEvent(); + myOutputDir = myTarget.getOutputDir(myContext.getProjectDescriptor().dataManager.getDataPaths()); + } + + @Override + public void registerOutputFile(String outputFilePath, Collection sourceFiles) throws IOException { + String relativePath = FileUtil.getRelativePath(myOutputDir, new File(outputFilePath)); + if (myOutputDir != null && relativePath != null) { + myFileGeneratedEvent.add(myOutputDir.getAbsolutePath(), relativePath); + } + for (String sourceFile : sourceFiles) { + myContext.getProjectDescriptor().dataManager.getSourceToOutputMap(myTarget).appendOutput(sourceFile, outputFilePath); + } + } + + public void fireFileGeneratedEvent() { + if (!myFileGeneratedEvent.getPaths().isEmpty()) { + myContext.processMessage(myFileGeneratedEvent); + } + } + } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectBuilderLogger.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectBuilderLogger.java deleted file mode 100644 index d9883375c79b..000000000000 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectBuilderLogger.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.jetbrains.jps.incremental; - -import java.util.Collection; - -/** - * @author nik - */ -public interface ProjectBuilderLogger { - boolean isEnabled(); - void logDeletedFiles(Collection paths); -} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectBuilderLoggerImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectBuilderLoggerImpl.java deleted file mode 100644 index bfb94564f9aa..000000000000 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectBuilderLoggerImpl.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.jetbrains.jps.incremental; - -import com.intellij.openapi.diagnostic.Logger; - -import java.util.Arrays; -import java.util.Collection; - -/** - * @author nik - */ -public class ProjectBuilderLoggerImpl implements ProjectBuilderLogger { - private static final Logger LOG = Logger.getInstance(ProjectBuilderLoggerImpl.class); - - @Override - public boolean isEnabled() { - return LOG.isDebugEnabled(); - } - - @Override - public void logDeletedFiles(Collection outputs) { - if (outputs.isEmpty()) return; - final String[] buffer = new String[outputs.size()]; - int i = 0; - for (final String o : outputs) { - buffer[i++] = o; - } - Arrays.sort(buffer); - logLine("Cleaning output files:"); - for (final String o : buffer) { - logLine(o); - } - logLine("End of files"); - } - - protected void logLine(final String message) { - LOG.debug(message); - } -} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/TargetBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/TargetBuilder.java index 7fea04440365..c3b7c2f58251 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/TargetBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/TargetBuilder.java @@ -1,10 +1,7 @@ package org.jetbrains.jps.incremental; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.builders.BuildRootDescriptor; -import org.jetbrains.jps.builders.BuildTarget; -import org.jetbrains.jps.builders.BuildTargetType; -import org.jetbrains.jps.builders.DirtyFilesHolder; +import org.jetbrains.jps.builders.*; import java.io.IOException; import java.util.Collection; @@ -24,7 +21,7 @@ public abstract class TargetBuilder holder) - throws ProjectBuildException, IOException; + public abstract void build(@NotNull T target, @NotNull DirtyFilesHolder holder, @NotNull BuildOutputConsumer outputConsumer, + @NotNull CompileContext context) throws ProjectBuildException, IOException; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactSourceFilesState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactSourceFilesState.java index b3fd9e9345f3..50235786941c 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactSourceFilesState.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactSourceFilesState.java @@ -11,10 +11,7 @@ import org.jetbrains.jps.incremental.IncProjectBuilder; import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactRootDescriptor; import org.jetbrains.jps.incremental.artifacts.instructions.SourceFileFilter; import org.jetbrains.jps.incremental.fs.BuildFSState; -import org.jetbrains.jps.incremental.storage.BuildDataManager; -import org.jetbrains.jps.incremental.storage.BuildTargetConfiguration; -import org.jetbrains.jps.incremental.storage.CompositeStorageOwner; -import org.jetbrains.jps.incremental.storage.StorageOwner; +import org.jetbrains.jps.incremental.storage.*; import java.io.File; import java.io.IOException; @@ -58,7 +55,7 @@ public class ArtifactSourceFilesState extends CompositeStorageOwner { BuildTargetConfiguration configuration = myProjectDescriptor.getTargetsState().getTargetConfiguration(myTarget); if (context.isProjectRebuild() || configuration.isTargetDirty() || context.getScope().isRecompilationForced(myTarget)) { IncProjectBuilder.clearOutputFiles(context, myTarget); - myProjectDescriptor.dataManager.getSourceToOutputMap(myTarget).clean(); + ((SourceToOutputMappingImpl)myProjectDescriptor.dataManager.getSourceToOutputMap(myTarget)).clean(); getOrCreateOutSrcMapping().clean(); markDirtyFiles(dataManager, null, true, context); configuration.save(); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java index b8dfb4705efd..f758babfe166 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java @@ -7,6 +7,7 @@ import com.intellij.util.containers.MultiMap; import gnu.trove.THashSet; import gnu.trove.TIntObjectHashMap; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.builders.BuildOutputConsumer; import org.jetbrains.jps.builders.BuildRootDescriptor; import org.jetbrains.jps.builders.BuildRootIndex; import org.jetbrains.jps.builders.DirtyFilesHolder; @@ -38,8 +39,8 @@ public class IncArtifactBuilder extends TargetBuilder holder) throws ProjectBuildException { + @NotNull DirtyFilesHolder holder, + @NotNull BuildOutputConsumer outputConsumer, @NotNull CompileContext context) throws ProjectBuildException { JpsArtifact artifact = target.getArtifact(); if (StringUtil.isEmpty(artifact.getOutputPath())) { context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Cannot build '" + artifact.getName() + "' artifact: output path is not specified")); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index d17bb14d22b8..dca1ab40671d 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -38,6 +38,7 @@ import org.jetbrains.jps.builders.java.JavaBuilderUtil; import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor; import org.jetbrains.jps.builders.java.dependencyView.Callbacks; import org.jetbrains.jps.builders.java.dependencyView.Mappings; +import org.jetbrains.jps.builders.logging.ProjectBuilderLogger; import org.jetbrains.jps.cmdline.ProjectDescriptor; import org.jetbrains.jps.incremental.*; import org.jetbrains.jps.incremental.messages.BuildMessage; @@ -234,13 +235,13 @@ public class JavaBuilder extends ModuleLevelBuilder { } } - final JavaBuilderLogger logger = context.getLoggingManager().getJavaBuilderLogger(); + final ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger(); if (logger.isEnabled() && context.isMake()) { if (filesToCompile.size() > 0) { - logFiles(filesToCompile, logger, "Compiling files:"); + logger.logCompiledFiles(filesToCompile, BUILDER_NAME, "Compiling files:"); } if (!formsToCompile.isEmpty()) { - logFiles(formsToCompile, logger, "Compiling forms:"); + logger.logCompiledFiles(formsToCompile, FORMS_BUILDER_NAME, "Compiling forms:"); } } @@ -261,20 +262,6 @@ public class JavaBuilder extends ModuleLevelBuilder { } } - private static void logFiles(Set files, JavaBuilderLogger logger, final String description) throws IOException { - logger.log(description); - final String[] buffer = new String[files.size()]; - int i = 0; - for (final File f : files) { - buffer[i++] = FileUtil.toSystemIndependentName(f.getCanonicalPath()); - } - Arrays.sort(buffer); - for (final String s : buffer) { - logger.log(s); - } - logger.log("End of files"); - } - @Override public boolean shouldHonorFileEncodingForCompilation(File file) { return JAVA_SOURCES_FILTER.accept(file) || FORM_SOURCES_FILTER.accept(file); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilderLogger.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilderLogger.java deleted file mode 100644 index 837183e6a71b..000000000000 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilderLogger.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.jetbrains.jps.incremental.java; - -/** - * @author nik - */ -public interface JavaBuilderLogger { - void log(String line); - boolean isEnabled(); -} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilderLoggerImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilderLoggerImpl.java deleted file mode 100644 index bca646cef3a7..000000000000 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilderLoggerImpl.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.jetbrains.jps.incremental.java; - -import com.intellij.openapi.diagnostic.Logger; - -/** - * @author nik - */ -public class JavaBuilderLoggerImpl implements JavaBuilderLogger { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.java.JavaBuilderLoggerImpl"); - - @Override - public void log(String line) { - LOG.debug(line); - } - - @Override - public boolean isEnabled() { - return LOG.isDebugEnabled(); - } -} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java index cc7603086c65..a040393b2b2e 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java @@ -7,6 +7,7 @@ import org.jetbrains.jps.builders.BuildTarget; import org.jetbrains.jps.builders.impl.BuildTargetChunk; import org.jetbrains.jps.builders.java.dependencyView.Mappings; import org.jetbrains.jps.builders.storage.BuildDataPaths; +import org.jetbrains.jps.builders.storage.SourceToOutputMapping; import org.jetbrains.jps.incremental.artifacts.ArtifactsBuildData; import java.io.*; @@ -49,7 +50,7 @@ public class BuildDataManager implements StorageOwner { return new File(myDataPaths.getDataStorageRoot(), "output-roots"); } - public SourceToOutputMappingImpl getSourceToOutputMap(final BuildTarget target) throws IOException { + public SourceToOutputMapping getSourceToOutputMap(final BuildTarget target) throws IOException { SourceToOutputMappingImpl mapping; synchronized (mySourceToOutputLock) { mapping = mySourceToOutputs.get(target); diff --git a/jps/jps-builders/testData/output/artifactIncludesArchiveArtifact/data/b.txt b/jps/jps-builders/testData/output/artifactIncludesArchiveArtifact/data/b.txt deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java index 8b8a16759c50..97d0b4b1f83a 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java @@ -19,16 +19,14 @@ import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Processor; -import org.jetbrains.jps.builders.CompileScopeTestBuilder; -import org.jetbrains.jps.incremental.*; -import org.jetbrains.jps.util.JpsPathUtil; import org.jetbrains.jps.builders.BuildResult; -import org.jetbrains.jps.builders.BuildTarget; +import org.jetbrains.jps.builders.CompileScopeTestBuilder; import org.jetbrains.jps.builders.JpsBuildTestCase; -import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; import org.jetbrains.jps.cmdline.ProjectDescriptor; +import org.jetbrains.jps.builders.logging.BuildLoggingManager; +import org.jetbrains.jps.builders.impl.logging.ProjectBuilderLoggerBase; +import org.jetbrains.jps.incremental.Utils; import org.jetbrains.jps.incremental.artifacts.ArtifactBuilderLoggerImpl; -import org.jetbrains.jps.incremental.java.JavaBuilderLogger; import org.jetbrains.jps.model.JpsDummyElement; import org.jetbrains.jps.model.java.JavaSourceRootType; import org.jetbrains.jps.model.java.JpsJavaExtensionService; @@ -37,10 +35,9 @@ import org.jetbrains.jps.model.library.JpsLibrary; import org.jetbrains.jps.model.library.JpsOrderRootType; import org.jetbrains.jps.model.library.sdk.JpsSdk; import org.jetbrains.jps.model.module.JpsModule; +import org.jetbrains.jps.util.JpsPathUtil; import java.io.*; -import java.util.Collections; -import java.util.Set; /** * @author db @@ -173,8 +170,7 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { protected BuildResult doTestBuild(int makesCount) { StringBuilder log = new StringBuilder(); String rootPath = FileUtil.toSystemIndependentName(workDir.getAbsolutePath()) + "/"; - final TestJavaBuilderLogger builderLogger = new TestJavaBuilderLogger(rootPath, log); - final ProjectDescriptor pd = createProjectDescriptor(new BuildLoggingManager(new ArtifactBuilderLoggerImpl(), builderLogger, + final ProjectDescriptor pd = createProjectDescriptor(new BuildLoggingManager(new ArtifactBuilderLoggerImpl(), new TestProjectBuilderLogger(rootPath, log))); try { doBuild(pd, CompileScopeTestBuilder.rebuild().allModules()).assertSuccessful(); @@ -238,10 +234,6 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { } } - private static CompileScope createAllModulesScope(final boolean forcedCompilation) { - return new CompileScopeImpl(forcedCompilation, JavaModuleBuildTargetType.ALL_TYPES, Collections.>emptySet(), Collections., Set>emptyMap()); - } - private JpsSdk getOrCreateJdk() { if (myJdk == null) { myJdk = addJdk("IDEA jdk"); @@ -259,27 +251,7 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { module.addSourceRoot(getUrl(testRootRelativePath), JavaSourceRootType.TEST_SOURCE); } - private static class TestJavaBuilderLogger implements JavaBuilderLogger { - private final String myRoot; - private final StringBuilder myLog; - - public TestJavaBuilderLogger(String root, final StringBuilder log) { - myRoot = root; - myLog = log; - } - - @Override - public void log(String line) { - myLog.append(StringUtil.trimStart(line, myRoot)).append('\n'); - } - - @Override - public boolean isEnabled() { - return true; - } - } - - private static class TestProjectBuilderLogger extends ProjectBuilderLoggerImpl { + private static class TestProjectBuilderLogger extends ProjectBuilderLoggerBase { private final String myRoot; private StringBuilder myLog; diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java index 81694f5ecc2d..5506b74e4563 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java @@ -11,6 +11,7 @@ import org.jetbrains.jps.api.CanceledStatus; import org.jetbrains.jps.builders.impl.BuildDataPathsImpl; import org.jetbrains.jps.builders.impl.BuildRootIndexImpl; import org.jetbrains.jps.builders.impl.BuildTargetIndexImpl; +import org.jetbrains.jps.builders.logging.BuildLoggingManager; import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.cmdline.ClasspathBootstrap; import org.jetbrains.jps.cmdline.ProjectDescriptor; diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java index a0329d934dc4..a20b8d561e37 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java @@ -23,9 +23,8 @@ import org.jetbrains.jps.builders.BuildResult; import org.jetbrains.jps.builders.CompileScopeTestBuilder; import org.jetbrains.jps.builders.JpsBuildTestCase; import org.jetbrains.jps.cmdline.ProjectDescriptor; -import org.jetbrains.jps.incremental.BuildLoggingManager; -import org.jetbrains.jps.incremental.ProjectBuilderLoggerImpl; -import org.jetbrains.jps.incremental.java.JavaBuilderLoggerImpl; +import org.jetbrains.jps.builders.logging.BuildLoggingManager; +import org.jetbrains.jps.builders.impl.logging.ProjectBuilderLoggerImpl; import org.jetbrains.jps.model.JpsElementFactory; import org.jetbrains.jps.model.artifact.DirectoryArtifactType; import org.jetbrains.jps.model.artifact.JpsArtifact; @@ -105,7 +104,7 @@ public abstract class ArtifactBuilderTestCase extends JpsBuildTestCase { protected BuildResult doBuild(CompileScopeTestBuilder scope) { BuildResult result; - ProjectDescriptor descriptor = createProjectDescriptor(new BuildLoggingManager(myArtifactBuilderLogger, new JavaBuilderLoggerImpl(), new ProjectBuilderLoggerImpl())); + ProjectDescriptor descriptor = createProjectDescriptor(new BuildLoggingManager(myArtifactBuilderLogger, new ProjectBuilderLoggerImpl())); try { myArtifactBuilderLogger.clear(); result = doBuild(descriptor, scope); diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidDexBuilder.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidDexBuilder.java index 7354f9e55e80..66244c2bd099 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidDexBuilder.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidDexBuilder.java @@ -33,6 +33,7 @@ import org.jetbrains.jps.ProjectPaths; import org.jetbrains.jps.android.builder.AndroidProjectBuildTarget; import org.jetbrains.jps.android.model.JpsAndroidModuleExtension; import org.jetbrains.jps.android.model.JpsAndroidSdkProperties; +import org.jetbrains.jps.builders.BuildOutputConsumer; import org.jetbrains.jps.builders.BuildRootDescriptor; import org.jetbrains.jps.builders.DirtyFilesHolder; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; @@ -68,8 +69,10 @@ public class AndroidDexBuilder extends TargetBuilder holder) throws ProjectBuildException { + public void build(@NotNull AndroidProjectBuildTarget target, + @NotNull DirtyFilesHolder holder, + @NotNull BuildOutputConsumer outputConsumer, + @NotNull CompileContext context) throws ProjectBuildException { if (target.getKind() != AndroidProjectBuildTarget.AndroidBuilderKind.DEX && AndroidJpsUtil.isLightBuild(context)) { return; } diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidPackagingBuilder.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidPackagingBuilder.java index fb8135121a43..8f8a995d5453 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidPackagingBuilder.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidPackagingBuilder.java @@ -18,6 +18,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.ProjectPaths; import org.jetbrains.jps.android.builder.AndroidProjectBuildTarget; import org.jetbrains.jps.android.model.JpsAndroidModuleExtension; +import org.jetbrains.jps.builders.BuildOutputConsumer; import org.jetbrains.jps.builders.BuildRootDescriptor; import org.jetbrains.jps.builders.DirtyFilesHolder; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; @@ -60,8 +61,10 @@ public class AndroidPackagingBuilder extends TargetBuilder holder) throws ProjectBuildException { + public void build(@NotNull AndroidProjectBuildTarget target, + @NotNull DirtyFilesHolder holder, + @NotNull BuildOutputConsumer outputConsumer, + @NotNull CompileContext context) throws ProjectBuildException { if (target.getKind() != AndroidProjectBuildTarget.AndroidBuilderKind.PACKAGING || AndroidJpsUtil.isLightBuild(context)) { return; } From fe577aaaf8ed963521b4549b8412d906f4fa8caa Mon Sep 17 00:00:00 2001 From: nik Date: Fri, 12 Oct 2012 15:54:57 +0400 Subject: [PATCH 50/51] external compiler: out-src mappings for artifacts moved to proper directory --- .../incremental/artifacts/ArtifactSourceFilesState.java | 7 ++----- .../jps/incremental/artifacts/ArtifactsBuildData.java | 9 ++------- .../jps/incremental/storage/BuildDataManager.java | 4 ++-- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactSourceFilesState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactSourceFilesState.java index 50235786941c..651c84f77cd1 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactSourceFilesState.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactSourceFilesState.java @@ -29,13 +29,10 @@ public class ArtifactSourceFilesState extends CompositeStorageOwner { private File myOutSrcMappingsFile; private final ProjectDescriptor myProjectDescriptor; - public ArtifactSourceFilesState(ArtifactBuildTarget target, - ProjectDescriptor projectDescriptor, - File mappingsDir) { - int artifactId = projectDescriptor.getTargetsState().getBuildTargetId(target); + public ArtifactSourceFilesState(ArtifactBuildTarget target, ProjectDescriptor projectDescriptor) { myProjectDescriptor = projectDescriptor; myTarget = target; - myOutSrcMappingsFile = new File(new File(mappingsDir, String.valueOf(artifactId)), "out-src"); + myOutSrcMappingsFile = new File(projectDescriptor.dataManager.getDataPaths().getTargetDataRoot(target), "out-src" + File.separator + "data"); } public ArtifactOutputToSourceMapping getOrCreateOutSrcMapping() throws IOException { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactsBuildData.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactsBuildData.java index 73207d9c0ed7..5d245ce93218 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactsBuildData.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactsBuildData.java @@ -1,11 +1,9 @@ package org.jetbrains.jps.incremental.artifacts; -import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.jps.cmdline.ProjectDescriptor; import org.jetbrains.jps.incremental.storage.CompositeStorageOwner; import org.jetbrains.jps.incremental.storage.StorageOwner; -import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -15,17 +13,15 @@ import java.util.Map; */ public class ArtifactsBuildData extends CompositeStorageOwner { private Map myArtifactState; - private final File myMappingsDir; - public ArtifactsBuildData(File artifactsDataDir) throws IOException { + public ArtifactsBuildData() throws IOException { myArtifactState = new HashMap(); - myMappingsDir = new File(artifactsDataDir, "mappings"); } public ArtifactSourceFilesState getOrCreateState(ArtifactBuildTarget target, ProjectDescriptor projectDescriptor) { ArtifactSourceFilesState state = myArtifactState.get(target); if (state == null) { - state = new ArtifactSourceFilesState(target, projectDescriptor, myMappingsDir); + state = new ArtifactSourceFilesState(target, projectDescriptor); myArtifactState.put(target, state); } return state; @@ -44,7 +40,6 @@ public class ArtifactsBuildData extends CompositeStorageOwner { } } myArtifactState.clear(); - FileUtil.delete(myMappingsDir); if (exc != null) { throw exc; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java index a040393b2b2e..9bade85f9a6d 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java @@ -20,7 +20,7 @@ import java.util.Map; * Date: 10/7/11 */ public class BuildDataManager implements StorageOwner { - private static final int VERSION = 14; + private static final int VERSION = 15; private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildDataManager"); private static final String SRC_TO_FORM_STORAGE = "src-form"; private static final String MAPPINGS_STORAGE = "mappings"; @@ -42,7 +42,7 @@ public class BuildDataManager implements StorageOwner { mySrcToFormMap = new OneToManyPathsMapping(new File(getSourceToFormsRoot(), "data")); myOutputRootsLayout = new ModuleOutputRootsLayout(new File(getOutputsLayoutRoot(), "data")); myMappings = new Mappings(getMappingsRoot(), useMemoryTempCaches); - myArtifactsBuildData = new ArtifactsBuildData(new File(dataPaths.getDataStorageRoot(), "artifacts")); + myArtifactsBuildData = new ArtifactsBuildData(); myVersionFile = new File(myDataPaths.getDataStorageRoot(), "version.dat"); } From 716a19171852dc65ac1047bcdcd2f36939f8e55b Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Fri, 12 Oct 2012 16:02:37 +0400 Subject: [PATCH 51/51] IDEA-90594 --- .../android-designer/src/META-INF/plugin.xml | 3 -- .../AndroidSelectedFileEditorProvider.java | 30 ++++--------------- 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/plugins/android-designer/src/META-INF/plugin.xml b/plugins/android-designer/src/META-INF/plugin.xml index ce299312b62e..e4e7726d743e 100644 --- a/plugins/android-designer/src/META-INF/plugin.xml +++ b/plugins/android-designer/src/META-INF/plugin.xml @@ -15,9 +15,6 @@ - - diff --git a/plugins/android-designer/src/com/intellij/android/designer/AndroidSelectedFileEditorProvider.java b/plugins/android-designer/src/com/intellij/android/designer/AndroidSelectedFileEditorProvider.java index a7ace5a2dc31..ad58731aae30 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/AndroidSelectedFileEditorProvider.java +++ b/plugins/android-designer/src/com/intellij/android/designer/AndroidSelectedFileEditorProvider.java @@ -15,14 +15,14 @@ */ package com.intellij.android.designer; -import com.intellij.openapi.components.*; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.fileEditor.*; import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager; import com.intellij.openapi.fileEditor.impl.EditorHistoryManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.xmlb.XmlSerializerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -30,6 +30,8 @@ import org.jetbrains.annotations.Nullable; * @author Alexander Lobas */ public class AndroidSelectedFileEditorProvider implements SelectedFileEditorProvider { + private static final String KEY = "AndroidLayoutSelectedEditor"; + @Nullable @Override public FileEditorProvider getSelectedProvider(Project project, VirtualFile openedFile) { @@ -37,7 +39,7 @@ public class AndroidSelectedFileEditorProvider implements SelectedFileEditorProv return null; } - String editorTypeId = MyState.getInstance(project).editorTypeId; + String editorTypeId = PropertiesComponent.getInstance(project).getValue(KEY); if (editorTypeId != null) { return FileEditorProviderManager.getInstance().getProvider(editorTypeId); } @@ -72,7 +74,7 @@ public class AndroidSelectedFileEditorProvider implements SelectedFileEditorProv if (file != null && AndroidDesignerEditorProvider.acceptLayout(myProject, file)) { FileEditorProvider provider = EditorHistoryManager.getInstance(myProject).getSelectedProvider(file); if (provider != null) { - MyState.getInstance(myProject).editorTypeId = provider.getEditorTypeId(); + PropertiesComponent.getInstance(myProject).setValue(KEY, provider.getEditorTypeId()); } } } @@ -99,24 +101,4 @@ public class AndroidSelectedFileEditorProvider implements SelectedFileEditorProv return "AndroidLayoutSelectedEditorListener"; } } - - @State(name = "AndroidLayoutSelectedEditor", storages = {@Storage(file = StoragePathMacros.WORKSPACE_FILE)}) - public static class MyState implements PersistentStateComponent { - public String editorTypeId; - - @Nullable - @Override - public MyState getState() { - return this; - } - - @Override - public void loadState(MyState state) { - XmlSerializerUtil.copyBean(state, this); - } - - public static MyState getInstance(Project project) { - return ServiceManager.getService(project, MyState.class); - } - } } \ No newline at end of file