diff --git a/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java b/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java index fc7c7d7b7eb8..3aef0d599083 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java @@ -70,8 +70,7 @@ import org.jetbrains.jps.client.CompileServerClient; import org.jetbrains.jps.server.ClasspathBootstrap; import org.jetbrains.jps.server.Server; -import javax.tools.JavaCompiler; -import javax.tools.ToolProvider; +import javax.tools.*; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -586,6 +585,10 @@ public class CompileServerManager implements ApplicationComponent{ cmdLine.addParameter("-XX:ReservedCodeCacheSize=64m"); cmdLine.addParameter("-Xmx" + Registry.intValue("compiler.server.heap.size") + "m"); cmdLine.addParameter("-Djava.awt.headless=true"); + final String shouldGenerateIndex = System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION); + if (shouldGenerateIndex != null) { + cmdLine.addParameter("-D"+ GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION +"=" + shouldGenerateIndex); + } //noinspection ConstantConditions if (pingInterval > 0L) { cmdLine.addParameter("-D" + GlobalOptions.PING_INTERVAL_MS_OPTION + "=" + pingInterval); diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java b/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java index 3cfdb3a8979f..f2459aadff39 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java @@ -32,20 +32,13 @@ import com.sun.jdi.ReferenceType; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author lex */ class ReloadClassesWorker { private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.impl.ReloadClassesWorker"); - /** - * number of clasess that will be reloaded in one go. - * Such restriction is needed to deal with big number of classes being reloaded - */ - private static final int CLASSES_CHUNK_SIZE = 100; private final DebuggerSession myDebuggerSession; private final HotSwapProgress myProgress; @@ -111,11 +104,12 @@ class ReloadClassesWorker { final Project project = debugProcess.getProject(); final BreakpointManager breakpointManager = (DebuggerManagerEx.getInstanceEx(project)).getBreakpointManager(); breakpointManager.disableBreakpoints(debugProcess); - + //virtualMachineProxy.suspend(); - + try { - final Map redefineMap = new HashMap(); + RedefineProcessor redefineProcessor = new RedefineProcessor(virtualMachineProxy); + int processedClassesCount = 0; for (final String qualifiedName : modifiedClasses.keySet()) { processedClassesCount++; @@ -124,32 +118,30 @@ class ReloadClassesWorker { myProgress.setFraction(processedClassesCount / (double)modifiedClasses.size()); } final HotSwapFile fileDescr = modifiedClasses.get(qualifiedName); + final byte[] content; try { - final byte[] buffer = FileUtil.loadFileBytes(fileDescr.file); - final List classes = virtualMachineProxy.classesByName(qualifiedName); - for (final ReferenceType reference : classes) { - redefineMap.put(reference, buffer); - } + content = FileUtil.loadFileBytes(fileDescr.file); } catch (IOException e) { reportProblem(qualifiedName, e); + continue; } - if (redefineMap.size() >= CLASSES_CHUNK_SIZE) { - // reload this portion of clasess and clear the map to free memory - try { - virtualMachineProxy.redefineClasses(redefineMap); - } - finally { - redefineMap.clear(); - } - } - } - if (redefineMap.size() > 0) { - virtualMachineProxy.redefineClasses(redefineMap); + redefineProcessor.processClass(qualifiedName, content); } + redefineProcessor.processPending(); myProgress.setFraction(1); - - myProgress.addMessage(myDebuggerSession, MessageCategory.INFORMATION, DebuggerBundle.message("status.classes.reloaded", modifiedClasses.size())); + + final int partiallyRedefinedClassesCount = redefineProcessor.getPartiallyRedefinedClassesCount(); + if (partiallyRedefinedClassesCount == 0) { + myProgress.addMessage(myDebuggerSession, MessageCategory.INFORMATION, + DebuggerBundle.message("status.classes.reloaded", redefineProcessor.getProcessedClassesCount())); + } + else { + final String message = DebuggerBundle.message("status.classes.not.all.versions.reloaded", partiallyRedefinedClassesCount, + redefineProcessor.getProcessedClassesCount()); + myProgress.addMessage(myDebuggerSession, MessageCategory.WARNING, message); + } + if (LOG.isDebugEnabled()) { LOG.debug("classes reloaded"); } @@ -203,11 +195,10 @@ class ReloadClassesWorker { catch (Exception e) { processException(e); } - } private void reportProblem(final String qualifiedName, @Nullable Exception ex) { - String reason = null; + String reason = null; if (ex != null) { reason = ex.getLocalizedMessage(); } @@ -223,4 +214,78 @@ class ReloadClassesWorker { StringBuilderSpinAllocator.dispose(buf); } } + + private static class RedefineProcessor { + /** + * number of classes that will be reloaded in one go. + * Such restriction is needed to deal with big number of classes being reloaded + */ + private static final int CLASSES_CHUNK_SIZE = 100; + private final VirtualMachineProxyImpl myVirtualMachineProxy; + private final Map myRedefineMap = new HashMap(); + private int myProcessedClassesCount; + private int myPartiallyRedefinedClassesCount; + + public RedefineProcessor(VirtualMachineProxyImpl virtualMachineProxy) { + myVirtualMachineProxy = virtualMachineProxy; + } + + public void processClass(String qualifiedName, byte[] content) throws Throwable { + final List vmClasses = myVirtualMachineProxy.classesByName(qualifiedName); + if (vmClasses.isEmpty()) return; + + if (vmClasses.size() == 1) { + myRedefineMap.put(vmClasses.get(0), content); + if (myRedefineMap.size() >= CLASSES_CHUNK_SIZE) { + processChunk(); + } + return; + } + + int redefinedVersionsCount = 0; + Throwable error = null; + for (ReferenceType vmClass : vmClasses) { + try { + myVirtualMachineProxy.redefineClasses(Collections.singletonMap(vmClass, content)); + redefinedVersionsCount++; + } + catch (Throwable t) { + error = t; + } + } + if (redefinedVersionsCount == 0) { + throw error; + } + + if (redefinedVersionsCount < vmClasses.size()) { + myPartiallyRedefinedClassesCount++; + } + myProcessedClassesCount++; + } + + private void processChunk() throws Throwable { + // reload this portion of classes and clear the map to free memory + try { + myVirtualMachineProxy.redefineClasses(myRedefineMap); + myProcessedClassesCount += myRedefineMap.size(); + } + finally { + myRedefineMap.clear(); + } + } + + public void processPending() throws Throwable { + if (myRedefineMap.size() > 0) { + processChunk(); + } + } + + public int getProcessedClassesCount() { + return myProcessedClassesCount; + } + + public int getPartiallyRedefinedClassesCount() { + return myPartiallyRedefinedClassesCount; + } + } } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java index 4a6ea36e7de0..be3f59f985d2 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java @@ -27,6 +27,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.roots.OrderRootType; @@ -371,7 +372,7 @@ public class LibraryRootsComponent implements Disposable, LibraryEditorComponent } } - public abstract class AttachItemActionBase extends AnAction { + public abstract class AttachItemActionBase extends DumbAwareAction { private VirtualFile myLastChosen = null; protected AttachItemActionBase(String text) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index be5894779a33..d2a350e0d918 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -688,7 +688,7 @@ public class GenericsHighlightUtil { return true; } } - if (isUncheckedTypeArgumentConversion(lTypeArg, rTypeArg)) return true; + if (!TypeConversionUtil.typesAgree(lTypeArg, rTypeArg, false)) return true; } return false; } @@ -730,48 +730,6 @@ public class GenericsHighlightUtil { return false; } - private static boolean isUncheckedTypeArgumentConversion (PsiType lTypeArg, PsiType rTypeArg) { - if (lTypeArg instanceof PsiPrimitiveType || rTypeArg instanceof PsiPrimitiveType) return false; - if (lTypeArg.equals(rTypeArg)) return false; - if (lTypeArg instanceof PsiCapturedWildcardType) { - //ignore capture conversion - return isUncheckedTypeArgumentConversion(((PsiCapturedWildcardType)lTypeArg).getWildcard(), rTypeArg); - } - if (rTypeArg instanceof PsiCapturedWildcardType) { - //ignore capture conversion - return isUncheckedTypeArgumentConversion(lTypeArg, ((PsiCapturedWildcardType)rTypeArg).getWildcard()); - } - - if (lTypeArg instanceof PsiWildcardType || rTypeArg instanceof PsiWildcardType) { - return !lTypeArg.isAssignableFrom(rTypeArg); - } - - if (lTypeArg instanceof PsiArrayType && rTypeArg instanceof PsiArrayType) { - return isUncheckedTypeArgumentConversion(((PsiArrayType)rTypeArg).getComponentType(), ((PsiArrayType)lTypeArg).getComponentType()); - } - if (lTypeArg instanceof PsiArrayType || rTypeArg instanceof PsiArrayType) return false; - if (lTypeArg instanceof PsiIntersectionType) { - for (PsiType type : ((PsiIntersectionType)lTypeArg).getConjuncts()) { - if (!isUncheckedTypeArgumentConversion(type, rTypeArg)) return false; - } - return true; - } - if (!(lTypeArg instanceof PsiClassType)) { - LOG.error("left: "+lTypeArg + "; "+lTypeArg.getClass()); - } - if (rTypeArg instanceof PsiIntersectionType) { - for (PsiType type : ((PsiIntersectionType)rTypeArg).getConjuncts()) { - if (!isUncheckedTypeArgumentConversion(lTypeArg, type)) return false; - } - return true; - } - if (!(rTypeArg instanceof PsiClassType)) { - LOG.error("right :"+rTypeArg + "; "+rTypeArg.getClass()); - } - return ((PsiClassType)lTypeArg).resolve() instanceof PsiTypeParameter || - ((PsiClassType)rTypeArg).resolve() instanceof PsiTypeParameter; - } - @Nullable public static HighlightInfo checkForeachLoopParameterType(PsiForeachStatement statement) { final PsiParameter parameter = statement.getIterationParameter(); diff --git a/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java b/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java index 34305ef9bc58..6c1f9220644d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java +++ b/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.folding.impl; +import com.intellij.codeInsight.daemon.impl.CollectHighlightsUtil; import com.intellij.codeInsight.folding.JavaCodeFoldingSettings; import com.intellij.codeInsight.generation.OverrideImplementUtil; import com.intellij.lang.ASTNode; @@ -47,7 +48,10 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class JavaFoldingBuilder extends CustomFoldingBuilder implements DumbAware { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.folding.impl.JavaFoldingBuilder"); @@ -312,7 +316,9 @@ public class JavaFoldingBuilder extends CustomFoldingBuilder implements DumbAwar if (importKeyword == null) return null; int startOffset = importKeyword.getTextRange().getEndOffset() + 1; int endOffset = statements[statements.length - 1].getTextRange().getEndOffset(); - return new TextRange(startOffset, endOffset); + if (!hasErrorElementsNearby(element.getContainingFile(), startOffset, endOffset)) { + return new TextRange(startOffset, endOffset); + } } if (element instanceof PsiDocComment) { return element.getTextRange(); @@ -330,6 +336,16 @@ public class JavaFoldingBuilder extends CustomFoldingBuilder implements DumbAwar return null; } + public static boolean hasErrorElementsNearby(final PsiFile file, int startOffset, int endOffset) { + endOffset = CharArrayUtil.shiftForward(file.getText(), endOffset, " \t\n"); + for (PsiElement element : CollectHighlightsUtil.getElementsInRange(file, startOffset, endOffset)) { + if (element instanceof PsiErrorElement) { + return true; + } + } + return false; + } + @Nullable private static TextRange getFileHeader(PsiJavaFile file) { PsiElement first = file.getFirstChild(); diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java index f27234ef9a5c..8d04c48535b9 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java @@ -767,7 +767,14 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { int minSpaces = 0; int minLineFeeds = 1; PsiElement psi = myChild1.getPsi(); - if (mySettings.KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE || psi != null && PsiTreeUtil.hasErrorElements(psi)) { + + // We want to avoid situations like below: + // 1. Call 'introduce variable' refactoring for the code like 'System.out.println(1);'; + // 2. When KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE is on, the output looks like 'int i = 1; System.out.println(i);'; + // That's why we process the option only during the explicit reformat (directly invoked by an user). + if ((mySettings.KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE && FormatterUtil.isFormatterCalledExplicitly()) + || psi != null && PsiTreeUtil.hasErrorElements(psi)) + { minSpaces = 1; minLineFeeds = 0; } diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java index 7aea5e6cdcdd..557c12198331 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java @@ -354,7 +354,7 @@ public class TypeConversionUtil { final PsiClass class1 = PsiUtil.resolveClassInType(typeArg1); if (class1 instanceof PsiTypeParameter) { for (PsiType type : class1.getExtendsListTypes()) { - if (TypesDistinctProver.provablyDistinct(type, typeArg2)) return false; + if (TypesDistinctProver.provablyDistinct(type, typeArg2) && !isAssignable(type, typeArg2)) return false; } } } @@ -746,7 +746,7 @@ public class TypeConversionUtil { private static boolean isAssignableToWildcard(PsiWildcardType wildcardType, PsiType right) { if (wildcardType.isSuper()) { - return isAssignable(right, wildcardType.getSuperBound()); + return isAssignable(wildcardType.getSuperBound(), right); } return isAssignable(wildcardType.getExtendsBound(), right); } @@ -859,7 +859,7 @@ public class TypeConversionUtil { return true; } - private static boolean typesAgree(PsiType typeLeft, PsiType typeRight, boolean allowUncheckedConversion) { + public static boolean typesAgree(PsiType typeLeft, PsiType typeRight, boolean allowUncheckedConversion) { if (typeLeft instanceof PsiWildcardType) { final PsiWildcardType leftWildcard = (PsiWildcardType)typeLeft; final PsiType leftBound = leftWildcard.getBound(); diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java b/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java index 4f86a7039399..4f479fc41c7f 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java @@ -92,7 +92,10 @@ public class TypesDistinctProver { for (PsiClassType type : parameter.getExtendsListTypes()) { if (!TypeConversionUtil.isAssignable(type, substitutedType1 != null ? substitutedType1 : substitutedType2, false)) return true; } - } else if (provablyDistinct(substitutedType1, substitutedType2)) return true; + } else { + if (provablyDistinct(substitutedType1, substitutedType2)) return true; + if (substitutedType1 instanceof PsiWildcardType && !((PsiWildcardType)substitutedType1).isBounded()) return true; + } } return false; } @@ -100,8 +103,8 @@ public class TypesDistinctProver { final PsiClass boundClass1 = classResolveResult1.getElement(); final PsiClass boundClass2 = classResolveResult2.getElement(); return type2 != null && type1 != null && !type1.equals(type2) && - !InheritanceUtil.isInheritorOrSelf(boundClass1, boundClass2, true) && - !InheritanceUtil.isInheritorOrSelf(boundClass2, boundClass1, true); + (!InheritanceUtil.isInheritorOrSelf(boundClass1, boundClass2, true) || + !InheritanceUtil.isInheritorOrSelf(boundClass2, boundClass1, true)); } public static boolean provablyDistinct(PsiWildcardType type1, PsiWildcardType type2) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/WildcardTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/WildcardTypes.java index 5145e806c4b4..1a586323851c 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/WildcardTypes.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/WildcardTypes.java @@ -172,4 +172,48 @@ class My { public void test() { if (getSuperclass() == List.class); } +} + +class IDEA75178 { + void test(Set labels) { + final Matcher empty = isEmpty(); + assertThat(labels, empty); + assertAlsoThat(empty, labels); + } + + public static void assertThat(T actual, Matcher matcher) { throw new AssertionError(actual.toString() + matcher.toString());} + public static void assertAlsoThat(Matcher matcher, T actual) { throw new AssertionError(actual.toString() + matcher.toString());} + + public static Matcher isEmpty() { + return null; + } + + static class Matcher<T>{} + + class Foo {} + void testComment() { + Set foos = Collections.emptySet(); + assertThatComment(foos, hasSize(0)); + } + + Matcher> hasSize(int size) {return size == 0 ? null : null;} + void assertThatComment(T actual, Matcher matcher){ throw new AssertionError(actual.toString() + matcher.toString());} +} + +class IDEA66750 { + public void test() { + List> data = new ArrayList>(); + List> y = (List>)data; + System.out.println(y); + + ArrayList al = (ArrayList) new ArrayList(1); + System.out.println(al); + } +} + +class IDEA73377 { + public Iterator, ?>> iterator(Map map) { + //noinspection unchecked + return (Iterator, ?>>)map.entrySet().iterator(); + } } \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/fieldProperties/nonIncremental1/.idea/misc.xml b/java/java-tests/testData/compileServer/incremental/fieldProperties/nonIncremental1/.idea/misc.xml index 8a6459d2c612..83d038f968a4 100644 --- a/java/java-tests/testData/compileServer/incremental/fieldProperties/nonIncremental1/.idea/misc.xml +++ b/java/java-tests/testData/compileServer/incremental/fieldProperties/nonIncremental1/.idea/misc.xml @@ -3,7 +3,7 @@ - + diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy index 23e2dcadaf3f..2b537de76906 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -618,7 +618,7 @@ class Test { doTest(before, toPaste2, expected) } - def testPlainTextPaste() { + void testPlainTextPaste() { def before = '''\ line1 line2 @@ -628,7 +628,7 @@ class Test { def toPaste = '''\ line to paste #1 - line to paste #2 + line to paste #2\ ''' @@ -641,10 +641,33 @@ line to paste #1 doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT) } - def testPlainTextPasteWithCompleteReplacement() { + void "test plain text when pasted string ends by line feed"() { + def before = '''\ + line1 + line2 + +''' + + def toPaste = + '''\ +line to paste #1 +line to paste #2 +''' + + def expected = '''\ + line1 + line2 + line to paste #1 + line to paste #2 + +''' + doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT) + } + + void "test plain text when caret is after selection"() { def before = '''\ line1 - line2\ +\ ''' def toPaste = @@ -655,32 +678,14 @@ line to paste #2 def expected = '''\ + line1 line to paste #1 line to paste #2 ''' doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT) } - def testPlainTextMultilinePasteWithCaretAfterSelection() { - def before = '''\ - line1\ -''' - - def toPaste = - '''\ -line to paste #1 -line to paste #2 -''' - - - def expected = '''\ -line to paste #1 -line to paste #2 -''' - doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT) - } - - def testPlainTextThatStartsByLineFeed() { + void testPlainTextThatStartsByLineFeed() { def before = '''\ line 1 # item1 @@ -715,6 +720,37 @@ line 1 doTest(before, toPaste2, expected2, StdFileTypes.PLAIN_TEXT) } + void "test formatter-based paste that starts with white space"() { + def before = '''\ +class Test { + int i; + int j; + + void test() { + + } +} +''' + + def toPaste = '''\ + int i; + int j;\ +''' + + def expected = '''\ +class Test { + int i; + int j; + + void test() { + int i; + int j; + } +} +''' + doTest(before, toPaste, expected) + } + def doTest(String before, toPaste, expected, FileType fileType = StdFileTypes.JAVA) { myFixture.configureByText(fileType, before) @@ -732,6 +768,7 @@ line 1 finally { settings.REFORMAT_ON_PASTE = old } + myFixture.editor.selectionModel.removeSelection() myFixture.checkResult(expected) } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy index 3b48d5e41fd3..5d13114d3e7f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy @@ -167,6 +167,32 @@ class Test { assertEquals(2, closureFolds.size()) } + public void "test closure folding doesn't expand when editing inside"() { + def text = """\ +class Test { + void test() { + new Runnable() { + public void run() { + System.out.println(); + } + }; + } +} +""" + + configure text + def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl + def closureStartFold = foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable")) + assertNotNull closureStartFold + assertFalse closureStartFold.expanded + assert text.substring(closureStartFold.endOffset).startsWith('System') //one line closure + + myFixture.type('2') + myFixture.doHighlighting() + closureStartFold = foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable")) + assert closureStartFold + } + public void testFindInFolding() { def text = """\ class Test { diff --git a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy new file mode 100644 index 000000000000..ceb2bbd93df6 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy @@ -0,0 +1,54 @@ +/* + * 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.psi.resolve + +import com.intellij.openapi.application.ex.PathManagerEx +import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.testFramework.PsiTestUtil +import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase + +/** + * @author peter + */ +class ResolveInLibrariesTest extends JavaCodeInsightFixtureTestCase { + + public void "test prefer current library when navigation from its source"() { + def lib = LocalFileSystem.getInstance().refreshAndFindFileByPath(PathManagerEx.getTestDataPath() + "/../../../lib") + def nanoJar = lib.children.find { it.name.startsWith("nanoxml") } + def nanoSrc = lib.findChild("src").children.find { it.name.startsWith("nanoxml") } + + def jarCopy = myFixture.copyFileToProject(nanoJar.path, 'lib/nanoJar.jar') + def srcCopy = myFixture.copyFileToProject(nanoSrc.path, 'lib/nanoSrc.zip') + + PsiTestUtil.addLibrary(myModule, 'nano1', lib.path, ["/$nanoJar.name!/"] as String[], ["/src/$nanoSrc.name!/"] as String[]) + PsiTestUtil.addLibrary(myModule, 'nano2', jarCopy.parent.path, ["/$jarCopy.name!/"] as String[], ["/$srcCopy.name!/"] as String[]) + + def parsers = JavaPsiFacade.getInstance(project).findClasses('net.n3.nanoxml.IXMLParser', GlobalSearchScope.allScope(project)) + assert parsers.size() == 2 + + def file0 = parsers[0].navigationElement.containingFile + assert file0.virtualFile.path.startsWith(nanoSrc.path) + assert file0.findReferenceAt(file0.text.indexOf('IXMLReader reader')).resolve().navigationElement.containingFile.virtualFile.path.startsWith(nanoSrc.path) + + def file1 = parsers[1].navigationElement.containingFile + assert file1.virtualFile.path.startsWith(srcCopy.path) + assert file1.findReferenceAt(file1.text.indexOf('IXMLReader reader')).resolve().navigationElement.containingFile.virtualFile.path.startsWith(srcCopy.path) + + } + +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java b/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java index f2fdd71e4b0d..febbe3880eb7 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java +++ b/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java @@ -9,4 +9,5 @@ public interface GlobalOptions { String USE_EXTERNAL_JAVAC_OPTION = "use.external.javac.process"; String HOSTNAME_OPTION = "localhost.name"; String PING_INTERVAL_MS_OPTION = "server.ping.interval"; + String GENERATE_CLASSPATH_INDEX_OPTION = "generate.classpath.index"; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/SharedThreadPool.java b/jps/jps-builders/src/org/jetbrains/jps/api/SharedThreadPool.java new file mode 100644 index 000000000000..508abe015b3f --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/api/SharedThreadPool.java @@ -0,0 +1,18 @@ +package org.jetbrains.jps.api; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @author Eugene Zhuravlev + * Date: 3/29/12 + */ +public class SharedThreadPool { + public static final ExecutorService INSTANCE = Executors.newCachedThreadPool(); + public static final AsyncTaskExecutor ASYNC_EXEC = new AsyncTaskExecutor() { + @Override + public void submit(Runnable runnable) { + INSTANCE.submit(runnable); + } + }; +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java index 62b2c1fd2cb4..dbe6eecef318 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java @@ -30,7 +30,7 @@ public class BuilderRegistry { myTasksExecutor = Executors.newFixedThreadPool(runtime.availableProcessors()); runtime.addShutdownHook(new Thread() { public void run() { - myTasksExecutor.shutdownNow(); + myTasksExecutor.shutdown(); } }); @@ -70,7 +70,7 @@ public class BuilderRegistry { } public void shutdown() { - myTasksExecutor.shutdownNow(); + myTasksExecutor.shutdown(); } } 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 f59e2c6a0da9..5d493a8dca64 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -9,7 +9,9 @@ import com.intellij.util.io.MappingFailedException; import com.intellij.util.io.PersistentEnumerator; import org.jetbrains.jps.*; import org.jetbrains.jps.api.CanceledStatus; +import org.jetbrains.jps.api.GlobalOptions; import org.jetbrains.jps.api.RequestFuture; +import org.jetbrains.jps.api.SharedThreadPool; import org.jetbrains.jps.incremental.java.ExternalJavacDescriptor; import org.jetbrains.jps.incremental.java.JavaBuilder; import org.jetbrains.jps.incremental.java.JavaBuilderLogger; @@ -21,10 +23,13 @@ import org.jetbrains.jps.incremental.storage.SourceToFormMapping; import org.jetbrains.jps.incremental.storage.SourceToOutputMapping; import org.jetbrains.jps.server.ProjectDescriptor; +import java.io.BufferedWriter; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Field; import java.util.*; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; /** @@ -35,6 +40,8 @@ public class IncProjectBuilder { private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.IncProjectBuilder"); public static final String COMPILE_SERVER_NAME = "COMPILE SERVER"; + private static final String CLASSPATH_INDEX_FINE_NAME = "classpath.index"; + private static final boolean GENERATE_CLASSPATH_INDEX = "true".equals(System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION)); private final ProjectDescriptor myProjectDescriptor; private final BuilderRegistry myBuilderRegistry; @@ -54,6 +61,7 @@ public class IncProjectBuilder { private float myModulesProcessed = 0.0f; private final float myTotalModulesWork; private final int myTotalModuleLevelBuilderCount; + private final List myAsyncTasks = new ArrayList(); public IncProjectBuilder(ProjectDescriptor pd, BuilderRegistry builderRegistry, Map builderParams, CanceledStatus cs) { myProjectDescriptor = pd; @@ -131,6 +139,15 @@ public class IncProjectBuilder { finally { memWatcher.stop(); flushContext(context); + // wait for the async tasks + for (Future task : myAsyncTasks) { + try { + task.get(); + } + catch (Throwable th) { + LOG.info(th); + } + } } } @@ -309,16 +326,18 @@ public class IncProjectBuilder { } } - private void buildChunk(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { + private void buildChunk(CompileContext context, final ModuleChunk chunk) throws ProjectBuildException { + boolean doneSomething = false; try { context.ensureFSStateInitialized(chunk); if (context.isMake()) { processDeletedPaths(context, chunk); + doneSomething |= context.hasRemovedSources(); } context.onChunkBuildStart(chunk); - runModuleLevelBuilders(context, chunk); + doneSomething = runModuleLevelBuilders(context, chunk); } catch (ProjectBuildException e) { throw e; @@ -343,11 +362,59 @@ public class IncProjectBuilder { } finally { Paths.CHUNK_REMOVED_SOURCES_KEY.set(context, null); + if (doneSomething && GENERATE_CLASSPATH_INDEX) { + final boolean forTests = context.isCompilingTests(); + final Future future = SharedThreadPool.INSTANCE.submit(new Runnable() { + @Override + public void run() { + createClasspathIndex(chunk, forTests); + } + }); + myAsyncTasks.add(future); + } } } } } + private static void createClasspathIndex(final ModuleChunk chunk, boolean forTests) { + final Set outputPaths = new LinkedHashSet(); + for (Module module : chunk.getModules()) { + if (forTests) { + outputPaths.add(new File(module.getTestOutputPath())); + } + else { + outputPaths.add(new File(module.getOutputPath())); + } + } + for (File outputRoot : outputPaths) { + try { + BufferedWriter writer = new BufferedWriter(new FileWriter(new File(outputRoot, CLASSPATH_INDEX_FINE_NAME))); + try { + writeIndex(writer, outputRoot, ""); + } + finally { + writer.close(); + } + } + catch (IOException e) { + // Ignore. Failed to create optional classpath index + } + } + } + + private static void writeIndex(final BufferedWriter writer, final File file, final String path) throws IOException { + writer.write(path); + writer.write('\n'); + final File[] files = file.listFiles(); + if (files != null) { + for (File child : files) { + writeIndex(writer, child, path + "/" + child.getName()); + } + } + } + + private void processDeletedPaths(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { try { // cleanup outputs @@ -420,13 +487,14 @@ public class IncProjectBuilder { } } - private void runModuleLevelBuilders(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException { + // return true if changed something, false otherwise + private boolean runModuleLevelBuilders(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException { + boolean doneSomething = false; boolean rebuildFromScratchRequested = false; float stageCount = myTotalModuleLevelBuilderCount; final int modulesInChunk = chunk.getModules().size(); int buildersPassed = 0; boolean nextPassRequired; - do { nextPassRequired = false; context.beforeCompileRound(chunk); @@ -448,6 +516,8 @@ public class IncProjectBuilder { } final ModuleLevelBuilder.ExitCode buildResult = builder.build(context, chunk); + doneSomething |= (buildResult != ModuleLevelBuilder.ExitCode.NOTHING_DONE); + if (buildResult == ModuleLevelBuilder.ExitCode.ABORT) { throw new ProjectBuildException("Builder " + builder.getDescription() + " requested build stop"); } @@ -492,6 +562,8 @@ public class IncProjectBuilder { } } while (nextPassRequired); + + return doneSomething; } private void runProjectLevelBuilders(CompileContext context) throws ProjectBuildException { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java index d503e83bff8e..5f442ca56ae0 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java @@ -32,7 +32,7 @@ public abstract class ModuleLevelBuilder extends Builder { } public static enum ExitCode { - OK, ABORT, ADDITIONAL_PASS_REQUIRED, CHUNK_REBUILD_REQUIRED + NOTHING_DONE, OK, ABORT, ADDITIONAL_PASS_REQUIRED, CHUNK_REBUILD_REQUIRED } public abstract ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException; 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 5378c096312a..0e5360167d20 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 @@ -33,8 +33,7 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; import org.objectweb.asm.commons.EmptyVisitor; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; +import javax.tools.*; import java.io.*; import java.net.MalformedURLException; import java.net.ServerSocket; @@ -239,7 +238,7 @@ public class JavaBuilder extends ModuleLevelBuilder { private ExitCode compile(final CompileContext context, ModuleChunk chunk, Collection files, Collection forms) throws Exception { - ExitCode exitCode = ExitCode.OK; + ExitCode exitCode = ExitCode.NOTHING_DONE; final boolean hasSourcesToCompile = !files.isEmpty() || !forms.isEmpty(); @@ -264,6 +263,7 @@ public class JavaBuilder extends ModuleLevelBuilder { DELTA_MAPPINGS_CALLBACK_KEY.set(context, delta.getCallback()); try { if (hasSourcesToCompile) { + exitCode = ExitCode.OK; final Set sourcePath = TEMPORARY_SOURCE_ROOTS_KEY.get(context, Collections.emptySet()); final String chunkName = getChunkPresentableName(chunk); @@ -868,7 +868,8 @@ public class JavaBuilder extends ModuleLevelBuilder { myContext.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "OutOfMemoryError: insufficient memory")); } else { - myContext.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.INFO, line)); + final BuildMessage.Kind kind = line.toLowerCase(Locale.US).contains("error")? BuildMessage.Kind.ERROR : BuildMessage.Kind.INFO; + myContext.processMessage(new CompilerMessage(BUILDER_NAME, kind, line)); } } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java index 06e142335840..21238fa03190 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java @@ -1,6 +1,7 @@ package org.jetbrains.jps.incremental.resources; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.jps.Module; import org.jetbrains.jps.ModuleChunk; @@ -38,12 +39,14 @@ public class ResourcesBuilder extends ModuleLevelBuilder { } try { final ResourcePatterns finalPatterns = patterns; + final Ref doneSomething = new Ref(false); context.processFilesToRecompile(chunk, new FileProcessor() { public boolean apply(final Module module, final File file, final String sourceRoot) throws IOException { if (finalPatterns.isResourceFile(file, sourceRoot)) { try { context.processMessage(new ProgressMessage("Copying " + file.getPath())); final String moduleName = module.getName().toLowerCase(Locale.US); + doneSomething.set(true); copyResource(context, module, file, sourceRoot, context.getDataManager().getSourceToOutputMap(moduleName, context.isCompilingTests())); } catch (IOException e) { @@ -56,7 +59,7 @@ public class ResourcesBuilder extends ModuleLevelBuilder { } }); - return ExitCode.OK; + return doneSomething.get()? ExitCode.OK : ExitCode.NOTHING_DONE; } catch (Exception e) { throw new ProjectBuildException(e.getMessage(), e); diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java index 75a3e7cb6e1d..136f07ce4798 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerClient.java @@ -2,31 +2,22 @@ package org.jetbrains.jps.javac; import org.jboss.netty.channel.MessageEvent; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.api.AsyncTaskExecutor; import org.jetbrains.jps.api.RequestFuture; +import org.jetbrains.jps.api.SharedThreadPool; import org.jetbrains.jps.client.SimpleProtobufClient; import org.jetbrains.jps.client.UUIDGetter; import java.io.File; import java.util.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; /** * @author Eugene Zhuravlev * Date: 1/22/12 */ public class JavacServerClient extends SimpleProtobufClient{ - private static final ExecutorService ourExecutors = Executors.newCachedThreadPool(); - private static final AsyncTaskExecutor ASYNC_EXEC = new AsyncTaskExecutor() { - @Override - public void submit(Runnable runnable) { - ourExecutors.submit(runnable); - } - }; public JavacServerClient() { - super(JavacRemoteProto.Message.getDefaultInstance(), ASYNC_EXEC, new UUIDGetter() { + super(JavacRemoteProto.Message.getDefaultInstance(), SharedThreadPool.ASYNC_EXEC, new UUIDGetter() { @NotNull public UUID getSessionUUID(@NotNull MessageEvent e) { final JavacRemoteProto.Message message = (JavacRemoteProto.Message)e.getMessage(); diff --git a/platform/icons/src/process/fs/step_1.png b/platform/icons/src/process/fs/step_1.png index a02f0d104b39..eb6c407124be 100644 Binary files a/platform/icons/src/process/fs/step_1.png and b/platform/icons/src/process/fs/step_1.png differ diff --git a/platform/icons/src/process/fs/step_10.png b/platform/icons/src/process/fs/step_10.png index b6bfb992ece4..39aed3098195 100644 Binary files a/platform/icons/src/process/fs/step_10.png and b/platform/icons/src/process/fs/step_10.png differ diff --git a/platform/icons/src/process/fs/step_11.png b/platform/icons/src/process/fs/step_11.png index a5c85de9aa18..3b5e3ac43e1a 100644 Binary files a/platform/icons/src/process/fs/step_11.png and b/platform/icons/src/process/fs/step_11.png differ diff --git a/platform/icons/src/process/fs/step_12.png b/platform/icons/src/process/fs/step_12.png index fe7462e4093e..31c891386732 100644 Binary files a/platform/icons/src/process/fs/step_12.png and b/platform/icons/src/process/fs/step_12.png differ diff --git a/platform/icons/src/process/fs/step_13.png b/platform/icons/src/process/fs/step_13.png index 29ee72483188..02210fd7087f 100644 Binary files a/platform/icons/src/process/fs/step_13.png and b/platform/icons/src/process/fs/step_13.png differ diff --git a/platform/icons/src/process/fs/step_14.png b/platform/icons/src/process/fs/step_14.png index 83adfde6df2a..35e5608db548 100644 Binary files a/platform/icons/src/process/fs/step_14.png and b/platform/icons/src/process/fs/step_14.png differ diff --git a/platform/icons/src/process/fs/step_15.png b/platform/icons/src/process/fs/step_15.png index dd7c72f16c71..96456a5122a6 100644 Binary files a/platform/icons/src/process/fs/step_15.png and b/platform/icons/src/process/fs/step_15.png differ diff --git a/platform/icons/src/process/fs/step_16.png b/platform/icons/src/process/fs/step_16.png index a8628ed26f60..36be132b3918 100644 Binary files a/platform/icons/src/process/fs/step_16.png and b/platform/icons/src/process/fs/step_16.png differ diff --git a/platform/icons/src/process/fs/step_17.png b/platform/icons/src/process/fs/step_17.png index 3184821bf5dc..bf4f3b9ec5b8 100644 Binary files a/platform/icons/src/process/fs/step_17.png and b/platform/icons/src/process/fs/step_17.png differ diff --git a/platform/icons/src/process/fs/step_18.png b/platform/icons/src/process/fs/step_18.png index ba0cb9b6147f..233501cadb81 100644 Binary files a/platform/icons/src/process/fs/step_18.png and b/platform/icons/src/process/fs/step_18.png differ diff --git a/platform/icons/src/process/fs/step_2.png b/platform/icons/src/process/fs/step_2.png index 116c7739306a..6c0aa8bb802f 100644 Binary files a/platform/icons/src/process/fs/step_2.png and b/platform/icons/src/process/fs/step_2.png differ diff --git a/platform/icons/src/process/fs/step_3.png b/platform/icons/src/process/fs/step_3.png index dfd20857736b..bd3ed3da1858 100644 Binary files a/platform/icons/src/process/fs/step_3.png and b/platform/icons/src/process/fs/step_3.png differ diff --git a/platform/icons/src/process/fs/step_4.png b/platform/icons/src/process/fs/step_4.png index a237bd9c4a91..c7b463f0662e 100644 Binary files a/platform/icons/src/process/fs/step_4.png and b/platform/icons/src/process/fs/step_4.png differ diff --git a/platform/icons/src/process/fs/step_5.png b/platform/icons/src/process/fs/step_5.png index a9793e2aa4fc..a58da6614372 100644 Binary files a/platform/icons/src/process/fs/step_5.png and b/platform/icons/src/process/fs/step_5.png differ diff --git a/platform/icons/src/process/fs/step_6.png b/platform/icons/src/process/fs/step_6.png index 3c7b285e2e5b..3838816d288f 100644 Binary files a/platform/icons/src/process/fs/step_6.png and b/platform/icons/src/process/fs/step_6.png differ diff --git a/platform/icons/src/process/fs/step_7.png b/platform/icons/src/process/fs/step_7.png index 103ba21a4677..aeef1d044d40 100644 Binary files a/platform/icons/src/process/fs/step_7.png and b/platform/icons/src/process/fs/step_7.png differ diff --git a/platform/icons/src/process/fs/step_8.png b/platform/icons/src/process/fs/step_8.png index 03898c63b27a..06d4602e9071 100644 Binary files a/platform/icons/src/process/fs/step_8.png and b/platform/icons/src/process/fs/step_8.png differ diff --git a/platform/icons/src/process/fs/step_9.png b/platform/icons/src/process/fs/step_9.png index 10c777aca3c0..c4a3766def38 100644 Binary files a/platform/icons/src/process/fs/step_9.png and b/platform/icons/src/process/fs/step_9.png differ diff --git a/platform/icons/src/process/fs/step_mask.png b/platform/icons/src/process/fs/step_mask.png index 1a95fada3d49..5411860022fe 100644 Binary files a/platform/icons/src/process/fs/step_mask.png and b/platform/icons/src/process/fs/step_mask.png differ diff --git a/platform/icons/src/process/fs/step_passive.png b/platform/icons/src/process/fs/step_passive.png index e1d490fdbbeb..70d281bbc1b6 100644 Binary files a/platform/icons/src/process/fs/step_passive.png and b/platform/icons/src/process/fs/step_passive.png differ diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerInfo.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerInfo.java index c944eec2ffb4..454e396c268a 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerInfo.java +++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerInfo.java @@ -35,7 +35,7 @@ import java.awt.event.MouseEvent; import java.lang.ref.WeakReference; public class LineMarkerInfo { - private final Icon myIcon; + protected final Icon myIcon; private final WeakReference elementRef; public final int startOffset; public final int endOffset; @@ -157,7 +157,7 @@ public class LineMarkerInfo { return myInfo.myIconAlignment; } - private boolean looksTheSameAs(@NotNull LineMarkerGutterIconRenderer renderer) { + protected boolean looksTheSameAs(@NotNull LineMarkerGutterIconRenderer renderer) { return myInfo.getElement() != null && renderer.myInfo.getElement() != null && diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java index 9889bdf263a8..55ce601e8943 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java +++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java @@ -60,4 +60,27 @@ public class RelatedItemLineMarkerInfo extends LineMarkerI public Collection createGotoRelatedItems() { return myTargets.getValue(); } + + @Override + public GutterIconRenderer createGutterRenderer() { + if (myIcon == null) return null; + return new RelatedItemLineMarkerGutterIconRenderer(this); + } + + private static class RelatedItemLineMarkerGutterIconRenderer extends LineMarkerGutterIconRenderer { + public RelatedItemLineMarkerGutterIconRenderer(final RelatedItemLineMarkerInfo markerInfo) { + super(markerInfo); + } + + @Override + protected boolean looksTheSameAs(@NotNull LineMarkerGutterIconRenderer renderer) { + if (!(renderer instanceof RelatedItemLineMarkerGutterIconRenderer) || !super.looksTheSameAs(renderer)) { + return false; + } + + final RelatedItemLineMarkerInfo markerInfo = (RelatedItemLineMarkerInfo)getLineMarkerInfo(); + final RelatedItemLineMarkerInfo otherInfo = (RelatedItemLineMarkerInfo)renderer.getLineMarkerInfo(); + return markerInfo.myTargets.equals(otherInfo.myTargets); + } + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java index 4b65a2c9716c..d2a99b30e253 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -379,7 +379,7 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser // Algorithm: the main idea is to process the first line of the pasted block, adjust its indent if necessary, calculate indent // adjustment string and apply to each line of the pasted block starting from the second one. // - // We differentiate three possible states here: + // We differentiate the following possible states here: // --- pasted block doesn't start new line, i.e. there are non-white space symbols before it at the first line. // Example: // old content [pasted line 1 @@ -460,7 +460,7 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser final int i = CharArrayUtil.shiftBackward(chars, startOffset - 1, " \t"); - // Handle situation when pasted block doesn't start new line. + // Handle a situation when pasted block doesn't start a new line. if (chars.charAt(startOffset) != '\n' && i > 0 && chars.charAt(i) != '\n') { int firstNonWsOffset = CharArrayUtil.shiftForward(chars, firstLineStart, " \t"); if (firstNonWsOffset > firstLineStart) { @@ -550,7 +550,7 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser } } else { - CharSequence toInsert = chars.subSequence(anchorLineStart, j + diff); + CharSequence toInsert = chars.subSequence(anchorLineStart, diff + startOffset); for (int line = anchorLine + 1; line <= lastLine; line++) { document.insertString(document.getLineStartOffset(line), toInsert); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java index d87e82a67b38..a233872b8e6c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java @@ -131,7 +131,6 @@ class MoverWrapper { } }); } - CodeFoldingManager.getInstance(project).allowFoldingOnCaretLine(editor); if (hasSelection) { restoreSelection(editor, selectionStart, selectionEnd, start, myInfo.range2.getStartOffset()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java index be52c03fed31..7c9ed482d819 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java @@ -50,14 +50,4 @@ public abstract class CodeFoldingManager { public abstract void releaseFoldings(Editor editor); public abstract void buildInitialFoldings(Editor editor); - - /** - * Asks do not perform automatic expansion of fold region that is located on the caret line during the next fold regions update. - *

