diff --git a/community-resources/src/idea_community_logo.png b/community-resources/src/idea_community_logo.png index c475940f4207..3a253badbb8a 100644 Binary files a/community-resources/src/idea_community_logo.png and b/community-resources/src/idea_community_logo.png differ diff --git a/community-resources/src/idea_community_logo@2x.png b/community-resources/src/idea_community_logo@2x.png index 72e127cdf224..7033b174c7b3 100644 Binary files a/community-resources/src/idea_community_logo@2x.png and b/community-resources/src/idea_community_logo@2x.png differ diff --git a/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java b/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java index 2cd375d23d2a..fc2547da6aa1 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java @@ -82,7 +82,7 @@ import java.util.List; * @author anna * @since 26-Jun-2007 */ -public class ExternalAnnotationsManagerImpl extends BaseExternalAnnotationsManager { +public class ExternalAnnotationsManagerImpl extends ReadableExternalAnnotationsManager { private static final Logger LOG = Logger.getInstance("#" + ExternalAnnotationsManagerImpl.class.getName()); private final MessageBus myBus; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java index 99dbcff4bbba..f7ed8a842e13 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java @@ -625,10 +625,8 @@ public class JavaCompletionData extends JavaAwareCompletionData { afterNew || expressionPosition || isStatementPosition(position)) { - boolean needSpace = !inCast && !typeFragment && !expressionPosition && !inGenerics && !afterNew; for (String primitiveType : PRIMITIVE_TYPES) { - LookupElement keyword = createKeyword(position, primitiveType); - result.addElement(needSpace ? new OverrideableSpace(keyword, TailType.HUMBLE_SPACE_BEFORE_WORD) : keyword); + result.addElement(createKeyword(position, primitiveType)); } } if (declaration) { diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index fe2fa2d95a20..96308387a030 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -1558,7 +1558,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { return myFactory.getVarFactory().createVariableValue(var, refExpr.getType(), false, null, isCall); } - if (var instanceof PsiField && var.hasModifierProperty(PsiModifier.FINAL)) { + if (DfaVariableState.isFinalField(var)) { DfaVariableValue qualifierValue = createChainedVariableValue(qualifier); if (qualifierValue != null) { return myFactory.getVarFactory().createVariableValue(var, refExpr.getType(), false, qualifierValue, isCall || qualifierValue.isViaMethods()); diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java index 6c4dc24227f5..fb3cc7de72b1 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java @@ -790,7 +790,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState { public void flushVariable(@NotNull DfaVariableValue variable) { PsiVariable psiVariable = variable.getPsiVariable(); - if (psiVariable instanceof PsiField && psiVariable.hasModifierProperty(PsiModifier.FINAL)) { + if (DfaVariableState.isFinalField(psiVariable)) { return; } diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java index 432ac81a50d9..ad6e89208148 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java @@ -63,7 +63,7 @@ public class DfaVariableState implements Cloneable { } private static boolean isNullableInitialized(PsiVariable var, boolean nullable) { - if (!var.hasModifierProperty(PsiModifier.FINAL) || !(var instanceof PsiField)) { + if (!isFinalField(var)) { return false; } @@ -90,6 +90,10 @@ public class DfaVariableState implements Cloneable { return !nullable; } + public static boolean isFinalField(PsiVariable var) { + return var.hasModifierProperty(PsiModifier.FINAL) && !var.hasModifierProperty(PsiModifier.TRANSIENT) && var instanceof PsiField; + } + public boolean isNullable() { return myNullable; } diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java index 57a619a7849f..83c9f5efaafb 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java @@ -122,7 +122,7 @@ public class DfaValueFactory { } final PsiVariable variable = (PsiVariable)psiSource; - if (variable.hasModifierProperty(PsiModifier.FINAL)) { + if (variable.hasModifierProperty(PsiModifier.FINAL) && !variable.hasModifierProperty(PsiModifier.TRANSIENT)) { DfaValue constValue = getConstFactory().create(variable); if (constValue != null) return constValue; diff --git a/java/java-indexing-impl/src/com/intellij/codeInsight/ReadableExternalAnnotationsManager.java b/java/java-indexing-impl/src/com/intellij/codeInsight/ReadableExternalAnnotationsManager.java new file mode 100644 index 000000000000..727f4a2e1e0c --- /dev/null +++ b/java/java-indexing-impl/src/com/intellij/codeInsight/ReadableExternalAnnotationsManager.java @@ -0,0 +1,81 @@ +/* + * 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.codeInsight; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.roots.*; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.psi.PsiManager; +import com.intellij.util.ThreeState; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class ReadableExternalAnnotationsManager extends BaseExternalAnnotationsManager { + @NotNull private volatile ThreeState myHasAnyAnnotationsRoots = ThreeState.UNSURE; + + public ReadableExternalAnnotationsManager(PsiManager psiManager) { + super(psiManager); + } + + @Override + protected boolean hasAnyAnnotationsRoots() { + if (myHasAnyAnnotationsRoots == ThreeState.UNSURE) { + final Module[] modules = ModuleManager.getInstance(myPsiManager.getProject()).getModules(); + for (Module module : modules) { + for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) { + final String[] urls = AnnotationOrderRootType.getUrls(entry); + if (urls.length > 0) { + myHasAnyAnnotationsRoots = ThreeState.YES; + return true; + } + } + } + myHasAnyAnnotationsRoots = ThreeState.NO; + } + return myHasAnyAnnotationsRoots == ThreeState.YES; + } + + @NotNull + @Override + protected List getExternalAnnotationsRoots(@NotNull VirtualFile libraryFile) { + final List entries = ProjectRootManager.getInstance(myPsiManager.getProject()).getFileIndex().getOrderEntriesForFile( + libraryFile); + List result = new ArrayList(); + for (OrderEntry entry : entries) { + if (entry instanceof ModuleOrderEntry) { + continue; + } + final String[] externalUrls = AnnotationOrderRootType.getUrls(entry); + for (String url : externalUrls) { + VirtualFile root = VirtualFileManager.getInstance().findFileByUrl(url); + if (root != null) { + result.add(root); + } + } + } + return result; + } + + @Override + protected void dropCache() { + myHasAnyAnnotationsRoots = ThreeState.UNSURE; + super.dropCache(); + } +} diff --git a/java/java-indexing-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java similarity index 87% rename from java/java-indexing-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java rename to java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java index 89638cdb67ae..b09ed08510af 100644 --- a/java/java-indexing-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java @@ -16,21 +16,16 @@ package com.intellij.codeInsight; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.roots.*; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.psi.*; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.ThreeState; import com.intellij.util.containers.ConcurrentSoftHashMap; import com.intellij.util.containers.ConcurrentSoftValueHashMap; import com.intellij.util.containers.MultiMap; @@ -45,11 +40,11 @@ import java.io.IOException; import java.util.*; import java.util.concurrent.ConcurrentMap; -public class BaseExternalAnnotationsManager extends ExternalAnnotationsManager { +public abstract class BaseExternalAnnotationsManager extends ExternalAnnotationsManager{ private static final Logger LOG = Logger.getInstance("#" + BaseExternalAnnotationsManager.class.getName()); @NotNull private static final List NULL = new ArrayList(); - @NotNull protected final ConcurrentMap> myExternalAnnotations = new ConcurrentSoftValueHashMap>(); - @NotNull private volatile ThreeState myHasAnyAnnotationsRoots = ThreeState.UNSURE; + @NotNull protected final ConcurrentMap> + myExternalAnnotations = new ConcurrentSoftValueHashMap>(); protected final PsiManager myPsiManager; public BaseExternalAnnotationsManager(final PsiManager psiManager) { @@ -95,22 +90,7 @@ public class BaseExternalAnnotationsManager extends ExternalAnnotationsManager { return StringUtil.trimEnd(buf.toString(), ", ") + externalName.substring(rightIdx); } - protected boolean hasAnyAnnotationsRoots() { - if (myHasAnyAnnotationsRoots == ThreeState.UNSURE) { - final Module[] modules = ModuleManager.getInstance(myPsiManager.getProject()).getModules(); - for (Module module : modules) { - for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) { - final String[] urls = AnnotationOrderRootType.getUrls(entry); - if (urls.length > 0) { - myHasAnyAnnotationsRoots = ThreeState.YES; - return true; - } - } - } - myHasAnyAnnotationsRoots = ThreeState.NO; - } - return myHasAnyAnnotationsRoots == ThreeState.YES; - } + protected abstract boolean hasAnyAnnotationsRoots(); @Override @Nullable @@ -216,7 +196,7 @@ public class BaseExternalAnnotationsManager extends ExternalAnnotationsManager { if (onlyWritable && !file.isWritable()) continue; final MultiMap fileData = getDataFromFile(file); - + collectAnnotations(result, fileData.get(externalName), factory); collectAnnotations(result, fileData.get(oldExternalName), factory); } @@ -241,24 +221,7 @@ public class BaseExternalAnnotationsManager extends ExternalAnnotationsManager { } @NotNull - protected List getExternalAnnotationsRoots(@NotNull VirtualFile libraryFile) { - final List entries = ProjectRootManager.getInstance(myPsiManager.getProject()).getFileIndex().getOrderEntriesForFile( - libraryFile); - List result = new ArrayList(); - for (OrderEntry entry : entries) { - if (entry instanceof ModuleOrderEntry) { - continue; - } - final String[] externalUrls = AnnotationOrderRootType.getUrls(entry); - for (String url : externalUrls) { - VirtualFile root = VirtualFileManager.getInstance().findFileByUrl(url); - if (root != null) { - result.add(root); - } - } - } - return result; - } + protected abstract List getExternalAnnotationsRoots(@NotNull VirtualFile libraryFile); @Override @Nullable @@ -321,7 +284,6 @@ public class BaseExternalAnnotationsManager extends ExternalAnnotationsManager { protected void dropCache() { myExternalAnnotations.clear(); annotationsFileToDataAndModificationStamp.clear(); - myHasAnyAnnotationsRoots = ThreeState.UNSURE; cache.clear(); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java index e4e25c9b00c1..7f9e847d9d66 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java @@ -217,7 +217,7 @@ public class PsiMethodCallExpressionImpl extends ExpressionPsiElement implements if (is15OrHigher) { final PsiSubstitutor substitutor = result.getSubstitutor(); PsiType substitutedReturnType = substitutor.substitute(ret); - if (substitutedReturnType == null) return TypeConversionUtil.erasure(ret); + if (PsiUtil.isRawSubstitutor(method, substitutor) && ret.equals(substitutedReturnType)) return TypeConversionUtil.erasure(ret); PsiType lowerBound = PsiType.NULL; if (substitutedReturnType instanceof PsiCapturedWildcardType) { lowerBound = ((PsiCapturedWildcardType)substitutedReturnType).getLowerBound(); diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java index 1458712506f8..50e5558b5645 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java @@ -81,15 +81,15 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ // then noone can be more specific if (!atLeastOneMatch) return null; + checkLambdaApplicable(conflicts); + if (conflicts.size() == 1) return conflicts.get(0); + checkSpecifics(conflicts, applicabilityLevel); if (conflicts.size() == 1) return conflicts.get(0); checkPrimitiveVarargs(conflicts, myActualParameterTypes.length); if (conflicts.size() == 1) return conflicts.get(0); - checkLambdaApplicable(conflicts); - if (conflicts.size() == 1) return conflicts.get(0); - THashSet uniques = new THashSet(conflicts); if (uniques.size() == 1) return uniques.iterator().next(); return null; diff --git a/java/java-tests/testData/codeInsight/completion/normal/PrimitiveMethodParameter_after.java b/java/java-tests/testData/codeInsight/completion/normal/PrimitiveMethodParameter_after.java index aa3645ad53c0..d649b2d4a6ce 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/PrimitiveMethodParameter_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/PrimitiveMethodParameter_after.java @@ -1,3 +1,3 @@ public class Foo { - Object foo(boolean ){ } + Object foo(boolean){ } } diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/DontDispreferImplsAfterNew.java b/java/java-tests/testData/codeInsight/completion/normalSorting/ImplsAfterNew.java similarity index 100% rename from java/java-tests/testData/codeInsight/completion/normalSorting/DontDispreferImplsAfterNew.java rename to java/java-tests/testData/codeInsight/completion/normalSorting/ImplsAfterNew.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aClassLoader_hl.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aClassLoader_hl.java index 5ad3d729e363..c7f959b6a630 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aClassLoader_hl.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aClassLoader_hl.java @@ -1723,7 +1723,7 @@ class SystemClassLoaderAction implements (cls, true, parent); - ctor = c.getDeclaredConstructor(cp); + ctor = c.getDeclaredConstructor(cp); sys = (ClassLoader) ctor.newInstance(params); Thread.currentThread().setContextClassLoader(sys); return sys; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA97888.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA97888.java new file mode 100644 index 000000000000..5a82678af70c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA97888.java @@ -0,0 +1,23 @@ +import java.util.*; +import java.io.File; +class Foo { + public Collection> getDependencies(LayoutElementBuilderService builder, JpsPackagingElement element, TargetOutputIndex outputIndex) { + return builder.getDependencies(element, outputIndex); + } +} + +class BuildTarget {} + +interface TargetOutputIndex { + Collection> getTargetsByOutputFile(File file); +} + +class BuildRootDescriptor {} + +class LayoutElementBuilderService { + public Collection> getDependencies(E element, TargetOutputIndex outputIndex) { + return Collections.emptyList(); + } +} + +class JpsPackagingElement {} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibilityBeforeSpecificsCheck.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibilityBeforeSpecificsCheck.java new file mode 100644 index 000000000000..70583e906788 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibilityBeforeSpecificsCheck.java @@ -0,0 +1,25 @@ +class X { + public static void main(final Stream stream) throws Throwable { + stream.map(s -> s.substring("http://".length())).forEach(System.out::println); + } +} + +interface Stream { + Stream map(Function mapper); + IntStream map(IntFunction mapper); + void forEach(Block block); +} + +interface IntFunction extends Function { + public int applyAsInt(T t); +} + +interface Function { + public R apply(T t); +} + +interface IntStream extends BaseStream {} +interface BaseStream {} +interface Block { + public void accept(T t); +} diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/TransientFinalField.java b/java/java-tests/testData/inspection/dataFlow/fixture/TransientFinalField.java new file mode 100644 index 000000000000..d2be77dc879c --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/TransientFinalField.java @@ -0,0 +1,11 @@ +final class Alive implements java.io.Serializable { + private transient final Object elvis = new Object(); + @Override + public String toString() { + if (elvis != null) { + return "uh-huh-huh"; + } else { + return "the king is dead"; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy index ff72157d0165..c83bf7e9073e 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy @@ -125,10 +125,10 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase { myFixture.complete(CompletionType.BASIC, 2); } - public void _testDontDispreferImplsAfterNew() { //todo[peter] + public void testImplsAfterNew() { myFixture.addClass("package foo; public interface Xxx {}"); configureSecondCompletion(); - assertPreferredItems(0, "Xxx", "XxxImpl"); + assertPreferredItems(0, "XxxImpl", "Xxx"); } public void testPreferLessHumps() throws Throwable { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index efd46470ee23..9d466584a653 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -207,6 +207,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testIDEA97276() throws Exception { doTest17Incompatibility(false); } public void testWildcardsBoundsIntersection() throws Exception { doTest17Incompatibility(false); } public void testOverrideWithMoreSpecificReturn() throws Exception { doTest17Incompatibility(false); } + public void testIDEA97888() throws Exception { doTest17Incompatibility(false); } public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java index 362f5babf12d..6b9e16ae63e0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java @@ -173,6 +173,10 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testReturnTypeCompatibilityBeforeSpecificsCheck() throws Exception { + doTest(); + } + private void doTest() throws Exception { doTest(BASE_PATH + "/" + getTestName(false) + ".java", false, false); } diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java index 3a80f6832cdf..4864bb856e56 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java @@ -147,6 +147,9 @@ public class DataFlowInspectionFixtureTest extends JavaCodeInsightFixtureTestCas public void testMethodCallFlushesField() { doTest(); } public void testUnknownFloatMayBeNaN() { doTest(); } public void testLastConstantConditionInAnd() { doTest(); } + + public void testTransientFinalField() { doTest(); } + public void testNullableForeachVariable() { setupCustomAnnotations(); doTest(); diff --git a/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java b/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java index 59c5b29084d6..8831f21ab6b2 100644 --- a/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java +++ b/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java @@ -120,7 +120,7 @@ public final class LoadTextUtil { Charset charset = virtualFile.isCharsetSet() ? virtualFile.getCharset() : detectCharset(virtualFile, content); Pair bomAndCharset = getBOMAndCharset(content, charset); final byte[] bom = bomAndCharset.second; - if (saveBOM && bom.length != 0) { + if (saveBOM && bom != null && bom.length != 0) { virtualFile.setBOM(bom); } return bomAndCharset; diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java index 59fc46c7f6ad..27e8049b3018 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java @@ -27,6 +27,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtilRt; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFile; @@ -216,6 +217,10 @@ public class JdkUtil { } String classpath = PathUtil.getJarPathForClass(commandLineWrapper); + final String utilRtPath = PathUtil.getJarPathForClass(StringUtilRt.class); + if (!classpath.equals(utilRtPath)) { + classpath += File.pathSeparator + utilRtPath; + } final Class ourUrlClassLoader = UrlClassLoader.class; if (ourUrlClassLoader.getName().equals(vmParametersList.getPropertyValue("java.system.class.loader"))) { classpath += File.pathSeparator + PathUtil.getJarPathForClass(ourUrlClassLoader); diff --git a/platform/lang-impl/src/com/intellij/tools/Tool.java b/platform/lang-impl/src/com/intellij/tools/Tool.java index 4af31bb0e305..58b53e2a3d09 100644 --- a/platform/lang-impl/src/com/intellij/tools/Tool.java +++ b/platform/lang-impl/src/com/intellij/tools/Tool.java @@ -38,6 +38,7 @@ import org.jetbrains.annotations.Nullable; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; public class Tool implements SchemeElement { @NonNls public final static String ACTION_ID_PREFIX = "Tool_"; @@ -201,22 +202,22 @@ public class Tool implements SchemeElement { } public void copyFrom(Tool source) { - myName = source.myName; - myDescription = source.myDescription; - myGroup = source.myGroup; - myShownInMainMenu = source.myShownInMainMenu; - myShownInEditor = source.myShownInEditor; - myShownInProjectViews = source.myShownInProjectViews; - myShownInSearchResultsPopup = source.myShownInSearchResultsPopup; - myEnabled = source.myEnabled; - myUseConsole = source.myUseConsole; - myShowConsoleOnStdOut = source.myShowConsoleOnStdOut; - myShowConsoleOnStdErr = source.myShowConsoleOnStdErr; - mySynchronizeAfterExecution = source.mySynchronizeAfterExecution; - myWorkingDirectory = source.myWorkingDirectory; - myProgram = source.myProgram; - myParameters = source.myParameters; - myOutputFilters = (ArrayList)source.myOutputFilters.clone(); + myName = source.getName(); + myDescription = source.getDescription(); + myGroup = source.getGroup(); + myShownInMainMenu = source.isShownInMainMenu(); + myShownInEditor = source.isShownInEditor(); + myShownInProjectViews = source.isShownInProjectViews(); + myShownInSearchResultsPopup = source.isShownInSearchResultsPopup(); + myEnabled = source.isEnabled(); + myUseConsole = source.isUseConsole(); + myShowConsoleOnStdOut = source.isShowConsoleOnStdOut(); + myShowConsoleOnStdErr = source.isShowConsoleOnStdErr(); + mySynchronizeAfterExecution = source.synchronizeAfterExecution(); + myWorkingDirectory = source.getWorkingDirectory(); + myProgram = source.getProgram(); + myParameters = source.getParameters(); + myOutputFilters = new ArrayList(Arrays.asList(source.getOutputFilters())); } public boolean equals(Object obj) { diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/config/PasswordSafeOptionsPanel.form b/platform/platform-impl/src/com/intellij/ide/passwordSafe/config/PasswordSafeOptionsPanel.form index 070432d8084e..62ebbcdc7c8c 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/config/PasswordSafeOptionsPanel.form +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/config/PasswordSafeOptionsPanel.form @@ -72,7 +72,7 @@ - + diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretLeftOrRightHandler.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretLeftOrRightHandler.java index 7ec8945a0fc6..8ad432908947 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretLeftOrRightHandler.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretLeftOrRightHandler.java @@ -24,7 +24,6 @@ import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.impl.EditorImpl; -import com.intellij.openapi.util.TextRange; class MoveCaretLeftOrRightHandler extends EditorActionHandler { enum Direction {LEFT, RIGHT} @@ -48,11 +47,12 @@ class MoveCaretLeftOrRightHandler extends EditorActionHandler { else { int start = selectionModel.getSelectionStart(); int end = selectionModel.getSelectionEnd(); + int caretOffset = caretModel.getOffset(); - int leftGuard = start + (myDirection == Direction.LEFT ? 1 : 0); - int rightGuard = end - (myDirection == Direction.RIGHT ? 1 : 0); - - if (TextRange.from(leftGuard, rightGuard - leftGuard + 1).contains(caretModel.getOffset())) { // See IDEADEV-36957 + //int leftGuard = start + (myDirection == Direction.LEFT ? 1 : 0); + //int rightGuard = end - (myDirection == Direction.RIGHT ? 1 : 0); + //if (TextRange.from(leftGuard, rightGuard - leftGuard + 1).contains(caretModel.getOffset())) { // See IDEADEV-36957 + if (start <= caretOffset && end >= caretOffset) { // See IDEADEV-36957 selectionModel.removeSelection(); caretModel.moveToOffset(myDirection == Direction.RIGHT ? end : start); scrollingModel.scrollToCaret(ScrollType.RELATIVE); diff --git a/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java b/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java index d9bd84c97856..e05a430ab2a7 100644 --- a/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java +++ b/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java @@ -321,6 +321,10 @@ public class NameUtilTest extends UsefulTestCase { assertFalse(pattern + " matches " + name + "!!!", caseInsensitiveMatcher(pattern).matches(name)); } + public void testUpperCaseMatchesLowerCase() { + assertMatches("ABC_B.C", "abc_b.c"); + } + public void testLowerCaseHumps() { assertMatches("foo", "foo"); assertDoesntMatch("foo", "fxoo"); diff --git a/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java b/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java index 4e77da42e3cb..a73f6d358c02 100644 --- a/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java +++ b/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java @@ -61,7 +61,7 @@ public class MinusculeMatcher implements Matcher { } int i = 0; while (isWildcard(i)) i++; - myHasHumps = hasHumps(i + 1); + myHasHumps = hasFlag(i + 1, isUpperCase) && hasFlag(i + 1, isLowerCase); myHasDots = hasDots(i); myHasWildCards = hasWildCards(); } @@ -75,9 +75,9 @@ public class MinusculeMatcher implements Matcher { return false; } - private boolean hasHumps(int start) { + private boolean hasFlag(int start, boolean[] flags) { for (int i = start; i < myPattern.length; i++) { - if (isUpperCase[i]) { + if (flags[i]) { return true; } } diff --git a/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java b/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java index 2a6d7918b308..a53bc00dd6c2 100644 --- a/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java +++ b/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesReadingTest.java @@ -19,6 +19,7 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.win32.FileInfo; import com.intellij.openapi.util.io.win32.IdeaWin32; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.TimeoutUtil; import org.jetbrains.annotations.NotNull; import org.junit.After; import org.junit.Before; @@ -30,7 +31,6 @@ import java.util.Arrays; import static com.intellij.openapi.util.io.IoTestUtil.assertTimestampsEqual; import static org.junit.Assert.*; -import static org.junit.Assert.assertEquals; import static org.junit.Assume.assumeTrue; public class FileAttributesReadingTest { @@ -344,6 +344,33 @@ public class FileAttributesReadingTest { assertEquals(link.getPath(), resolved); } + @Test + public void stamps() throws Exception { + FileAttributes attributes = FileSystemUtil.getAttributes(myTempDirectory); + assumeTrue(attributes != null && attributes.lastModified > (attributes.lastModified/1000)*1000); + + long t1 = System.currentTimeMillis(); + TimeoutUtil.sleep(10); + File file = IoTestUtil.createTestFile(myTempDirectory, "test.txt"); + TimeoutUtil.sleep(10); + long t2 = System.currentTimeMillis(); + attributes = getAttributes(file); + assertTrue(attributes.lastModified + " not in " + t1 + ".." + t2, t1 <= attributes.lastModified && attributes.lastModified <= t2); + + t1 = System.currentTimeMillis(); + TimeoutUtil.sleep(10); + FileUtil.writeToFile(file, myTestData); + TimeoutUtil.sleep(10); + t2 = System.currentTimeMillis(); + attributes = getAttributes(file); + assertTrue(attributes.lastModified + " not in " + t1 + ".." + t2, t1 <= attributes.lastModified && attributes.lastModified <= t2); + + ProcessBuilder cmd = SystemInfo.isWindows ? new ProcessBuilder("attrib", "-A", file.getPath()) : new ProcessBuilder("chmod", "644", file.getPath()); + assertEquals(0, cmd.start().waitFor()); + attributes = getAttributes(file); + assertTrue(attributes.lastModified + " not in " + t1 + ".." + t2, t1 <= attributes.lastModified && attributes.lastModified <= t2); + } + @NotNull private static FileAttributes getAttributes(@NotNull final File file) { return getAttributes(file, true); diff --git a/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationBase.java b/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationBase.java index 7bf4f34bf843..315b09732c45 100644 --- a/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationBase.java +++ b/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationBase.java @@ -112,9 +112,6 @@ public abstract class AndroidRunConfigurationBase extends ModuleBasedConfigurati if (avdInfo == null) { throw new RuntimeConfigurationError(AndroidBundle.message("avd.not.found.error", PREFERRED_AVD)); } - if (!facet.isCompatibleAvd(avdInfo)) { - throw new RuntimeConfigurationError(AndroidBundle.message("avd.not.compatible.error", PREFERRED_AVD)); - } if (avdInfo.getStatus() != AvdInfo.AvdStatus.OK) { throw new RuntimeConfigurationError(AndroidBundle.message("avd.not.valid.error", PREFERRED_AVD)); } diff --git a/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationEditor.java b/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationEditor.java index 83b3078be95e..8d0cc2d86ccf 100644 --- a/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationEditor.java +++ b/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationEditor.java @@ -15,6 +15,8 @@ */ package org.jetbrains.android.run; +import com.android.sdklib.internal.avd.AvdInfo; +import com.android.sdklib.internal.avd.AvdManager; import com.intellij.execution.ui.ConfigurationModuleSelector; import com.intellij.icons.AllIcons; import com.intellij.openapi.application.ModalityState; @@ -98,17 +100,28 @@ public class AndroidRunConfigurationEditor branches1 = getBranches(root, abstractHash); + if (branches1 != null && ! branches1.isEmpty()) return; List branches; try { branches = new LowLevelAccessImpl(myProject, root).getBranchesWithCommit(abstractHash.getString()); diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java b/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java index 6bea70cf82b6..bd2e523d44fd 100644 --- a/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java +++ b/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java @@ -495,7 +495,7 @@ public class GitLogUI implements Disposable { if (commitI == null) return; final VirtualFile root = commitI.selectRepository(myRootsUnderVcs); final List branches = myDetailsCache.getBranches(root, commitI.getHash()); - if (branches != null) { + if (branches != null && ! branches.isEmpty()) { try { myBranchesLoader.take(commitI, branches); } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/project/GradleProjectStructureChangesCalculator.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/project/GradleProjectStructureChangesCalculator.java index 45b0c01a340e..f999dd659b0c 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/project/GradleProjectStructureChangesCalculator.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/project/GradleProjectStructureChangesCalculator.java @@ -2,6 +2,7 @@ package org.jetbrains.plugins.gradle.diff.project; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.pom.java.LanguageLevel; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.gradle.config.PlatformFacade; @@ -9,10 +10,12 @@ import org.jetbrains.plugins.gradle.diff.GradleChangesCalculationContext; import org.jetbrains.plugins.gradle.diff.GradleDiffUtil; import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChange; import org.jetbrains.plugins.gradle.diff.GradleStructureChangesCalculator; +import org.jetbrains.plugins.gradle.diff.library.GradleLibraryStructureChangesCalculator; import org.jetbrains.plugins.gradle.diff.module.GradleModuleStructureChangesCalculator; import org.jetbrains.plugins.gradle.model.gradle.GradleModule; import org.jetbrains.plugins.gradle.model.gradle.GradleProject; +import java.util.Arrays; import java.util.Collection; import java.util.Set; @@ -26,12 +29,16 @@ import java.util.Set; */ public class GradleProjectStructureChangesCalculator implements GradleStructureChangesCalculator { - private final GradleModuleStructureChangesCalculator myModuleChangesCalculator; - private final PlatformFacade myPlatformFacade; + @NotNull private final GradleModuleStructureChangesCalculator myModuleChangesCalculator; + @NotNull private final GradleLibraryStructureChangesCalculator myLibraryChangesCalculator; + @NotNull private final PlatformFacade myPlatformFacade; public GradleProjectStructureChangesCalculator(@NotNull GradleModuleStructureChangesCalculator moduleCalculator, - @NotNull PlatformFacade platformFacade) { + @NotNull GradleLibraryStructureChangesCalculator calculator, + @NotNull PlatformFacade platformFacade) + { myModuleChangesCalculator = moduleCalculator; + myLibraryChangesCalculator = calculator; myPlatformFacade = platformFacade; } @@ -45,6 +52,9 @@ public class GradleProjectStructureChangesCalculator implements GradleStructureC final Set gradleSubEntities = gradleEntity.getModules(); final Collection intellijSubEntities = myPlatformFacade.getModules(intellijEntity); GradleDiffUtil.calculate(myModuleChangesCalculator, gradleSubEntities, intellijSubEntities, context); + + LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(intellijEntity); + GradleDiffUtil.calculate(myLibraryChangesCalculator, gradleEntity.getLibraries(), Arrays.asList(libraryTable.getLibraries()), context); } @NotNull diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleJarManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleJarManager.java index a3aa33580708..0d2b4a6b46bf 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleJarManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleJarManager.java @@ -62,7 +62,7 @@ public class GradleJarManager { Library.ModifiableModel model = library.getModifiableModel(); try { for (VirtualFile file : model.getFiles(OrderRootType.CLASSES)) { - if (jar.getPath().equals(file.getPath())) { + if (jar.getPath().equals(GradleUtil.getLocalFileSystemPath(file))) { return; } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleLocalNodeManageHelper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleLocalNodeManageHelper.java index 497671c1eadf..d034e210d356 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleLocalNodeManageHelper.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleLocalNodeManageHelper.java @@ -5,7 +5,9 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ExportableOrderEntry; import com.intellij.openapi.roots.LibraryOrderEntry; import com.intellij.openapi.roots.ModuleOrderEntry; +import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; @@ -189,16 +191,34 @@ public class GradleLocalNodeManageHelper { private void collectLibraryDependencyEntities(@NotNull GradleLibraryDependency dependency, @NotNull Context context) { final LibraryOrderEntry intellijDependency = myProjectStructureHelper.findIntellijLibraryDependency(dependency.getOwnerModule().getName(), dependency.getName()); - if (intellijDependency != null) { - // Already imported. - return; + Set intellijPaths = ContainerUtilRt.newHashSet(); + GradleLibrary gradleLibrary = dependency.getTarget(); + Library intellijLibrary = null; + if (intellijDependency == null) { + context.dependencies.add(dependency); } - context.dependencies.add(dependency); - final GradleLibrary gradleLibrary = dependency.getTarget(); - final Library intellijLibrary = myProjectStructureHelper.findIntellijLibrary(gradleLibrary); + else { + intellijLibrary = intellijDependency.getLibrary(); + } + + if (intellijLibrary == null) { + intellijLibrary = myProjectStructureHelper.findIntellijLibrary(gradleLibrary); + } + if (intellijLibrary == null) { context.libraries.add(gradleLibrary); } + else { + for (VirtualFile jarFile : intellijLibrary.getFiles(OrderRootType.CLASSES)) { + intellijPaths.add(GradleUtil.getLocalFileSystemPath(jarFile)); + } + } + + for (String gradleJarPath : gradleLibrary.getPaths(LibraryPathType.BINARY)) { + if (!intellijPaths.contains(gradleJarPath)) { + context.jars.add(new GradleJar(gradleJarPath, null, gradleLibrary)); + } + } } /** @@ -256,7 +276,6 @@ public class GradleLocalNodeManageHelper { } }); } - GradleUtil.refreshProject(myProjectStructureHelper.getProject()); } public void removeNodes(@NotNull Collection> nodes) { @@ -283,7 +302,9 @@ public class GradleLocalNodeManageHelper { for (GradleProjectStructureNode node : nodes) { GradleProjectStructureNodeDescriptor descriptor = node.getDescriptor(); - if (descriptor.getAttributes() != GradleTextAttributes.INTELLIJ_LOCAL_CHANGE) { + if (descriptor.getAttributes() == GradleTextAttributes.GRADLE_LOCAL_CHANGE + || descriptor.getElement().getType() == GradleEntityType.SYNTHETIC + || node.getParent() == null /* is root */) { continue; } Object entity = myIdMapper.mapIdToEntity(descriptor.getElement()); @@ -300,7 +321,6 @@ public class GradleLocalNodeManageHelper { myModuleDependencyManager.removeDependencies(dependencies); myModuleManager.removeModules(modules); myLibraryManager.removeLibraries(libraries); - GradleUtil.refreshProject(myProjectStructureHelper.getProject()); } private class Context { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleProjectImportBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleProjectImportBuilder.java index b1b224b94330..e57379e6cae3 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleProjectImportBuilder.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleProjectImportBuilder.java @@ -32,6 +32,7 @@ import org.jetbrains.plugins.gradle.config.GradleSettings; import org.jetbrains.plugins.gradle.model.gradle.GradleLibrary; import org.jetbrains.plugins.gradle.model.gradle.GradleModule; import org.jetbrains.plugins.gradle.model.gradle.GradleProject; +import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesModel; import org.jetbrains.plugins.gradle.sync.GradleProjectStructureHelper; import org.jetbrains.plugins.gradle.task.GradleResolveProjectTask; import org.jetbrains.plugins.gradle.util.GradleBundle; @@ -240,6 +241,9 @@ public class GradleProjectImportBuilder extends ProjectImportBuilder oldChanges, @NotNull final Collection currentChanges) { - final Runnable task = new Runnable() { - @Override - public void run() { - List currentChangesToUse = ContainerUtilRt.newArrayList(currentChanges); - Collection obsoleteChangesToUse = ContainerUtil.subtract(oldChanges, currentChanges); - if (myChangesComparator != null) { - List toSort = ContainerUtilRt.newArrayList(obsoleteChangesToUse); - Collections.sort(toSort, myChangesComparator); - obsoleteChangesToUse = toSort; - Collections.sort(currentChangesToUse, myChangesComparator); - } - processObsoleteChanges(obsoleteChangesToUse); - processCurrentChanges(currentChangesToUse); - } - }; - if (myProcessChangesAtTheSameThread) { - task.run(); - } - else { - UIUtil.invokeLaterIfNeeded(task); - } + processChanges(oldChanges, currentChanges); } }); @@ -138,6 +116,39 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel { rebuild(); } } + + private void processChanges(@NotNull final Collection oldChanges, + @NotNull final Collection currentChanges) + { + final Runnable task = new Runnable() { + @Override + public void run() { + Collection obsoleteChangesToUse = ContainerUtil.subtract(oldChanges, currentChanges); + Collection currentChangesToUse = currentChanges; + if (myChangesComparator != null) { + obsoleteChangesToUse = sort(obsoleteChangesToUse, myChangesComparator); + currentChangesToUse = sort(currentChangesToUse, myChangesComparator); + } + processObsoleteChanges(obsoleteChangesToUse); + processCurrentChanges(currentChangesToUse); + } + }; + if (myProcessChangesAtTheSameThread) { + task.run(); + } + else { + UIUtil.invokeLaterIfNeeded(task); + } + } + + @NotNull + private static Collection sort(@NotNull Collection changes, + @NotNull Comparator myChangesComparator) + { + List toSort = ContainerUtilRt.newArrayList(changes); + Collections.sort(toSort, myChangesComparator); + return toSort; + } @SuppressWarnings("unchecked") @Override @@ -209,8 +220,13 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel { } } } - processCurrentChanges(myChangesModel.getChanges()); - filterNodes(root); + + GradleProject project = myChangesModel.getGradleProject(); + if (project != null) { + GradleChangesCalculationContext context = myChangesModel.getCurrentChangesContext(project); + processChanges(context.getKnownChanges(), context.getCurrentChanges()); + filterNodes(root); + } } private void populateLibraryDependencyNode(@NotNull GradleProjectStructureNode node, @@ -470,18 +486,56 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel { private void processNewLibraryDependencyPresenceChange(@NotNull GradleLibraryDependencyPresenceChange change) { GradleProjectStructureNode dependencyNode = processNewDependencyPresenceChange(change); GradleLibraryDependencyId id = change.getGradleEntity(); - if (dependencyNode != null && id != null) { - GradleLibrary library = myProjectStructureHelper.findGradleLibrary(id.getLibraryId()); - if (library != null) { - GradleLibraryId libraryId = dependencyNode.getDescriptor().getElement().getLibraryId(); - for (String path : library.getPaths(LibraryPathType.BINARY)) { - GradleJarId jarId = new GradleJarId(path, libraryId); - GradleProjectStructureNode jarNode = buildNode(jarId, GradleUtil.extractNameFromPath(jarId.getPath())); - jarNode.setAttributes(GradleTextAttributes.GRADLE_LOCAL_CHANGE); - jarNode.getDescriptor().setToolTip(jarId.getPath()); - dependencyNode.add(jarNode); + if (dependencyNode == null || id == null) { + return; + } + GradleLibrary gradleLibrary = myProjectStructureHelper.findGradleLibrary(id.getLibraryId()); + if (gradleLibrary == null) { + return; + } + + Map> existingJarNodes = ContainerUtilRt.newHashMap(); + for (GradleProjectStructureNode jarNode : dependencyNode.getChildren(GradleJarId.class)) { + existingJarNodes.put(jarNode.getDescriptor().getElement(), jarNode); + } + + Map> gradleJarIds = ContainerUtilRt.newHashMap(); + GradleLibraryId libraryId = dependencyNode.getDescriptor().getElement().getLibraryId(); + for (String path : gradleLibrary.getPaths(LibraryPathType.BINARY)) { + GradleJarId jarId = new GradleJarId(path, libraryId); + GradleProjectStructureNode jarNode = existingJarNodes.get(jarId); + if (jarNode == null) { + jarNode = buildNode(jarId, GradleUtil.extractNameFromPath(jarId.getPath())); + jarNode.setAttributes(GradleTextAttributes.NO_CHANGE); + jarNode.getDescriptor().setToolTip(jarId.getPath()); + dependencyNode.add(jarNode); + } + gradleJarIds.put(jarId, jarNode); + } + + Library intellijLibrary = myProjectStructureHelper.findIntellijLibrary(gradleLibrary); + if (intellijLibrary == null) { + for (GradleProjectStructureNode jarNode : dependencyNode) { + jarNode.setAttributes(GradleTextAttributes.GRADLE_LOCAL_CHANGE); + } + } + else { + Set intellijJarIds = ContainerUtilRt.newHashSet(); + for (VirtualFile jarFile : intellijLibrary.getFiles(OrderRootType.CLASSES)) { + GradleJarId jarId = new GradleJarId(GradleUtil.getLocalFileSystemPath(jarFile), libraryId); + if (gradleJarIds.remove(jarId) == null) { + intellijJarIds.add(jarId); } } + for (GradleProjectStructureNode jarNode : gradleJarIds.values()) { + jarNode.setAttributes(GradleTextAttributes.GRADLE_LOCAL_CHANGE); + } + for (GradleJarId jarId : intellijJarIds) { + GradleProjectStructureNode jarNode = buildNode(jarId, GradleUtil.extractNameFromPath(jarId.getPath())); + jarNode.setAttributes(GradleTextAttributes.INTELLIJ_LOCAL_CHANGE); + jarNode.getDescriptor().setToolTip(jarId.getPath()); + dependencyNode.add(jarNode); + } } } diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesModelTest.groovy b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesModelTest.groovy index 7f1c41cd086c..b1836fe4d600 100644 --- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesModelTest.groovy +++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesModelTest.groovy @@ -227,7 +227,8 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest { dependencies { lib1('gradle') { jar1('gradle') - jar2('gradle')} } } + jar2() + jar3('intellij')} } } module1 { dependencies { lib1 { @@ -346,51 +347,6 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest { } } } - @Test - public void "gradle local library dependency outweighs library path conflict"() { - init( - gradle: { - project { - module('module1') { - dependencies { - library('lib1', bin: ['jar1']) } } - module('module2') { - dependencies { - library('lib1') } } } }, - intellij: { - project { - module('module1') { - dependencies { - library('lib1', bin: ['jar2']) } } } }, - changesSorter: changeByClassSorter([ - (GradleModulePresenceChange) : 1, - (GradleLibraryDependencyPresenceChange) : 2, - (GradleJarPresenceChange) : 3, - ]) - ) - - checkChanges { - presence { - module(gradle: gradle.modules['module2']) - jar(gradle: [findJarId('jar1')]) - jar(intellij: [findJarId('jar2')]) - libraryDependency(gradle: gradle.libraryDependencies[gradle.modules['module2']].first()) - } - } - - checkTree { - project { - module2('gradle') { - dependencies { - lib1('gradle') { - jar1('gradle') } } } - module1() { - dependencies { - lib1 { - jar1('gradle') - jar2('intellij') } } } } } - } - @Test public void "mismatched module dependency import"() { init( @@ -789,7 +745,7 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest { module('module1') module('module2') { dependencies { - library('lib1', bin: ['1']) + library('lib1', bin: ['jar1']) module('module1', scope: 'compile') } } } } init(gradle: gradleProject, intellij: { @@ -797,7 +753,7 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest { module('module1') module('module2') { dependencies { - library('lib1', bin: ['2']) + library('lib1', bin: ['jar2']) module('module1', scope: 'test') } } } }) @@ -814,4 +770,88 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest { project { } } } + + @Test + public void "gradle-local library dependency with mixed jars state"() { + init( + gradle: { + project { + module('module1') { + dependencies { + library('lib1', bin: ['jar1', 'jar2']) } } + module('module2') { + dependencies { + library('lib1', bin: ['jar1', 'jar2'])} } } }, + intellij: { + project { + module('module1') { + dependencies { + library('lib1', bin: ['jar2', 'jar3']) }} + module('module2') }} + ) + + checkChanges { + presence { + libraryDependency(gradle: gradle.modules['module2'].dependencies) + jar(gradle: [findJarId('jar1')]) + jar(intellij: [findJarId('jar3')]) + } + } + checkTree { + project { + module1 { + dependencies { + lib1 { + jar1('gradle') + jar2() + jar3('intellij')} } } + module2 { + dependencies { + lib1('gradle') { + jar1('gradle') + jar2() + jar3('intellij') } } } } } + } + + @Test + public void "intellij-local library dependency with mixed jars state"() { + init( + gradle: { + project { + module('module1') { + dependencies { + library('lib1', bin: ['jar1', 'jar2']) } } + module('module2')} }, + intellij: { + project { + module('module1') { + dependencies { + library('lib1', bin: ['jar2', 'jar3']) }} + module('module2') { + dependencies { + library('lib1', bin: ['jar1', 'jar2'])}}}} + ) + + checkChanges { + presence { + libraryDependency(intellij: intellij.libraryDependencies[intellij.modules['module2']]) + jar(gradle: [findJarId('jar1')]) + jar(intellij: [findJarId('jar3')]) + } + } + checkTree { + project { + module1 { + dependencies { + lib1 { + jar1('gradle') + jar2() + jar3('intellij')} } } + module2 { + dependencies { + lib1('intellij') { + jar1('gradle') + jar2() + jar3('intellij') } } } } } + } } \ No newline at end of file diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/AbstractGradleTest.groovy b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/AbstractGradleTest.groovy index d21c03409ad4..878d3c146bb0 100644 --- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/AbstractGradleTest.groovy +++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/AbstractGradleTest.groovy @@ -43,7 +43,7 @@ public abstract class AbstractGradleTest { GradleProjectStructureTreeModel treeModel GradleProjectBuilder gradle IntellijProjectBuilder intellij - def changesBuilder + ChangeBuilder changesBuilder ProjectStructureChecker treeChecker def container private Map treeFilters = [:] diff --git a/xml/dom-openapi/src/com/intellij/util/xml/ui/AbstractTableView.java b/xml/dom-openapi/src/com/intellij/util/xml/ui/AbstractTableView.java index 4b2f1d58b893..82df8a529d21 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/ui/AbstractTableView.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/ui/AbstractTableView.java @@ -128,7 +128,7 @@ public abstract class AbstractTableView extends JPanel implements TypeSafeDat final ActionManager actionManager = ActionManager.getInstance(); final ToolbarPosition position = getToolbarPosition(); final ActionToolbar myActionToolbar = actionManager.createActionToolbar(ActionPlaces.PROJECT_VIEW_TOOLBAR, actionGroup, position == ToolbarPosition.TOP || position == ToolbarPosition.BOTTOM); - myActionToolbar.setTargetComponent(myTable); + myActionToolbar.setTargetComponent(myInnerPanel); final JComponent toolbarComponent = myActionToolbar.getComponent(); final MatteBorder matteBorder = BorderFactory.createMatteBorder(0, 0, position == ToolbarPosition.TOP ? 1 : 0, 0, JBColor.DARK_GRAY); toolbarComponent.setBorder(BorderFactory.createCompoundBorder(matteBorder, toolbarComponent.getBorder())); diff --git a/xml/dom-openapi/src/com/intellij/util/xml/ui/DomCollectionControl.java b/xml/dom-openapi/src/com/intellij/util/xml/ui/DomCollectionControl.java index e41204fc20b7..ba69ab5992b9 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/ui/DomCollectionControl.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/ui/DomCollectionControl.java @@ -167,7 +167,9 @@ public class DomCollectionControl extends DomUIControl imp } protected DefaultActionGroup createPopupActionGroup() { - return (DefaultActionGroup)ActionManager.getInstance().getAction("DomCollectionControl"); + final DefaultActionGroup group = new DefaultActionGroup(); + group.addAll((DefaultActionGroup)ActionManager.getInstance().getAction("DomCollectionControl")); + return group; } protected ColumnInfo[] createColumnInfos(DomElement parent) { diff --git a/xml/impl/src/com/intellij/xml/DefaultXmlExtension.java b/xml/impl/src/com/intellij/xml/DefaultXmlExtension.java index 771f52c63e2b..d692afa985b8 100644 --- a/xml/impl/src/com/intellij/xml/DefaultXmlExtension.java +++ b/xml/impl/src/com/intellij/xml/DefaultXmlExtension.java @@ -275,7 +275,7 @@ public class DefaultXmlExtension extends XmlExtension { final Collection files = XmlTagNamesIndex.getFilesByTagName(tagName, project); final Set possibleUris = new LinkedHashSet(files.size()); for (VirtualFile virtualFile : files) { - final String namespace = XmlNamespaceIndex.getNamespace(virtualFile, project); + final String namespace = XmlNamespaceIndex.getNamespace(virtualFile, project, file); if (namespace != null) { possibleUris.add(namespace); } diff --git a/xml/impl/src/com/intellij/xml/impl/schema/SchemaDefinitionsSearch.java b/xml/impl/src/com/intellij/xml/impl/schema/SchemaDefinitionsSearch.java index b197c17128ac..fe3a323cc28c 100644 --- a/xml/impl/src/com/intellij/xml/impl/schema/SchemaDefinitionsSearch.java +++ b/xml/impl/src/com/intellij/xml/impl/schema/SchemaDefinitionsSearch.java @@ -63,13 +63,13 @@ public class SchemaDefinitionsSearch implements QueryExecutor { @Nullable - public static String getNamespace(@NotNull VirtualFile file, final Project project) { - if (DumbService.isDumb(project)) { + public static String getNamespace(@NotNull VirtualFile file, final Project project, PsiFile context) { + if (DumbService.isDumb(project) || (context != null && XmlUtil.isStubBuilding(context))) { try { return XsdNamespaceBuilder.computeNamespace(file.getInputStream()); }