- * This method is necessary because fold regions that are located on caret line are automatically expanded to prevent problem - * from IDEA-64687. However, we don't want such an expansion when we, for example, move method up or down. - * - * @param editor target editor - */ - public abstract void allowFoldingOnCaretLine(@NotNull Editor editor); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java index f2008c380b8f..74c83d50d8cb 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java @@ -331,9 +331,4 @@ public class CodeFoldingManagerImpl extends CodeFoldingManager implements Projec document.putUserData(FOLDING_STATE_INFO_IN_DOCUMENT_KEY, null); } } - - @Override - public void allowFoldingOnCaretLine(@NotNull Editor editor) { - editor.putUserData(UpdateFoldRegionsOperation.ALLOW_FOLDING_ON_CARET_LINE_KEY, true); - } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java index e2e051772a6c..3ad2f94584a3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java @@ -18,14 +18,12 @@ package com.intellij.codeInsight.folding.impl; import com.intellij.lang.folding.FoldingDescriptor; import com.intellij.lang.injection.InjectedLanguageManager; -import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.FoldRegion; import com.intellij.openapi.editor.FoldingGroup; import com.intellij.openapi.editor.ex.FoldingModelEx; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -43,9 +41,6 @@ import static com.intellij.util.containers.CollectionFactory.newTroveMap; * @author cdr */ class UpdateFoldRegionsOperation implements Runnable { - - static final Key ALLOW_FOLDING_ON_CARET_LINE_KEY = Key.create("AllowFoldingOnCaretLine.KEY"); - private final Project myProject; private final Editor myEditor; private final PsiFile myFile; @@ -80,9 +75,6 @@ class UpdateFoldRegionsOperation implements Runnable { List newRegions = addNewRegions(info, foldingModel, rangeToExpandStatusMap, shouldExpand, groupExpand); applyExpandStatus(newRegions, shouldExpand, groupExpand); - - // Reset the key. - myEditor.putUserData(ALLOW_FOLDING_ON_CARET_LINE_KEY, false); } private static void applyExpandStatus(@NotNull List newRegions, @@ -147,24 +139,9 @@ class UpdateFoldRegionsOperation implements Runnable { // Considering that this code is executed only on initial fold regions construction on editor opening. return !FoldingPolicy.isCollapseByDefault(element); } - boolean caretInside; - if (myEditor.getUserData(ALLOW_FOLDING_ON_CARET_LINE_KEY) == Boolean.TRUE) { - caretInside = FoldingUtil.caretInsideRange(myEditor, range); - } - else { - final Document document = myEditor.getDocument(); - final int firstLine = document.getLineNumber(range.getStartOffset()); - final int lastLine = document.getLineNumber(range.getEndOffset()); - int caretOffset = myEditor.getCaretModel().getOffset(); - if (caretOffset > myEditor.getDocument().getTextLength()) { - return false; - } - final int currentLine = document.getLineNumber(caretOffset); - caretInside = firstLine <= currentLine && currentLine <= lastLine; - } final Boolean oldStatus = rangeToExpandStatusMap.get(range); - return oldStatus == null || caretInside || oldStatus.booleanValue(); + return oldStatus == null || FoldingUtil.caretInsideRange(myEditor, range) || oldStatus.booleanValue(); } private void removeInvalidRegions(@NotNull EditorFoldingInfo info, diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java index d6febddfd9e2..1f6f52be9fb4 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java @@ -206,6 +206,10 @@ public class GlobalInspectionContextImpl extends UserDataHolderBase implements G myContent.setDisposer(myView); + ContentManager contentManager = getContentManager(); + contentManager.addContent(myContent); + contentManager.setSelectedContent(myContent); + ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.INSPECTION).activate(null); } diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java index 1be5c6ccf3c9..71b22aef2b5c 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -95,6 +95,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { private final JPanel myPanel = new JPanel(new MyLayout()); private String myTitle; + @Nullable private String myPrompt = "> "; private final LightVirtualFile myHistoryFile; private Editor myCurrentEditor; @@ -316,11 +317,12 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { return myHistoryFile; } + @Nullable public String getPrompt() { return myPrompt; } - public void setPrompt(String prompt) { + public void setPrompt(@Nullable String prompt) { // always add space to the prompt otherwise it may look ugly myPrompt = prompt != null && !prompt.endsWith(" ") ? prompt + " " : prompt; setPromptInner(myPrompt); @@ -435,8 +437,10 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { protected String addTextRangeToHistory(TextRange textRange, final EditorEx consoleEditor, boolean preserveMarkup) { final Document history = myHistoryViewer.getDocument(); final MarkupModel markupModel = DocumentMarkupModel.forDocument(history, myProject, true); - appendToHistoryDocument(history, myPrompt); - markupModel.addRangeHighlighter(history.getTextLength() - myPrompt.length(), history.getTextLength(), HighlighterLayer.SYNTAX, + if (myPrompt != null) { + appendToHistoryDocument(history, myPrompt); + } + markupModel.addRangeHighlighter(history.getTextLength() - StringUtil.length(myPrompt), history.getTextLength(), HighlighterLayer.SYNTAX, ConsoleViewContentType.USER_INPUT.getAttributes(), HighlighterTargetArea.EXACT_RANGE); diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java index 660eedc034a7..0b47d69e55ef 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -18,7 +18,6 @@ package com.intellij.formatting; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileType; @@ -34,7 +33,6 @@ import com.intellij.psi.formatter.PsiBasedFormattingModel; import com.intellij.util.IncorrectOperationException; import com.intellij.util.SequentialTask; import com.intellij.util.text.CharArrayUtil; -import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -98,7 +96,7 @@ public class FormatterImpl extends FormatterEx @Override public void setProgressTask(@NotNull FormattingProgressTask progressIndicator) { - if (!FormatterUtil.FORMATTER_ACTION_NAMES.contains(CommandProcessor.getInstance().getCurrentCommandName())) { + if (!FormatterUtil.isFormatterCalledExplicitly()) { return; } myProgressTask.set(progressIndicator); @@ -694,7 +692,7 @@ public class FormatterImpl extends FormatterEx final boolean keepLineBreaksFlag, final int keepLineBreaks, final boolean keepFirstColumn, int prefLineFeeds) { - synchronized(this) { + synchronized(ourSharedSpacing) { ourSharedSpacing.init(minSpaces, maxSpaces, minLineFeeds, readOnly, safe, keepLineBreaksFlag, keepLineBreaks, keepFirstColumn, prefLineFeeds); SpacingImpl spacing = ourSharedProperties.get(ourSharedSpacing); diff --git a/platform/lang-impl/src/com/intellij/openapi/module/impl/scopes/LibraryRuntimeClasspathScope.java b/platform/lang-impl/src/com/intellij/openapi/module/impl/scopes/LibraryRuntimeClasspathScope.java index dbbbacc90f1d..90ad86b3980b 100644 --- a/platform/lang-impl/src/com/intellij/openapi/module/impl/scopes/LibraryRuntimeClasspathScope.java +++ b/platform/lang-impl/src/com/intellij/openapi/module/impl/scopes/LibraryRuntimeClasspathScope.java @@ -29,6 +29,7 @@ import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -39,11 +40,9 @@ import java.util.Set; public class LibraryRuntimeClasspathScope extends GlobalSearchScope { private final ProjectFileIndex myIndex; private final LinkedHashSet myEntries = new LinkedHashSet(); - private final List myModules; public LibraryRuntimeClasspathScope(final Project project, final List modules) { super(project); - myModules = modules; myIndex = ProjectRootManager.getInstance(project).getFileIndex(); final Set processedSdk = new THashSet(); final Set processedLibraries = new THashSet(); @@ -63,8 +62,14 @@ public class LibraryRuntimeClasspathScope extends GlobalSearchScope { } } + public LibraryRuntimeClasspathScope(Project project, LibraryOrderEntry entry) { + super(project); + myIndex = ProjectRootManager.getInstance(project).getFileIndex(); + Collections.addAll(myEntries, entry.getRootFiles(OrderRootType.CLASSES)); + } + public int hashCode() { - return myModules.hashCode(); + return myEntries.hashCode(); } public boolean equals(Object object) { @@ -72,7 +77,7 @@ public class LibraryRuntimeClasspathScope extends GlobalSearchScope { if (object == null || object.getClass() != LibraryRuntimeClasspathScope.class) return false; final LibraryRuntimeClasspathScope that = (LibraryRuntimeClasspathScope)object; - return that.myModules.equals(myModules); + return that.myEntries.equals(myEntries); } private void buildEntries(@NotNull final Module module, diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java b/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java index c40a94360506..12b46a4f83e9 100644 --- a/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -19,6 +19,7 @@ import com.intellij.codeInsight.actions.ReformatAndOptimizeImportsProcessor; import com.intellij.codeInsight.actions.ReformatCodeProcessor; import com.intellij.lang.ASTFactory; import com.intellij.lang.ASTNode; +import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.TokenType; @@ -292,7 +293,11 @@ public class FormatterUtil { private static ASTNode findPreviousWhiteSpace(final ASTNode leafElement, final IElementType whiteSpaceTokenType) { final int offset = leafElement.getTextRange().getStartOffset() - 1; if (offset < 0) return null; - final PsiElement found = SourceTreeToPsiMap.treeElementToPsi(leafElement).getContainingFile().findElementAt(offset); + final PsiElement psiElement = SourceTreeToPsiMap.treeElementToPsi(leafElement); + if (psiElement == null) { + return null; + } + final PsiElement found = psiElement.getContainingFile().findElementAt(offset); if (found == null) return null; final ASTNode treeElement = found.getNode(); if (treeElement != null && treeElement.getElementType() == whiteSpaceTokenType) return treeElement; @@ -357,6 +362,9 @@ public class FormatterUtil { public static void replaceLastWhiteSpace(final ASTNode astNode, final String whiteSpace, final TextRange textRange) { ASTNode lastWS = TreeUtil.findLastLeaf(astNode); + if (lastWS == null) { + return; + } if (lastWS.getElementType() != TokenType.WHITE_SPACE) { lastWS = null; } @@ -381,4 +389,11 @@ public class FormatterUtil { treeParent.replaceChild(lastWS, whiteSpaceElement); } } + + /** + * @return true explicitly called 'reformat' is in progress at the moment; false otherwise + */ + public static boolean isFormatterCalledExplicitly() { + return FORMATTER_ACTION_NAMES.contains(CommandProcessor.getInstance().getCurrentCommandName()); + } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java index d00bba8e12d7..a7c4277861f2 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java @@ -16,6 +16,7 @@ package com.intellij.psi.impl.file.impl; import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.impl.scopes.LibraryRuntimeClasspathScope; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; @@ -25,6 +26,7 @@ import com.intellij.psi.*; import com.intellij.psi.impl.PsiManagerImpl; import com.intellij.psi.impl.ResolveScopeManager; import com.intellij.psi.impl.source.resolve.FileContextUtil; +import com.intellij.psi.search.DelegatingGlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.util.containers.ConcurrentFactoryMap; @@ -91,6 +93,7 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager { List modulesLibraryUsedIn = new ArrayList(); List orderEntries = projectFileIndex.getOrderEntriesForFile(vFile); + LibraryOrderEntry lib = null; for (OrderEntry entry : orderEntries) { ProgressManager.checkCanceled(); @@ -98,12 +101,32 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager { return ((ProjectRootManagerEx)myProjectRootManager).getScopeForJdk((JdkOrderEntry)entry); } - if (entry instanceof LibraryOrderEntry || entry instanceof ModuleOrderEntry) { + if (entry instanceof LibraryOrderEntry) { + lib = (LibraryOrderEntry)entry; + modulesLibraryUsedIn.add(entry.getOwnerModule()); + } + else if (entry instanceof ModuleOrderEntry) { modulesLibraryUsedIn.add(entry.getOwnerModule()); } } - return ((ProjectRootManagerEx)myProjectRootManager).getScopeForLibraryUsedIn(modulesLibraryUsedIn); + GlobalSearchScope allCandidates = ((ProjectRootManagerEx)myProjectRootManager).getScopeForLibraryUsedIn(modulesLibraryUsedIn); + if (lib != null) { + final LibraryRuntimeClasspathScope preferred = new LibraryRuntimeClasspathScope(myProject, lib); + // prefer current library + return new DelegatingGlobalSearchScope(allCandidates, preferred) { + @Override + public int compare(VirtualFile file1, VirtualFile file2) { + boolean c1 = preferred.contains(file1); + boolean c2 = preferred.contains(file2); + if (c1 && !c2) return 1; + if (c2 && !c1) return -1; + + return super.compare(file1, file2); + } + }; + } + return allCandidates; } } diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintUtil.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintUtil.java index ef9259d2c2da..a87d71b8a9c8 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintUtil.java +++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintUtil.java @@ -33,7 +33,7 @@ import java.awt.*; public class HintUtil { public static final Color INFORMATION_COLOR = new Color(253, 254, 226); public static final Color QUESTION_COLOR = new Color(181, 208, 251); - private static final Color ERROR_COLOR = new Color(255, 220, 220); + public static final Color ERROR_COLOR = new Color(255, 220, 220); private static final Icon INFORMATION_ICON = null; private static final Icon QUESTION_ICON = IconLoader.getIcon("/actions/help.png"); @@ -91,7 +91,7 @@ public class HintUtil { } public static JComponent createInformationLabel(final SimpleColoredText text, final Icon icon) { - SimpleColoredComponent highlighted = new SimpleColoredComponent (); + SimpleColoredComponent highlighted = new SimpleColoredComponent(); highlighted.setIcon(icon); highlighted.setBackground(INFORMATION_COLOR); @@ -219,6 +219,5 @@ public class HintUtil { public String toString() { return "Hint: text='" + (myPane != null ? myPane.getText() : "") + "'"; } - } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 5c633a0048b6..697399225e26 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -32,6 +32,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; @@ -75,6 +76,8 @@ import static java.awt.event.KeyEvent.*; @SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod", "SSBasedInspection"}) public class Switcher extends AnAction implements DumbAware { private static volatile SwitcherPanel SWITCHER = null; + private static final Icon PIN_ON = IconLoader.getIcon("/general/autohideOn.png"); + private static final Icon PIN_OFF = IconLoader.getIcon("/general/autohideOff.png"); private static final Color BORDER_COLOR = Gray._135; private static final Color SEPARATOR_COLOR = BORDER_COLOR.brighter(); @NonNls private static final String SWITCHER_FEATURE_ID = "switcher"; @@ -189,7 +192,7 @@ public class Switcher extends AnAction implements DumbAware { addKeyListener(this); setBorder(new EmptyBorder(0, 0, 0, 0)); setBackground(Color.WHITE); - pathLabel.setHorizontalAlignment(SwingConstants.RIGHT); + pathLabel.setHorizontalAlignment(SwingConstants.LEFT); final Font font = pathLabel.getFont(); pathLabel.setFont(font.deriveFont((float)10)); @@ -204,7 +207,19 @@ public class Switcher extends AnAction implements DumbAware { }; descriptions.setBorder(BorderFactory.createEmptyBorder(1, 4, 1, 4)); - descriptions.add(pathLabel); + descriptions.add(pathLabel, BorderLayout.CENTER); + final JLabel pinLabel = new JLabel(isPinnedMode() ? PIN_ON : PIN_OFF); + pinLabel.setToolTipText(isPinnedMode() ? "Pinned mode" : "Floating mode"); + pinLabel.setBorder(IdeBorderFactory.createEmptyBorder(0, 10, 0, 0)); + descriptions.add(pinLabel, BorderLayout.EAST); + pinLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE = !UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE; + pinLabel.setIcon(isPinnedMode() ? PIN_ON : PIN_OFF); + pinLabel.setToolTipText(isPinnedMode() ? "Pinned mode" : "Floating mode"); + } + }); twManager = ToolWindowManager.getInstance(project); final DefaultListModel twModel = new DefaultListModel(); for (String id : twManager.getToolWindowIds()) { @@ -285,6 +300,7 @@ public class Switcher extends AnAction implements DumbAware { final VirtualFile[] recentFiles = ArrayUtil.reverseArray(EditorHistoryManager.getInstance(project).getFiles()); final int maxFiles = Math.max(editors.size(), recentFiles.length); final int len = isPinnedMode() ? maxFiles : Math.min(toolWindows.getModel().getSize(), maxFiles); + boolean firstRecentMarked = false; for (int i = 0; i < len; i++) { final FileInfo info = new FileInfo(recentFiles[i], null); boolean add = true; @@ -298,6 +314,10 @@ public class Switcher extends AnAction implements DumbAware { } if (add) { filesData.add(info); + if (!firstRecentMarked) { + firstRecentMarked = true; + info.isSeparator = true; + } } } if (editors.size() == 1 && (filesData.isEmpty() || !editors.get(0).getFirst().equals(filesData.get(0).getFirst()))) { @@ -743,6 +763,7 @@ public class Switcher extends AnAction implements DumbAware { public SwitcherSpeedSearch() { super(SwitcherPanel.this); addChangeListener(this); + setComparator(new SpeedSearchComparator(false, true)); } @Override @@ -805,6 +826,7 @@ public class Switcher extends AnAction implements DumbAware { private final Project myProject; private final SpeedSearchBase mySearch; private boolean hide = false; + private boolean separator = false; public VirtualFilesRenderer(Project project, SpeedSearchBase search) { myProject = project; @@ -817,10 +839,12 @@ public class Switcher extends AnAction implements DumbAware { final VirtualFile virtualFile = ((FileInfo)value).first; final String name = virtualFile.getPresentableName(); setIcon(IconUtil.getIcon(virtualFile, Iconable.ICON_FLAG_READ_STATUS, myProject)); + separator = ((FileInfo)value).isSeparator; if ( mySearch != null && mySearch.isPopupActive()) { hide = mySearch.matchingFragments(name) == null && !StringUtil.isEmpty(mySearch.getEnteredPrefix()); } + final FileStatus fileStatus = FileStatusManager.getInstance(myProject).getStatus(virtualFile); final TextAttributes attributes = new TextAttributes(fileStatus.getColor(), null, null, EffectType.LINE_UNDERSCORE, Font.PLAIN); append(name, SimpleTextAttributes.fromTextAttributes(attributes)); @@ -835,10 +859,14 @@ public class Switcher extends AnAction implements DumbAware { } super.doPaint(g); config.restore(); + if (separator) { + UIUtil.drawDottedLine(g, 0, 0, getWidth(), 0, Color.WHITE, Color.BLACK); + } } } private static class FileInfo extends Pair { + boolean isSeparator = false; public FileInfo(VirtualFile first, EditorWindow second) { super(first, second); } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java b/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java index f1399ec5e82b..7f92920f3b53 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java @@ -36,6 +36,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Function; import com.intellij.util.net.IOExceptionDialog; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.event.HyperlinkEvent; import java.io.IOException; @@ -157,7 +158,7 @@ public class ActionInstallPlugin extends AnAction implements DumbAware { } if (needToRestart) { - notifyPluginsWereInstalled(); + notifyPluginsWereInstalled(list.size() == 1 ? list.get(0).getName() : null); } } } @@ -256,7 +257,7 @@ public class ActionInstallPlugin extends AnAction implements DumbAware { } } - private static void notifyPluginsWereInstalled() { + private static void notifyPluginsWereInstalled(@Nullable String pluginName) { final ApplicationEx app = ApplicationManagerEx.getApplicationEx(); final boolean restartCapable = app.isRestartCapable(); String message = ""; @@ -265,7 +266,8 @@ public class ActionInstallPlugin extends AnAction implements DumbAware { message += "
Restart now" : "\"shutdown\">Shutdown"; message += ""; - Notifications.Bus.notify(new Notification(IdeBundle.message("title.plugin.error"), IdeBundle.message("title.plugin.error"), + Notifications.Bus.notify(new Notification("Plugins Lifecycle Group", + pluginName != null ? "Plugin \'" + pluginName + "\' was successfully installed" : "Plugins were installed", message, NotificationType.INFORMATION, new NotificationListener() { @Override public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/DetectedPluginsPanel.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/DetectedPluginsPanel.java index b3013c4a347e..860d7c367872 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/DetectedPluginsPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/DetectedPluginsPanel.java @@ -53,15 +53,17 @@ public class DetectedPluginsPanel extends OrderPanel { final int row, final int column) { final PluginDownloader downloader = (PluginDownloader)value; - append(downloader.getPluginName(), SimpleTextAttributes.REGULAR_ATTRIBUTES); - final IdeaPluginDescriptor ideaPluginDescriptor = PluginManager.getPlugin(PluginId.getId(downloader.getPluginId())); - final String loadedVersion = downloader.getPluginVersion(); - if (loadedVersion != null || (ideaPluginDescriptor != null && ideaPluginDescriptor.getVersion() != null)) { - final String installedVersion = ideaPluginDescriptor != null && ideaPluginDescriptor.getVersion() != null - ? "v. " + ideaPluginDescriptor.getVersion() + (loadedVersion != null ? " -> " : "") - : ""; - final String availableVersion = loadedVersion != null ? loadedVersion : ""; - append(" (" + installedVersion + availableVersion + ")", SimpleTextAttributes.GRAY_ATTRIBUTES); + if (downloader != null) { + append(downloader.getPluginName(), SimpleTextAttributes.REGULAR_ATTRIBUTES); + final IdeaPluginDescriptor ideaPluginDescriptor = PluginManager.getPlugin(PluginId.getId(downloader.getPluginId())); + final String loadedVersion = downloader.getPluginVersion(); + if (loadedVersion != null || (ideaPluginDescriptor != null && ideaPluginDescriptor.getVersion() != null)) { + final String installedVersion = ideaPluginDescriptor != null && ideaPluginDescriptor.getVersion() != null + ? "v. " + ideaPluginDescriptor.getVersion() + (loadedVersion != null ? " -> " : "") + : ""; + final String availableVersion = loadedVersion != null ? loadedVersion : ""; + append(" (" + installedVersion + availableVersion + ")", SimpleTextAttributes.GRAY_ATTRIBUTES); + } } } }); diff --git a/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectDialog.form b/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectDialog.form index d7c77b76f80f..4b1d4deab6d2 100644 --- a/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectDialog.form +++ b/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectDialog.form @@ -69,7 +69,7 @@ - + diff --git a/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java index 480dc6312069..4f66a034eae0 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java @@ -30,10 +30,7 @@ import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.JarFileSystem; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.*; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; @@ -278,4 +275,26 @@ import java.util.Collection; } }.execute().throwException(); } + + public static void addLibrary(final Module module, + final String libName, final String libDir, + final String[] classRoots, + final String[] sourceRoots) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel(); + final String parentUrl = VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, libDir); + final Library library = model.getModuleLibraryTable().createLibrary(libName); + final Library.ModifiableModel libModifiableModel = library.getModifiableModel(); + for (String classRoot : classRoots) { + libModifiableModel.addRoot(parentUrl + classRoot, OrderRootType.CLASSES); + } + for (String sourceRoot : sourceRoots) { + libModifiableModel.addRoot(parentUrl + sourceRoot, OrderRootType.SOURCES); + } + libModifiableModel.commit(); + model.commit(); + } + }); + } } \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/icons/FrameLayout.png b/plugins/android-designer/src/com/intellij/android/designer/icons/FrameLayout.png new file mode 100644 index 000000000000..66bd0421cb0c Binary files /dev/null and b/plugins/android-designer/src/com/intellij/android/designer/icons/FrameLayout.png differ diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java b/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java index 707d353226c5..e87ab8732618 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java @@ -25,6 +25,7 @@ import com.intellij.android.designer.propertyTable.editors.ResourceDialog; import com.intellij.designer.model.MetaManager; import com.intellij.designer.model.MetaModel; import com.intellij.designer.model.RadComponent; +import com.intellij.designer.model.RadLayout; import com.intellij.designer.propertyTable.Property; import com.intellij.designer.propertyTable.PropertyTable; import com.intellij.openapi.module.Module; @@ -47,6 +48,10 @@ import java.util.*; public class PropertyParser { public static final String KEY = "PROPERTY_PARSER"; + private static final String[] DEFAULT_LAYOUT_PARAMS = {"ViewGroup_Layout"}; + private static final String LAYOUT_PREFIX = "layout_"; + private static final String LAYOUT_MARGIN_PREFIX = "layout_margin"; + private final Module myModule; private MetaManager myMetaManager; private AttributeDefinitions myDefinitions; @@ -90,23 +95,45 @@ public class PropertyParser { if (componentClass.getName().equals("com.android.layoutlib.bridge.MockView")) { componentClass = myClassLoader.loadClass("android.view.View"); } - component.setProperties(load(componentClass, model)); + component.setProperties(loadWidgetProperties(componentClass, model)); } } else { - component.setProperties(load(myClassLoader.loadClass(target), model)); + component.setProperties(loadWidgetProperties(myClassLoader.loadClass(target), model)); } - // TODO: load layout constrain properties + RadComponent parent = component.getParent(); + if (parent != null) { + String[] layoutParams = null; + RadLayout layout = parent.getLayout(); + + if (layout instanceof RadViewLayoutWithData) { + layoutParams = ((RadViewLayoutWithData)layout).getLayoutParams(); + } + else if (parent == parent.getRoot()) { + layoutParams = DEFAULT_LAYOUT_PARAMS; + } + + if (layoutParams != null) { + List properties = loadLayoutProperties(layoutParams, 0); + + if (!properties.isEmpty()) { + properties = new ArrayList(properties); + properties.addAll(component.getProperties()); + component.setProperties(properties); + } + } + } } - private List load(Class componentClass, MetaModel model) throws Exception { + private List loadWidgetProperties(Class componentClass, MetaModel model) throws Exception { String component = componentClass.getSimpleName(); List properties = myCachedProperties.get(component); if (properties == null) { properties = new ArrayList(); + myCachedProperties.put(component, properties); StyleableDefinition definitions = myDefinitions.getStyleableByName(component); if (definitions != null) { @@ -153,7 +180,8 @@ public class PropertyParser { superComponentClass = myClassLoader.loadClass("android.view.View"); } - List superProperties = load(superComponentClass, myMetaManager.getModelByTarget(superComponentClass.getName())); + List superProperties = loadWidgetProperties(superComponentClass, + myMetaManager.getModelByTarget(superComponentClass.getName())); for (Property superProperty : superProperties) { if (PropertyTable.findProperty(properties, superProperty) == -1) { if (model == null) { @@ -192,8 +220,79 @@ public class PropertyParser { } }); } + } + return properties; + } + + private List loadLayoutProperties(String[] components, int index) throws Exception { + String component = components[index]; + + List properties = myCachedProperties.get(component); + + if (properties == null) { + properties = new ArrayList(); myCachedProperties.put(component, properties); + + StyleableDefinition definitions = myDefinitions.getStyleableByName(component); + if (definitions != null) { + Property margin = null; + + for (AttributeDefinition definition : definitions.getAttributes()) { + String name = definition.getName(); + boolean important = true; + Set formats = definition.getFormats(); + Property property; + + if (name.startsWith(LAYOUT_MARGIN_PREFIX) && name.length() > LAYOUT_MARGIN_PREFIX.length()) { + name = name.substring(LAYOUT_PREFIX.length()); + important = false; + } + else if (name.startsWith(LAYOUT_PREFIX)) { + name = "layout:" + name.substring(LAYOUT_PREFIX.length()); + } + + if ("layout:margin".equals(name) && "ViewGroup_MarginLayout".equals(component)) { + property = margin = new CompoundProperty(name, definition); + } + else if (formats.contains(AttributeFormat.Flag)) { + property = new FlagProperty(name, definition); + } + else { + property = new AttributeProperty(name, definition); + } + + property.setImportant(important); + properties.add(property); + } + + if (margin != null) { + List children = margin.getChildren(null); + children.add(PropertyTable.extractProperty(properties, "marginLeft")); + children.add(PropertyTable.extractProperty(properties, "marginTop")); + children.add(PropertyTable.extractProperty(properties, "marginRight")); + children.add(PropertyTable.extractProperty(properties, "marginBottom")); + children.add(PropertyTable.extractProperty(properties, "marginStart")); + children.add(PropertyTable.extractProperty(properties, "marginEnd")); + } + } + + if (++index < components.length) { + for (Property property : loadLayoutProperties(components, index)) { + if (PropertyTable.findProperty(properties, property) == -1) { + properties.add(property); + } + } + } + + if (!properties.isEmpty()) { + Collections.sort(properties, new Comparator() { + @Override + public int compare(Property p1, Property p2) { + return p1.getName().compareTo(p2.getName()); + } + }); + } } return properties; diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadFrameLayout.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadFrameLayout.java new file mode 100644 index 000000000000..1f97e251d2b7 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadFrameLayout.java @@ -0,0 +1,56 @@ +/* + * 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.model; + +import com.intellij.designer.designSurface.ComponentDecorator; +import com.intellij.designer.designSurface.DesignerEditorPanel; +import com.intellij.designer.designSurface.EditOperation; +import com.intellij.designer.designSurface.OperationContext; +import com.intellij.designer.model.RadComponent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; + +import javax.swing.*; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class RadFrameLayout extends RadViewLayoutWithData { + private static final String[] LAYOUT_PARAMS = {"FrameLayout_Layout", "ViewGroup_MarginLayout"}; + + @Override + public String[] getLayoutParams() { + return LAYOUT_PARAMS; + } + + @Override + public ComponentDecorator getChildSelectionDecorator(RadComponent component, List selection) { + return super.getChildSelectionDecorator(component, selection); // TODO: Auto-generated method stub + } + + @Override + public EditOperation processChildOperation(OperationContext context) { + return super.processChildOperation(context); // TODO: Auto-generated method stub + } + + @Override + public void addSelectionActions(DesignerEditorPanel designer, + DefaultActionGroup actionGroup, + JComponent shortcuts, + List selection) { + super.addSelectionActions(designer, actionGroup, shortcuts, selection); // TODO: Auto-generated method stub + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java index e6cbf4533c44..19e04a31053a 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java @@ -30,7 +30,14 @@ import java.util.List; /** * @author Alexander Lobas */ -public class RadLinearLayout extends RadViewLayout { +public class RadLinearLayout extends RadViewLayoutWithData { + private static final String[] LAYOUT_PARAMS = {"LinearLayout_Layout", "ViewGroup_MarginLayout"}; + + @Override + public String[] getLayoutParams() { + return LAYOUT_PARAMS; + } + @Override public EditOperation processChildOperation(OperationContext context) { if (context.isCreate()) { diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewGroupComponent.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewGroupComponent.java new file mode 100644 index 000000000000..af4d30984129 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewGroupComponent.java @@ -0,0 +1,36 @@ +/* + * 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.model; + +import com.intellij.designer.designSurface.DesignerEditorPanel; +import com.intellij.designer.model.RadComponent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; + +import javax.swing.*; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class RadViewGroupComponent extends RadViewComponent { + @Override + public void addSelectionActions(DesignerEditorPanel designer, + DefaultActionGroup actionGroup, + JComponent shortcuts, + List selection) { + super.addSelectionActions(designer, actionGroup, shortcuts, selection); // TODO: Auto-generated method stub + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayoutWithData.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayoutWithData.java new file mode 100644 index 000000000000..ca1af9c2692d --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewLayoutWithData.java @@ -0,0 +1,23 @@ +/* + * 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.model; + +/** + * @author Alexander Lobas + */ +public abstract class RadViewLayoutWithData extends RadViewLayout { + public abstract String[] getLayoutParams(); +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml b/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml index 0d9f8e077767..a91e9ba6d1cd 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml +++ b/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml @@ -983,7 +983,7 @@ - @@ -1004,6 +1004,26 @@ + + + + + + + + + + ]]> + + + @@ -1061,6 +1081,7 @@ + diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidLibraryPackagingBuilder.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidLibraryPackagingBuilder.java index 0720446f5288..827e177c5930 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidLibraryPackagingBuilder.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidLibraryPackagingBuilder.java @@ -30,9 +30,9 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder { } @Override - public ModuleLevelBuilder.ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { + public ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { if (context.isCompilingTests() || !AndroidJpsUtil.containsAndroidFacet(chunk) || AndroidJpsUtil.isLightBuild(context)) { - return ModuleLevelBuilder.ExitCode.OK; + return ExitCode.NOTHING_DONE; } try { @@ -48,6 +48,7 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder { final AndroidFileSetStorage storage = new AndroidFileSetStorage(context.getDataManager().getDataStorageRoot(), "libs_packaging"); try { + boolean doneSomething = false; for (Module module : chunk.getModules()) { final AndroidFacet facet = AndroidJpsUtil.getFacet(module); if (facet == null || !facet.isLibrary()) { @@ -82,7 +83,7 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder { if (subdirs.size() > 0) { context.processMessage(new ProgressMessage(AndroidJpsBundle.message("android.jps.progress.library.packaging", module.getName()))); final File outputJarFile = new File(outputDirectoryForPackagedFiles, AndroidCommonUtils.CLASSES_JAR_FILE_NAME); - + doneSomething = true; try { AndroidCommonUtils.packClassFilesIntoJar(ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.toStringArray(subdirs), outputJarFile); storage.update(module.getName(), newState); @@ -94,7 +95,7 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder { } } } - return success ? ModuleLevelBuilder.ExitCode.OK : ModuleLevelBuilder.ExitCode.ABORT; + return success ? (doneSomething? ExitCode.OK : ExitCode.NOTHING_DONE) : ExitCode.ABORT; } finally { storage.close(); diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java index c3f8d80ef2cd..e9ef804f1eef 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java @@ -61,7 +61,7 @@ public class AndroidSourceGeneratingBuilder extends ModuleLevelBuilder { @Override public ModuleLevelBuilder.ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException { if (context.isCompilingTests() || !AndroidJpsUtil.containsAndroidFacet(chunk)) { - return ModuleLevelBuilder.ExitCode.OK; + return ExitCode.NOTHING_DONE; } try { diff --git a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java index 05dfc5829a4b..d7972ddbb3fc 100644 --- a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java +++ b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseLibrariesModificationsTest.java @@ -30,6 +30,7 @@ import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.testFramework.PsiTestUtil; import com.intellij.util.ArrayUtil; public class EclipseLibrariesModificationsTest extends EclipseVarsTest { @@ -38,22 +39,8 @@ public class EclipseLibrariesModificationsTest extends EclipseVarsTest { final Project project = getProject(); final String path = project.getBaseDir().getPath() + "/test"; final Module module = EclipseClasspathTest.setUpModule(path, project); - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel(); - final String parentUrl = VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, model.getContentRoots()[0].getParent().getPath()); - final Library library = model.getModuleLibraryTable().createLibrary("created"); - final Library.ModifiableModel libModifiableModel = library.getModifiableModel(); - for (String classRoot : classRoots) { - libModifiableModel.addRoot(parentUrl + classRoot, OrderRootType.CLASSES); - } - for (String sourceRoot : sourceRoots) { - libModifiableModel.addRoot(parentUrl + sourceRoot, OrderRootType.SOURCES); - } - libModifiableModel.commit(); - model.commit(); - } - }); + PsiTestUtil.addLibrary(module, "created", ModuleRootManager.getInstance(module).getContentRoots()[0].getParent().getPath(), classRoots, + sourceRoots); EclipseClasspathTest.checkModule(project.getBaseDir().getPath() + "/expected", module); } diff --git a/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java index 2c6a41287403..0852f2e8fdfe 100644 --- a/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java +++ b/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java @@ -49,7 +49,7 @@ public class GroovyBuilder extends ModuleLevelBuilder { try { final List toCompile = collectChangedFiles(context, chunk); if (toCompile.isEmpty()) { - return ExitCode.OK; + return ExitCode.NOTHING_DONE; } String moduleOutput = getModuleOutput(context, chunk); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java index f695d0ebe0d8..b77bd7c933fc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.folding; import com.intellij.codeInsight.folding.JavaCodeFoldingSettings; +import com.intellij.codeInsight.folding.impl.JavaFoldingBuilder; import com.intellij.lang.ASTNode; import com.intellij.lang.folding.CustomFoldingBuilder; import com.intellij.lang.folding.FoldingDescriptor; @@ -194,7 +195,7 @@ public class GroovyFoldingBuilder extends CustomFoldingBuilder implements Groovy int start = first.getTextRange().getStartOffset(); int end = marker.getTextRange().getEndOffset(); int tail = "import ".length(); - if (start + tail < end) { + if (start + tail < end && !JavaFoldingBuilder.hasErrorElementsNearby(first.getContainingFile(), start, end)) { descriptors.add(new FoldingDescriptor(first.getNode(), new TextRange(start + tail, end))); } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFoldingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFoldingTest.groovy index 04ee1eab49e1..7df5c8c1830e 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFoldingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFoldingTest.groovy @@ -47,6 +47,25 @@ class GroovyFoldingTest extends LightCodeInsightFixtureTestCase { assert assertNoFolding(myFixture.file.text.indexOf(marker)), marker } + public void testEditingImports() { + configure """ +import java.util.List +import java.util.Map + + +println 'hello' + +class Foo { List a; Map b; } +""" + + assert myFixture.editor.foldingModel.getCollapsedRegionAtOffset(10) + + myFixture.type 'import ' + myFixture.doHighlighting() + assert !myFixture.editor.foldingModel.getCollapsedRegionAtOffset(10) + } + + void testOpenBlock() { configure '''def foo() {print 'a'} def bar() { diff --git a/plugins/junit/src/com/intellij/execution/junit/TestObject.java b/plugins/junit/src/com/intellij/execution/junit/TestObject.java index 7ef35d90713f..6942a997b0b9 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestObject.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestObject.java @@ -252,7 +252,7 @@ public abstract class TestObject implements JavaCommandLine { @Override public ExecutionResult execute(final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException { - final JUnitProcessHandler handler = createHandler(); + final JUnitProcessHandler handler = createHandler(executor); final RunnerSettings runnerSettings = getRunnerSettings(); JavaRunConfigurationExtensionManager.getInstance().attachExtensionsToProcess(myConfiguration, handler, runnerSettings); final TestProxy unboundOutputRoot = new TestProxy(new RootTestInfo()); @@ -360,19 +360,20 @@ public abstract class TestObject implements JavaCommandLine { TestsUIUtil.notifyByBalloon(myProject, model != null ? model.getRoot() : null, consoleProperties); } - protected JUnitProcessHandler createHandler() throws ExecutionException { - appendForkInfo(); + protected JUnitProcessHandler createHandler(Executor executor) throws ExecutionException { + appendForkInfo(executor); return JUnitProcessHandler.runCommandLine(CommandLineBuilder.createFromJavaParameters(myJavaParameters, myProject, true)); } - private void appendForkInfo() throws ExecutionException { + private void appendForkInfo(Executor executor) throws ExecutionException { final String forkMode = myConfiguration.getForkMode(); if (Comparing.strEqual(forkMode, "none")) { return; } - if (myRunnerSettings.getData() instanceof DebuggingRunnerData) { - throw new CantRunException("Debug is disabled in fork mode.
Please change fork mode to <none> to debug."); + if (myRunnerSettings.getData() != null) { + final String actionName = executor.getActionName(); + throw new CantRunException(actionName + " is disabled in fork mode.
Please change fork mode to <none> to " + actionName.toLowerCase() + "."); } final JavaParameters javaParameters = getJavaParameters(); diff --git a/plugins/junit/src/com/intellij/execution/junit/TestPackage.java b/plugins/junit/src/com/intellij/execution/junit/TestPackage.java index b4460ea4d7b9..2bb70b12c018 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestPackage.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestPackage.java @@ -87,8 +87,8 @@ public class TestPackage extends TestObject { } @Override - protected JUnitProcessHandler createHandler() throws ExecutionException { - final JUnitProcessHandler handler = super.createHandler(); + protected JUnitProcessHandler createHandler(Executor executor) throws ExecutionException { + final JUnitProcessHandler handler = super.createHandler(executor); final SearchForTestsTask[] tasks = new SearchForTestsTask[1]; handler.addProcessListener(new ProcessAdapter() { @Override diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java index fc75268f3598..9f65a8138aeb 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java @@ -17,7 +17,6 @@ package com.intellij.junit4; import org.junit.Ignore; import org.junit.internal.AssumptionViolatedException; -import org.junit.internal.builders.JUnit3Builder; import org.junit.internal.requests.ClassRequest; import org.junit.internal.runners.model.EachTestNotifier; import org.junit.runner.Description; @@ -151,7 +150,7 @@ public class JUnit4TestRunnerUtil { } try { if (clazz.getMethod("suite", new Class[0]) != null && !methodName.equals("suite")) { - return Request.runner(new JUnit3Builder().runnerForClass(clazz)).filterWith(Description.createTestDescription(clazz, methodName)); + return Request.classWithoutSuiteMethod(clazz).filterWith(Description.createTestDescription(clazz, methodName)); } } catch (Throwable e) { diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java index aa34ea474344..211cf736ca95 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java @@ -21,6 +21,8 @@ import com.intellij.psi.PsiReference; import org.jetbrains.idea.maven.indices.MavenIndicesTestFixture; import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; public class MavenExtensionCompletionAndResolutionTest extends MavenDomWithIndicesTestCase { @@ -70,10 +72,11 @@ public class MavenExtensionCompletionAndResolutionTest extends MavenDomWithIndic List actual = getCompletionVariants(myProjectPom); - if (actual.isEmpty()) { + if (!new HashSet(actual).equals(new HashSet(Arrays.asList("maven-compiler-plugin", "maven-war-plugin", "maven-eclipse-plugin", "maven-surefire-plugin")))) { MavenProjectIndicesManager instance = MavenProjectIndicesManager.getInstance(myProject); System.out.println("GetArtifacts: " + instance.getArtifactIds("org.apache.maven.plugins")); System.out.println("Indexes: " + instance.getIndices()); + throw new AssertionError("GetArtifacts: " + instance.getArtifactIds("org.apache.maven.plugins") + "Indexes: " + instance.getIndices()); } assertUnorderedElementsAreEqual(actual, "maven-compiler-plugin", "maven-war-plugin", "maven-eclipse-plugin", "maven-surefire-plugin"); diff --git a/resources-en/src/messages/DebuggerBundle.properties b/resources-en/src/messages/DebuggerBundle.properties index 1a51ab4d3574..508ae6ee32c8 100644 --- a/resources-en/src/messages/DebuggerBundle.properties +++ b/resources-en/src/messages/DebuggerBundle.properties @@ -164,6 +164,7 @@ error.exception.while.reloading=Exception while reloading classes : {0} : {1} status.hotswap.loaded.classes.up.to.date=Loaded classes are up to date. Nothing to reload error.io.error=I/O error status.classes.reloaded={0,number} {0,choice, 0#classes|1#class|2#classes} reloaded +status.classes.not.all.versions.reloaded=For {0} of {1} {1,choice, 1#class|2#classes} not all versions were reloaded error.cannot.create.void.value=Cannot create void value warning.range.too.big=Range specified is too big. {0} needs too much resources to perform requested operation. Are you sure you want to continue? title.range.too.big=Range is Too Big diff --git a/xml/impl/src/com/intellij/xml/util/InclusionProvider.java b/xml/impl/src/com/intellij/xml/util/InclusionProvider.java index d53f251bd356..9f637d59a193 100644 --- a/xml/impl/src/com/intellij/xml/util/InclusionProvider.java +++ b/xml/impl/src/com/intellij/xml/util/InclusionProvider.java @@ -17,13 +17,11 @@ package com.intellij.xml.util; import com.intellij.openapi.util.NullableComputable; import com.intellij.openapi.util.RecursionManager; -import com.intellij.psi.PsiAnchor; import com.intellij.psi.PsiElement; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.xml.XmlDocument; -import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.intellij.util.xmlb.JDOMXIncluder; @@ -82,12 +80,7 @@ class InclusionProvider implements CachedValueProvider { final XmlTag[] includeTag = extractXpointer(rootTag, xpointer); PsiElement[] result = new PsiElement[includeTag.length]; for (int i = 0; i < includeTag.length; i++) { - XmlTag xmlTag = includeTag[i]; - final PsiElement psiElement = xmlTag.copy(); - psiElement.putUserData(XmlElement.INCLUDING_ELEMENT, xincludeTag.getParentTag()); - psiElement.putUserData(XmlUtil.ORIGINAL_ELEMENT, PsiAnchor.create(xmlTag)); - result[i] = psiElement; - //result[i] = new IncludedXmlTag(includeTag[i], xincludeTag.getParentTag()); + result[i] = new IncludedXmlTag(includeTag[i], xincludeTag.getParentTag()); } return result; }