diff --git a/bin/mac/fsnotifier b/bin/mac/fsnotifier index 9bbf3898bb5d..02040b8cbf39 100755 Binary files a/bin/mac/fsnotifier and b/bin/mac/fsnotifier differ diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompilerUtil.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompilerUtil.java index 67bdb5209f39..1881d088c61f 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompilerUtil.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompilerUtil.java @@ -37,7 +37,6 @@ import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Set; public class CompilerUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.CompilerUtil"); @@ -74,7 +73,7 @@ public class CompilerUtil { } } - public static void refreshOutputDirectories(Set outputs, boolean async) { + public static void refreshOutputDirectories(Collection outputs, boolean async) { LocalFileSystem fileSystem = LocalFileSystem.getInstance(); List toRefresh = new ArrayList(); diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index efaf9e2b4346..d516d5b2f74e 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -17,6 +17,7 @@ package com.intellij.compiler.server; import com.intellij.ProjectTopics; import com.intellij.compiler.CompilerWorkspaceConfiguration; +import com.intellij.compiler.impl.CompilerUtil; import com.intellij.compiler.impl.javaCompiler.javac.JavacConfiguration; import com.intellij.compiler.server.impl.BuildProcessClasspathManager; import com.intellij.execution.ExecutionAdapter; @@ -1266,26 +1267,39 @@ public class BuildManager implements ApplicationComponent{ roots = ArrayUtil.toStringArray(myRootsToRefresh); myRootsToRefresh.clear(); } - ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { - @Override - public void run() { - if (project.isDisposed()) { - return; - } - final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); - final LocalFileSystem lfs = LocalFileSystem.getInstance(); - final Set filesToRefresh = new HashSet(); - for (String root : roots) { - final VirtualFile rootFile = lfs.refreshAndFindFileByPath(root); - if (rootFile != null && fileIndex.isInSourceContent(rootFile)) { - filesToRefresh.add(rootFile); + if (roots.length != 0) { + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + if (project.isDisposed()) { + return; } + final List rootFiles = new ArrayList(roots.length); + for (String root : roots) { + rootFiles.add(new File(root)); + } + // this will ensure that we'll be able to obtain VirtualFile for existing roots + CompilerUtil.refreshOutputDirectories(rootFiles, false); + + final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); + final LocalFileSystem lfs = LocalFileSystem.getInstance(); + final Set filesToRefresh = new HashSet(); + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + for (File root : rootFiles) { + final VirtualFile rootFile = lfs.findFileByIoFile(root); + if (rootFile != null && fileIndex.isInSourceContent(rootFile)) { + filesToRefresh.add(rootFile); + } + } + if (!filesToRefresh.isEmpty()) { + lfs.refreshFiles(filesToRefresh, true, true, null); + } + } + }); } - if (!filesToRefresh.isEmpty()) { - lfs.refreshFiles(filesToRefresh, true, true, null); - } - } - }); + }); + } } @Override diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java index d1c5d9bec832..697bf0e0e8a6 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java @@ -651,10 +651,11 @@ public class HighlightControlFlowUtil { return null; } } - if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && isEffectivelyFinal(variable, innerClass, context)) { + final boolean isToBeEffectivelyFinal = languageLevel.isAtLeast(LanguageLevel.JDK_1_8); + if (isToBeEffectivelyFinal && isEffectivelyFinal(variable, innerClass, context)) { return null; } - final String description = JavaErrorMessages.message("variable.must.be.final", context.getText()); + final String description = JavaErrorMessages.message(isToBeEffectivelyFinal ? "variable.must.be.final.or.effectively.final" : "variable.must.be.final", context.getText()); final HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(context).descriptionAndTooltip(description).create(); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index 83af5606d8c8..d00fd30209f1 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -915,7 +915,8 @@ public class HighlightMethodUtil { PsiType paramType = i < parameters.length && parameters[i] != null ? substitutor.substitute(parameters[i].getType()) : null; - return paramType != null && TypeConversionUtil.areTypesAssignmentCompatible(paramType, expression); + PsiType expressionType = expression.getType(); + return paramType != null && expressionType != null && TypeConversionUtil.isAssignable(paramType, expressionType); } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java index c5763cc2691e..1e03e711a72c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java @@ -79,6 +79,7 @@ public class CreateFromUsageUtils { private static final Logger LOG = Logger.getInstance( "#com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils"); private static final int MAX_GUESSED_MEMBERS_COUNT = 10; + private static final int MAX_RAW_GUESSED_MEMBERS_COUNT = 2 * MAX_GUESSED_MEMBERS_COUNT; public static boolean isValidReference(PsiReference reference, boolean unresolvedOnly) { if (!(reference instanceof PsiJavaReference)) return false; @@ -671,12 +672,12 @@ public class CreateFromUsageUtils { final PsiShortNamesCache cache = PsiShortNamesCache.getInstance(expression.getProject()); PsiElementFactory factory = facade.getElementFactory(); for (String fieldName : expectedFieldNames) { - PsiField[] fields = cache.getFieldsByName(fieldName, resolveScope); + PsiField[] fields = cache.getFieldsByNameIfNotMoreThan(fieldName, resolveScope, MAX_RAW_GUESSED_MEMBERS_COUNT); addMemberInfo(fields, expression, typesList, factory); } for (String methodName : expectedMethodNames) { - PsiMethod[] methods = cache.getMethodsByName(methodName, resolveScope); + PsiMethod[] methods = cache.getMethodsByNameIfNotMoreThan(methodName, resolveScope, MAX_RAW_GUESSED_MEMBERS_COUNT); addMemberInfo(methods, expression, typesList, factory); } } @@ -723,12 +724,12 @@ public class CreateFromUsageUtils { final PsiShortNamesCache cache = PsiShortNamesCache.getInstance(expression.getProject()); PsiElementFactory factory = facade.getElementFactory(); for (String fieldName : expectedFieldNames) { - PsiField[] fields = cache.getFieldsByName(fieldName, resolveScope); + PsiField[] fields = cache.getFieldsByNameIfNotMoreThan(fieldName, resolveScope, MAX_RAW_GUESSED_MEMBERS_COUNT); addMemberInfo(fields, expression, typesList, factory); } for (String methodName : expectedMethodNames) { - PsiMethod[] methods = cache.getMethodsByName(methodName, resolveScope); + PsiMethod[] methods = cache.getMethodsByNameIfNotMoreThan(methodName, resolveScope, MAX_RAW_GUESSED_MEMBERS_COUNT); addMemberInfo(methods, expression, typesList, factory); } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ClassElement.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ClassElement.java index 14d72a92da1c..35700b5dab35 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ClassElement.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ClassElement.java @@ -26,6 +26,7 @@ import com.intellij.psi.impl.source.tree.*; import com.intellij.psi.tree.ChildRoleBase; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.CharTable; import org.jetbrains.annotations.NotNull; @@ -111,6 +112,9 @@ public class ClassElement extends CompositeElement implements Constants { for (ASTNode run = anchor; run != null; run = run.getTreeNext()) { if (run == semicolonPlace) { anchor = before.booleanValue() ? semicolonPlace.getTreeNext() : semicolonPlace; + if (anchor != null && PsiImplUtil.isWhitespaceOrComment(anchor)) { + anchor = PsiTreeUtil.skipSiblingsForward(anchor.getPsi(), PsiWhiteSpace.class, PsiComment.class).getNode(); + } break; } } diff --git a/java/java-psi-impl/src/messages/JavaErrorMessages.properties b/java/java-psi-impl/src/messages/JavaErrorMessages.properties index e4e2303a2be4..f8712565c0ec 100644 --- a/java/java-psi-impl/src/messages/JavaErrorMessages.properties +++ b/java/java-psi-impl/src/messages/JavaErrorMessages.properties @@ -134,6 +134,7 @@ variable.already.assigned=Variable ''{0}'' might already have been assigned to variable.assigned.in.loop=Variable ''{0}'' might be assigned in loop assignment.to.final.variable=Cannot assign a value to final variable ''{0}'' variable.must.be.final=Variable ''{0}'' is accessed from within inner class, needs to be declared final +variable.must.be.final.or.effectively.final=Variable ''{0}'' is accessed from within inner class, needs to be final or effectively final initializer.must.be.able.to.complete.normally=Initializer must be able to complete normally weaker.privileges={0}; attempting to assign weaker access privileges (''{1}''); was ''{2}'' incompatible.return.type=attempting to use incompatible return type diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java index 001b1f39c494..deae737d9853 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java @@ -108,7 +108,7 @@ class ParameterIsEffectivelyFinal { new Runnable() { @Override public void run() { - System.out.println(o); + System.out.println(o); } }.run(); return 0; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromParameter/afterEnumComments.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromParameter/afterEnumComments.java new file mode 100644 index 000000000000..218e3ffcc412 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromParameter/afterEnumComments.java @@ -0,0 +1,12 @@ +// "Create Field for Parameter 'p1'" "true" + +enum Test{ + A;//comment + + private int myP1; + + void f(int p1){ + myP1 = p1; + } +} + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromParameter/beforeEnumComments.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromParameter/beforeEnumComments.java new file mode 100644 index 000000000000..1de861c06b9b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromParameter/beforeEnumComments.java @@ -0,0 +1,9 @@ +// "Create Field for Parameter 'p1'" "true" + +enum Test{ + A;//comment + + void f(int p1){ + } +} + diff --git a/java/java-tests/testData/compileServer/incremental/membersChange/addMethod.log b/java/java-tests/testData/compileServer/incremental/membersChange/addMethod.log index 316e4be06caa..9e0611c49b3a 100644 --- a/java/java-tests/testData/compileServer/incremental/membersChange/addMethod.log +++ b/java/java-tests/testData/compileServer/incremental/membersChange/addMethod.log @@ -5,8 +5,10 @@ Compiling files: src/A.java End of files Cleaning output files: +out/production/AddMethod/C.class out/production/AddMethod/D.class End of files Compiling files: +src/C.java src/D.java End of files diff --git a/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod.log b/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod.log new file mode 100644 index 000000000000..424b39bc3bd2 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod.log @@ -0,0 +1,14 @@ +Cleaning output files: +out/production/AddVarargMethod/A.class +End of files +Compiling files: +src/A.java +End of files +Cleaning output files: +out/production/AddVarargMethod/C.class +out/production/AddVarargMethod/D.class +End of files +Compiling files: +src/C.java +src/D.java +End of files diff --git a/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod/src/A.java b/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod/src/A.java new file mode 100644 index 000000000000..eee8a41d0deb --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod/src/A.java @@ -0,0 +1,9 @@ +public class A { + void f (String x, Integer y) { + + } + + void f (String x, Integer y, Long z, String... v){ + + } +} diff --git a/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod/src/A.java.new b/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod/src/A.java.new new file mode 100644 index 000000000000..1b7d9e4bdbd8 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod/src/A.java.new @@ -0,0 +1,9 @@ +public class A { + void f (String x, Integer y, String... v) { + + } + + void f (String x, Integer y, Long z, String... v){ + + } +} diff --git a/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod/src/C.java b/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod/src/C.java new file mode 100644 index 000000000000..4aa7df6d14a0 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod/src/C.java @@ -0,0 +1,5 @@ +public class C { + void f (A a){ + a.f("1", 2); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod/src/D.java b/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod/src/D.java new file mode 100644 index 000000000000..8c9dba5c485c --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/membersChange/addVarargMethod/src/D.java @@ -0,0 +1,5 @@ +public class D { + void f(A a){ + a.f("1", 2, null, "comment"); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java index d7b123839b3a..5f606082970e 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java @@ -75,12 +75,13 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { public void testNestedCallsInsideLambdaReturnExpression() { doTest(); } public void testIDEA123731() { doTest(); } public void testIDEA123869() { doTest(); } + @Bombed(day = 30, month = Calendar.NOVEMBER) public void testIDEA123848() { doTest(); } public void testOnlyLambdaAtTypeParameterPlace() { doTest(); } public void testLiftedIntersectionType() { doTest(); } public void testInferenceFromReturnStatements() { doTest(); } public void testDownUpThroughLambdaReturnStatements() { doTest(); } - @Bombed(day = 30, month = Calendar.OCTOBER) + @Bombed(day = 30, month = Calendar.NOVEMBER) public void testIDEA124547() { doTest(); } public void testIDEA118362() { doTest(); } public void testIDEA126056() { doTest(); } @@ -134,7 +135,7 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } - @Bombed(month = Calendar.OCTOBER, day = 30) + @Bombed(month = Calendar.NOVEMBER, day = 30) public void testCheckedExceptionsConstraintsSubstitutions() throws Exception { doTest(); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java index 01013e05186a..137f4527b5a8 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java @@ -173,7 +173,7 @@ class ClassfileAnalyzer { } myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, myType.className, methodDescr)); - myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, myType.className, methodDescr)); + myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, myType.className)); myUsedArguments.add(methodName); } @@ -183,7 +183,7 @@ class ClassfileAnalyzer { final String methodDescr = "()" + desc; myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, myType.className, methodDescr)); - myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, myType.className, methodDescr)); + myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, myType.className)); myUsedArguments.add(methodName); } @@ -526,7 +526,7 @@ class ClassfileAnalyzer { final int methodOwner = myContext.get(owner); myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, methodOwner, desc)); - myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, methodOwner, desc)); + myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, methodOwner)); addClassUsage(TypeRepr.getType(myContext, Type.getReturnType(desc))); super.visitMethodInsn(opcode, owner, name, desc, itf); diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java index 3274a7ef896c..612adb06e27d 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java @@ -400,16 +400,31 @@ public class Mappings { private boolean hasOverriddenMethods(final ClassRepr fromClass, final MethodRepr.Predicate predicate) { for (int superName : fromClass.getSupers()) { - final ClassRepr superClass = reprByName(superName); - if (superClass == null) { - return true; // assumption + if (superName == myObjectClassName) { + continue; } - for (MethodRepr mm : superClass.findMethods(predicate)) { - if (isVisibleIn(superClass, mm, fromClass)) { + final ClassRepr superClass = reprByName(superName); + if (superClass != null) { + for (MethodRepr mm : superClass.findMethods(predicate)) { + if (isVisibleIn(superClass, mm, fromClass)) { + return true; + } + } + if (hasOverriddenMethods(superClass, predicate)) { return true; } } - if (hasOverriddenMethods(superClass, predicate)) { + } + return false; + } + + private boolean extendsLibraryClass(final ClassRepr fromClass) { + for (int superName : fromClass.getSupers()) { + if (superName != myObjectClassName) { + continue; + } + final ClassRepr superClass = reprByName(superName); + if (superClass == null || extendsLibraryClass(superClass)) { return true; } } @@ -440,6 +455,9 @@ public class Mappings { void addOverriddenFields(final FieldRepr f, final ClassRepr fromClass, final Collection> container) { for (int supername : fromClass.getSupers()) { + if (supername == myObjectClassName) { + continue; + } final ClassRepr superClass = reprByName(supername); if (superClass != null) { final FieldRepr ff = superClass.findField(f.name); @@ -455,6 +473,9 @@ public class Mappings { boolean hasOverriddenFields(final FieldRepr f, final ClassRepr fromClass) { for (int supername : fromClass.getSupers()) { + if (supername == myObjectClassName) { + continue; + } final ClassRepr superClass = reprByName(supername); if (superClass != null) { final FieldRepr ff = superClass.findField(f.name); @@ -534,15 +555,8 @@ public class Mappings { return Boolean.FALSE; } - boolean isMethodVisible(final int className, final MethodRepr m) { - final ClassRepr r = reprByName(className); - if (r != null) { - if (r.findMethods(MethodRepr.equalByJavaRules(m)).size() > 0) { - return true; - } - return hasOverriddenMethods(r, MethodRepr.equalByJavaRules(m)); - } - return false; + boolean isMethodVisible(final ClassRepr classRepr, final MethodRepr m) { + return classRepr.findMethods(MethodRepr.equalByJavaRules(m)).size() > 0 || hasOverriddenMethods(classRepr, MethodRepr.equalByJavaRules(m)); } boolean isFieldVisible(final int className, final FieldRepr field) { @@ -1082,10 +1096,7 @@ public class Mappings { } final ClassRepr oldIt = oldItRef.get(); - if (oldIt != null && myPresent.hasOverriddenMethods(oldIt, MethodRepr.equalByJavaRules(m))) { - - } - else { + if (oldIt == null || !myPresent.hasOverriddenMethods(oldIt, MethodRepr.equalByJavaRules(m))) { if (m.myArgumentTypes.length > 0) { propagated = myFuture.propagateMethodAccess(m, it.name); debug("Conservative case on overriding methods, affecting method usages"); @@ -1170,10 +1181,13 @@ public class Mappings { final Collection sourceFileNames = myClassToSourceFile.get(subClass); if (sourceFileNames != null && !myCompiledFiles.containsAll(sourceFileNames)) { final int outerClass = r.getOuterClassName(); - if (!isEmpty(outerClass) && myFuture.isMethodVisible(outerClass, m)) { - myAffectedFiles.addAll(sourceFileNames); - for (File sourceFileName : sourceFileNames) { - debug("Affecting file due to local overriding: ", sourceFileName); + if (!isEmpty(outerClass)) { + final ClassRepr outerClassRepr = myFuture.reprByName(outerClass); + if (outerClassRepr != null && (myFuture.isMethodVisible(outerClassRepr, m) || myFuture.extendsLibraryClass(outerClassRepr))) { + myAffectedFiles.addAll(sourceFileNames); + for (File sourceFileName : sourceFileNames) { + debug("Affecting file due to local overriding: ", sourceFileName); + } } } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java index fea3d8a3d8d8..1338bca67e08 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java @@ -112,8 +112,8 @@ class MethodRepr extends ProtoMember { public void updateClassUsages(final DependencyContext context, final int owner, final Set s) { myType.updateClassUsages(context, owner, s); - for (int i = 0; i < myArgumentTypes.length; i++) { - myArgumentTypes[i].updateClassUsages(context, owner, s); + for (final TypeRepr.AbstractType argType : myArgumentTypes) { + argType.updateClassUsages(context, owner, s); } if (myExceptions != null) { @@ -124,17 +124,17 @@ class MethodRepr extends ProtoMember { } public MethodRepr(final DependencyContext context, - final int a, - final int n, - final int s, - final String d, - final String[] e, - final Object value) { - super(a, s, n, TypeRepr.getType(context, Type.getReturnType(d)), value); + final int accessFlags, + final int name, + final int signature, + final String descriptor, + final String[] exceptions, + final Object defaultValue) { + super(accessFlags, signature, name, TypeRepr.getType(context, Type.getReturnType(descriptor)), defaultValue); Set typeCollection = - e != null ? new THashSet(e.length) : Collections.emptySet(); - myExceptions = (Set)TypeRepr.createClassType(context, e, typeCollection); - myArgumentTypes = TypeRepr.getType(context, Type.getArgumentTypes(d)); + exceptions != null ? new THashSet(exceptions.length) : Collections.emptySet(); + myExceptions = (Set)TypeRepr.createClassType(context, exceptions, typeCollection); + myArgumentTypes = TypeRepr.getType(context, Type.getArgumentTypes(descriptor)); } public MethodRepr(final DependencyContext context, final DataInput in) { @@ -216,7 +216,7 @@ class MethodRepr extends ProtoMember { } public UsageRepr.Usage createMetaUsage(final DependencyContext context, final int owner) { - return UsageRepr.createMetaMethodUsage(context, name, owner, getDescr(context)); + return UsageRepr.createMetaMethodUsage(context, name, owner); } @Override diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java index e7b376980fae..d6d3ff799a7b 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java @@ -278,52 +278,18 @@ class UsageRepr { } public static class MetaMethodUsage extends FMUsage { - private int myArity; - public MetaMethodUsage(final DependencyContext context, final int n, final int o, final String descr) { + public MetaMethodUsage(final int n, final int o) { super(n, o); - myArity = TypeRepr.getType(context, Type.getArgumentTypes(descr)).length; } public MetaMethodUsage(final DataInput in) { super(in); - try { - myArity = DataInputOutputUtil.readINT(in); - } - catch (IOException e) { - throw new BuildDataCorruptedException(e); - } } @Override public void save(final DataOutput out) { save(METAMETHOD_USAGE, out); - try { - DataInputOutputUtil.writeINT(out, myArity); - } - catch (IOException e) { - throw new BuildDataCorruptedException(e); - } - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - - MetaMethodUsage that = (MetaMethodUsage)o; - - if (myArity != that.myArity) return false; - - return super.equals(o); - } - - @Override - public int hashCode() { - int result = super.hashCode(); - result = 31 * result + myArity; - return result; } @Override @@ -334,7 +300,6 @@ class UsageRepr { @Override public void toStream(DependencyContext context, PrintStream stream) { super.toStream(context, stream); - stream.println(" Arity: " + Integer.toString(myArity)); } } @@ -679,8 +644,8 @@ class UsageRepr { return context.getUsage(new MethodUsage(context, name, owner, descr)); } - public static Usage createMetaMethodUsage(final DependencyContext context, final int name, final int owner, final String descr) { - return context.getUsage(new MetaMethodUsage(context, name, owner, descr)); + public static Usage createMetaMethodUsage(final DependencyContext context, final int name, final int owner) { + return context.getUsage(new MetaMethodUsage(name, owner)); } public static Usage createClassUsage(final DependencyContext context, final int name) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java index a6ed636e8d11..9a40498ec619 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java @@ -42,7 +42,7 @@ import java.util.concurrent.ConcurrentMap; * Date: 10/7/11 */ public class BuildDataManager implements StorageOwner { - private static final int VERSION = 25; + private static final int VERSION = 26; private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildDataManager"); private static final String SRC_TO_FORM_STORAGE = "src-form"; private static final String OUT_TARGET_STORAGE = "out-target"; diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java index 90ecb820bbc6..3866756a0929 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java @@ -203,4 +203,8 @@ public class MemberChangeTest extends IncrementalTestCase { public void testAddMethod() { doTest(); } + + public void testAddVarargMethod() { + doTest(); + } } diff --git a/native/fsNotifier/mac/make.sh b/native/fsNotifier/mac/make.sh index fbc17c8f77c8..3869c599b820 100755 --- a/native/fsNotifier/mac/make.sh +++ b/native/fsNotifier/mac/make.sh @@ -1,3 +1,3 @@ #!/bin/sh # Clang can be downloaded from http://llvm.org/releases/download.html or found in XCode 4+ -clang -arch i386 -mmacosx-version-min=10.5 -framework CoreServices -o fsnotifier fsnotifier.c +clang -arch i386 -arch x86_64 -mmacosx-version-min=10.5 -framework CoreServices -o fsnotifier fsnotifier.c diff --git a/platform/icons/src/Logo_welcomeScreen.png b/platform/icons/src/Logo_welcomeScreen.png index 211668560d0f..9023c4285eba 100644 Binary files a/platform/icons/src/Logo_welcomeScreen.png and b/platform/icons/src/Logo_welcomeScreen.png differ diff --git a/platform/icons/src/Logo_welcomeScreen@2x.png b/platform/icons/src/Logo_welcomeScreen@2x.png index 1cc67984967c..2ef76b6c829c 100644 Binary files a/platform/icons/src/Logo_welcomeScreen@2x.png and b/platform/icons/src/Logo_welcomeScreen@2x.png differ diff --git a/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java b/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java index dfbaa33999fb..7c3e91f78394 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java @@ -19,6 +19,7 @@ import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Conditions; import com.intellij.openapi.util.Ref; import com.intellij.openapi.wm.ToolWindow; import com.intellij.ui.content.Content; @@ -26,9 +27,8 @@ import com.intellij.ui.content.ContentManager; import com.intellij.ui.content.ContentManagerAdapter; import com.intellij.ui.content.ContentManagerEvent; import com.intellij.ui.switcher.QuickActionProvider; -import com.intellij.ui.tabs.JBTabs; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.AwtVisitor; +import com.intellij.util.ui.JBSwingUtilities; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -38,7 +38,6 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ContainerAdapter; import java.awt.event.ContainerEvent; -import java.util.LinkedList; import java.util.List; public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider, DataProvider { @@ -199,14 +198,6 @@ public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider component instanceof DataProvider ? PlatformDataKeys.CONTENT_MANAGER.getData((DataProvider)component) : null; if (contentManager != null) contentManager.addContentManagerListener(this); } - - @Override - public void selectionChanged(ContentManagerEvent event) { - Content content = event.getContent(); - if (content != null) { - setContentToolbarVisible(content.getComponent(), getVisibilityValue()); - } - } }); } @@ -233,18 +224,8 @@ public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider } private static void setContentToolbarVisible(@NotNull JComponent root, boolean state) { - LinkedList deque = ContainerUtil.newLinkedList(root); - while(!deque.isEmpty()) { - JComponent component = deque.pollFirst(); - for (int i = 0, count = component.getComponentCount(); i < count; i++) { - Component c = component.getComponent(i); - if (c instanceof ActionToolbar) { - c.setVisible(state); - } - else if (c instanceof JPanel || c instanceof JLayeredPane || c instanceof JBTabs) { - deque.addLast((JComponent)c); - } - } + for (Component c : JBSwingUtilities.uiTraverser().preOrderTraversal(root).filter(Conditions.instanceOf(ActionToolbar.class))) { + c.setVisible(state); } } } diff --git a/platform/platform-api/src/com/intellij/ui/components/OrphanGuardian.java b/platform/platform-api/src/com/intellij/ui/components/OrphanGuardian.java deleted file mode 100644 index c8a044c16a3c..000000000000 --- a/platform/platform-api/src/com/intellij/ui/components/OrphanGuardian.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.intellij.ui.components; - -import com.intellij.openapi.util.Key; -import com.intellij.util.Consumer; - -import javax.swing.*; - -/** - * @author gregsh - */ -public interface OrphanGuardian { - Key CLIENT_PROPERTY_KEY = Key.create("OrphanGuardian"); - - void iterateOrphans(Consumer processor); -} diff --git a/platform/platform-api/src/com/intellij/ui/components/labels/ActionLink.java b/platform/platform-api/src/com/intellij/ui/components/labels/ActionLink.java index a4f278539dd4..4a790facf2ee 100644 --- a/platform/platform-api/src/com/intellij/ui/components/labels/ActionLink.java +++ b/platform/platform-api/src/com/intellij/ui/components/labels/ActionLink.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import com.intellij.util.ui.EmptyIcon; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -41,7 +42,12 @@ public class ActionLink extends LinkLabel implements DataProvider { public ActionLink(String text, @NotNull AnAction action) { this(text, ICON, action); } + public ActionLink(String text, Icon icon, @NotNull AnAction action) { + this(text, icon, action, null); + } + + public ActionLink(String text, Icon icon, @NotNull AnAction action, @Nullable final Runnable onDone) { super(text, icon); setListener(new LinkListener() { @Override @@ -56,6 +62,9 @@ public class ActionLink extends LinkLabel implements DataProvider { myAction.update(event); if (event.getPresentation().isEnabled() && event.getPresentation().isVisible()) { myAction.actionPerformed(event); + if (onDone != null) { + onDone.run(); + } } } }, null); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index 97c158e08d9f..56df43a94eaf 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -28,7 +28,6 @@ import com.intellij.openapi.wm.*; import com.intellij.ui.*; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.awt.RelativeRectangle; -import com.intellij.ui.components.OrphanGuardian; import com.intellij.ui.switcher.QuickActionProvider; import com.intellij.ui.switcher.SwitchProvider; import com.intellij.ui.switcher.SwitchTarget; @@ -37,13 +36,10 @@ import com.intellij.ui.tabs.impl.singleRow.SingleRowLayout; import com.intellij.ui.tabs.impl.singleRow.SingleRowPassInfo; import com.intellij.ui.tabs.impl.table.TableLayout; import com.intellij.ui.tabs.impl.table.TablePassInfo; -import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.ui.Animator; -import com.intellij.util.ui.JBInsets; -import com.intellij.util.ui.TimedDeadzone; -import com.intellij.util.ui.UIUtil; +import com.intellij.util.containers.FluentIterable; +import com.intellij.util.ui.*; import com.intellij.util.ui.update.ComparableObject; import com.intellij.util.ui.update.LazyUiDisposable; import org.jetbrains.annotations.NonNls; @@ -316,16 +312,19 @@ public class JBTabsImpl extends JComponent } } }; - putClientProperty(OrphanGuardian.CLIENT_PROPERTY_KEY, new OrphanGuardian() { - - @Override - public void iterateOrphans(Consumer consumer) { - for (TabInfo info : getVisibleInfos()) { - if (info == mySelectedInfo) continue; - consumer.consume(info.getComponent()); + UIUtil.putClientProperty( + this, JBSwingUtilities.NOT_IN_HIERARCHY_COMPONENTS, new Iterable() { + @Override + public Iterator iterator() { + return FluentIterable.from(getVisibleInfos()).filter(Conditions.not(Conditions.is(mySelectedInfo))).transform( + new Function() { + @Override + public JComponent fun(TabInfo info) { + return info.getComponent(); + } + }).iterator(); } - } - }); + }); } protected SingleRowLayout createSingleRowLayout() { diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedoStacksHolder.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedoStacksHolder.java index 49bb65608450..529fddd24a5d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedoStacksHolder.java +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedoStacksHolder.java @@ -19,6 +19,8 @@ import com.intellij.openapi.command.undo.DocumentReference; import com.intellij.openapi.command.undo.DocumentReferenceManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.Key; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.WeakList; import gnu.trove.THashSet; @@ -41,7 +43,8 @@ class UndoRedoStacksHolder { @NotNull LinkedList getStack(@NotNull DocumentReference r) { - return r.getFile() != null ? doGetStackForFile(r) : doGetStackForDocument(r); + VirtualFile file = r.getFile(); + return file != null && !(file instanceof LightVirtualFile) ? doGetStackForFile(r) : doGetStackForDocument(r); } @NotNull diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 484191e67b07..504e47abb36a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -74,7 +74,6 @@ import com.intellij.ui.*; import com.intellij.ui.components.JBLayeredPane; import com.intellij.ui.components.JBScrollBar; import com.intellij.ui.components.JBScrollPane; -import com.intellij.ui.components.OrphanGuardian; import com.intellij.util.*; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtilRt; @@ -491,16 +490,17 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi myVerticalScrollBar = (MyScrollBar)myScrollPane.getVerticalScrollBar(); myPanel = new JPanel(); - myPanel.putClientProperty(OrphanGuardian.CLIENT_PROPERTY_KEY, new OrphanGuardian() { - - @Override - public void iterateOrphans(Consumer consumer) { - JComponent component = getPermanentHeaderComponent(); - if (component != null && !component.isValid()) { - consumer.consume(component); + UIUtil.putClientProperty( + myPanel, JBSwingUtilities.NOT_IN_HIERARCHY_COMPONENTS, new Iterable() { + @Override + public Iterator iterator() { + JComponent component = getPermanentHeaderComponent(); + if (component != null && !component.isValid()) { + return Collections.singleton(component).iterator(); + } + return ContainerUtil.emptyIterator(); } - } - }); + }); myHeaderPanel = new MyHeaderPanel(); myGutterComponent = new EditorGutterComponentImpl(this); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java index 72f9fbf05459..916c9e796518 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java @@ -17,7 +17,8 @@ package com.intellij.openapi.wm.impl.welcomeScreen; import com.intellij.icons.AllIcons; import com.intellij.ide.DataManager; -import com.intellij.ide.RecentProjectsManager; +import com.intellij.ide.RecentProjectsManagerBase; +import com.intellij.internal.statistic.UsageTrigger; import com.intellij.openapi.Disposable; import com.intellij.openapi.MnemonicHelper; import com.intellij.openapi.actionSystem.*; @@ -88,7 +89,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { setTitle("Welcome to " + ApplicationNamesInfo.getInstance().getFullProductName()); AppUIUtil.updateWindowIcon(this); //Rectangle bounds = ScreenUtil.getMainScreenBounds(); - if (RecentProjectsManager.getInstance().getRecentProjectsActions(false).length > 0) { + if (RecentProjectsManagerBase.getInstance().getRecentProjectsActions(false).length > 0) { setSize(666, 460); } else { setSize(555, 460); @@ -166,23 +167,23 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { public StatusBar getStatusBar() { return null; } - + public static Color getMainBackground() { return new JBColor(0xf7f7f7, 0x45474a); } - + public static Color getProjectsBackground() { return new JBColor(Gray.xFF, Gray.x39); } - + public static Color getLinkNormalColor() { return new JBColor(Gray._0, Gray.xBB); } - + public static Color getListSelectionColor(boolean hasFocus) { return hasFocus ? new JBColor(0x3875d6, 0x4b6eaf) : new JBColor(Gray.xDD, Gray.x45); } - + public static Color getActionLinkSelectionColor() { return new JBColor(0xdbe5f5, 0x485875); } @@ -195,14 +196,14 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { public FlatWelcomeScreen() { super(new BorderLayout()); setBackground(getMainBackground()); - if (RecentProjectsManager.getInstance().getRecentProjectsActions(false).length > 0) { + if (RecentProjectsManagerBase.getInstance().getRecentProjectsActions(false).length > 0) { final JComponent recentProjects = createRecentProjects(); add(recentProjects, BorderLayout.WEST); final JList projectsList = UIUtil.findComponentOfType(recentProjects, JList.class); if (projectsList != null) { projectsList.getModel().addListDataListener(new ListDataListener() { @Override - public void intervalAdded(ListDataEvent e) { + public void intervalAdded(ListDataEvent e) { } @Override @@ -211,7 +212,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { } private void removeIfNeeded() { - if (RecentProjectsManager.getInstance().getRecentProjectsActions(false).length == 0) { + if (RecentProjectsManagerBase.getInstance().getRecentProjectsActions(false).length == 0) { FlatWelcomeScreen.this.remove(recentProjects); FlatWelcomeScreen.this.revalidate(); FlatWelcomeScreen.this.repaint(); @@ -260,7 +261,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { if (register != null) { Presentation presentation = register.getTemplatePresentation(); register.update(new AnActionEvent(null, DataManager.getInstance().getDataContext(this), - ActionPlaces.WELCOME_SCREEN, presentation, ActionManager.getInstance(), 0)); + ActionPlaces.WELCOME_SCREEN, presentation, ActionManager.getInstance(), 0)); if (presentation.isEnabled()) { ActionLink registerLink = new ActionLink("Register", register); registerLink.setNormalColor(getLinkNormalColor()); @@ -279,14 +280,14 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { toolbar.setLayout(new BoxLayout(toolbar, BoxLayout.X_AXIS)); toolbar.add(createActionLink("Configure", IdeActions.GROUP_WELCOME_SCREEN_CONFIGURE, AllIcons.General.GearPlain, !registeredVisible)); toolbar.add(createActionLink("Get Help", IdeActions.GROUP_WELCOME_SCREEN_DOC, null, false)); - + panel.add(toolbar, BorderLayout.EAST); - + panel.setBorder(new EmptyBorder(0,0,8,11)); return panel; } - + private JComponent createActionLink(final String text, final String groupId, Icon icon, boolean focusListOnLeft) { final Ref ref = new Ref(null); AnAction action = new AnAction() { @@ -294,8 +295,10 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { public void actionPerformed(@NotNull AnActionEvent e) { ActionGroup configureGroup = (ActionGroup)ActionManager.getInstance().getAction(groupId); final PopupFactoryImpl.ActionGroupPopup popup = (PopupFactoryImpl.ActionGroupPopup)JBPopupFactory.getInstance() - .createActionGroupPopup(null, new IconsFreeActionGroup(configureGroup), e.getDataContext(), JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, false, ActionPlaces.WELCOME_SCREEN); + .createActionGroupPopup(null, new IconsFreeActionGroup(configureGroup), e.getDataContext(), JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, false, + ActionPlaces.WELCOME_SCREEN); popup.showUnderneathOfLabel(ref.get()); + UsageTrigger.trigger("welcome.screen." + groupId); } }; ref.set(new ActionLink(text, icon, action)); @@ -334,7 +337,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { if (icon.getIconHeight() != 16 || icon.getIconWidth() != 16) { icon = EmptyIcon.ICON_16; } - ActionLink link = new ActionLink(text, icon, action); + ActionLink link = new ActionLink(text, icon, action, createUsageTracker(action)); link.setPaintUnderline(false); link.setNormalColor(getLinkNormalColor()); button.add(link); @@ -374,16 +377,16 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { appName.setFont(font.deriveFont(36f).deriveFont(Font.PLAIN)); appName.setHorizontalAlignment(SwingConstants.CENTER); String appVersion = "Version " + app.getFullVersion(); - + if (app.isEAP() && app.getBuild().getBuildNumber() < Integer.MAX_VALUE) { appVersion += " (" + app.getBuild().asString() + ")"; } - + JLabel version = new JLabel(appVersion); version.setFont(getProductFont().deriveFont(16f)); version.setHorizontalAlignment(SwingConstants.CENTER); version.setForeground(Gray._128); - + panel.add(appName); panel.add(version, BorderLayout.SOUTH); panel.setBorder(new EmptyBorder(0, 0, 20, 0)); @@ -393,9 +396,9 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { private Font getProductFont() { String name = "/fonts/Roboto-Light.ttf"; URL url = AppUIUtil.class.getResource(name); - if (url == null) { - Logger.getInstance(AppUIUtil.class).warn("Resource missing: " + name); - } else { + if (url == null) { + Logger.getInstance(AppUIUtil.class).warn("Resource missing: " + name); + } else { try { InputStream is = url.openStream(); @@ -450,7 +453,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { if (focusListOnLeft) { if (list != null) { list.requestFocus(); - } + } } else { focusPrev(comp); } @@ -533,14 +536,15 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { if (child instanceof ActionGroup) { return new IconsFreeActionGroup((ActionGroup)child); } - - Presentation presentation = child.getTemplatePresentation(); + + Presentation presentation = child.getTemplatePresentation(); return new AnAction(presentation.getText(), presentation.getDescription(), null) { @Override public void actionPerformed(@NotNull AnActionEvent e) { child.actionPerformed(e); + UsageTrigger.trigger("welcome.screen." + e.getActionManager().getId(child)); } @Override @@ -558,6 +562,15 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { } } + private static Runnable createUsageTracker(final AnAction action) { + return new Runnable() { + @Override + public void run() { + UsageTrigger.trigger("welcome.screen." + ActionManager.getInstance().getId(action)); + } + }; + } + private static JLabel createArrow(final ActionLink link) { JLabel arrow = new JLabel(AllIcons.General.Combo3); arrow.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); @@ -613,7 +626,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { public static void notifyFrameClosed(JFrame frame) { saveLocation(frame.getBounds()); } - + public static class WelcomeScreenActionsPanel { private JPanel root; private JPanel actions; diff --git a/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java b/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java index 5660f0ca05d6..30e1e5b58d6d 100644 --- a/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java +++ b/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java @@ -20,7 +20,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.ui.EditorTextField; -import com.intellij.ui.components.OrphanGuardian; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.FilteringIterator; import com.intellij.util.ui.JBSwingUtilities; @@ -230,47 +229,16 @@ public class IJSwingUtilities extends JBSwingUtilities { * @param c component * @see javax.swing.SwingUtilities#updateComponentTreeUI */ - public static void updateComponentTreeUI(Component c) { - updateComponentTreeUI0(c); + public static void updateComponentTreeUI(@Nullable Component c) { + if (c == null) return; + for (Component component : uiTraverser().postOrderTraversal(c)) { + if (component instanceof JComponent) ((JComponent)component).updateUI(); + } c.invalidate(); c.validate(); c.repaint(); } - private static final Consumer UI_TREE_UPDATER = new Consumer() { - @Override - public void consume(JComponent component) { - updateComponentTreeUI0(component); - } - }; - - private static void updateComponentTreeUI0(Component c) { - Component[] children = null; - if (c instanceof JMenu) { - children = ((JMenu)c).getMenuComponents(); - } - else if (c instanceof Container) { - children = ((Container)c).getComponents(); - } - if (children != null) { - for (Component aChildren : children) { - updateComponentTreeUI0(aChildren); - } - } - if (c instanceof JComponent) { - JComponent jc = (JComponent)c; - OrphanGuardian orphans = (OrphanGuardian)jc.getClientProperty(OrphanGuardian.CLIENT_PROPERTY_KEY); - if (orphans != null) { - orphans.iterateOrphans(UI_TREE_UPDATER); - } - jc.updateUI(); - JPopupMenu jpm = jc.getComponentPopupMenu(); - if (jpm != null && jpm.isVisible() && jpm.getInvoker() == jc) { - updateComponentTreeUI(jpm); - } - } - } - public static void moveMousePointerOn(Component component) { if (component != null && component.isShowing()) { UISettings settings = ApplicationManager.getApplication() == null ? null : UISettings.getInstance(); diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index ee5f49e1fb53..96ead9730061 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -514,7 +514,7 @@ message.idea.restart.required=Restart {0} to activate changes in plugins? title.plugins=Plugins title.plugins.changed=Plugins Changed plugin.status.not.specified=(not specified) -error.list.of.plugins.was.not.loaded=List of plugins was not loaded: {0} +error.list.of.plugins.was.not.loaded=Unable to update the list of plugins due to the following error: {0} action.download.and.install.plugin=Download and Install action.update.plugin=Update Plugin error.plugin.download.failed=Plugin download failed diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java index 100abd8650c8..06a61b1da4fc 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java @@ -146,6 +146,7 @@ public class MatcherImpl { visitor.matchContext(matchedNodes); } finally { matchedNodes.reset(); + matchContext.getOptions().setScope(null); } } @@ -440,6 +441,8 @@ public class MatcherImpl { MalformedPatternException exception = new MalformedPatternException(); exception.initCause(e); throw exception; + } finally { + options.setScope(null); } return sink.getMatches(); diff --git a/platform/util-rt/src/com/intellij/openapi/util/Conditions.java b/platform/util-rt/src/com/intellij/openapi/util/Conditions.java index ef3c0d2acbf6..a837d43487e3 100644 --- a/platform/util-rt/src/com/intellij/openapi/util/Conditions.java +++ b/platform/util-rt/src/com/intellij/openapi/util/Conditions.java @@ -26,12 +26,14 @@ import java.util.HashMap; * @author max */ public class Conditions { - private Conditions() {} + private Conditions() { + } @NotNull public static Condition alwaysTrue() { return (Condition)TRUE; } + @NotNull public static Condition alwaysFalse() { return (Condition)FALSE; @@ -67,12 +69,23 @@ public class Conditions { public static Condition not(Condition c) { return new Not(c); } + public static Condition and(Condition c1, Condition c2) { return new And(c1, c2); } + + public static Condition and2(Condition c1, Condition c2) { + return new And(c1, c2); + } + public static Condition or(Condition c1, Condition c2) { return new Or(c1, c2); } + + public static Condition or2(Condition c1, Condition c2) { + return new Or(c1, c2); + } + public static Condition cached(Condition c) { return new SoftRefCache(c); } @@ -89,11 +102,12 @@ public class Conditions { return !myCondition.value(value); } } - private static class And implements Condition { - private final Condition t1; - private final Condition t2; - public And(final Condition t1, final Condition t2) { + private static class And implements Condition { + private final Condition t1; + private final Condition t2; + + public And(Condition t1, Condition t2) { this.t1 = t1; this.t2 = t2; } @@ -103,11 +117,12 @@ public class Conditions { return t1.value(object) && t2.value(object); } } - private static class Or implements Condition { - private final Condition t1; - private final Condition t2; - public Or(final Condition t1, final Condition t2) { + private static class Or implements Condition { + private final Condition t1; + private final Condition t2; + + public Or(Condition t1, Condition t2) { this.t1 = t1; this.t2 = t2; } diff --git a/platform/util/src/com/intellij/util/containers/FluentIterable.java b/platform/util/src/com/intellij/util/containers/FluentIterable.java new file mode 100644 index 000000000000..d6e9d27d9be6 --- /dev/null +++ b/platform/util/src/com/intellij/util/containers/FluentIterable.java @@ -0,0 +1,282 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.containers; + + +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Conditions; +import com.intellij.util.Function; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +/** + * A pruned version of com.google.common.collect.FluentIterable. + *

+ * {@code FluentIterable} provides a rich interface for manipulating {@code Iterable} instances in a + * chained fashion. A {@code FluentIterable} can be created from an {@code Iterable}, or from a set + * of elements. The following types of methods are provided on {@code FluentIterable}: + *

    + *
  • chained methods which return a new {@code FluentIterable} based in some way on the contents + * of the current one (for example {@link #transform}) + *
  • conversion methods which copy the {@code FluentIterable}'s contents into a new collection or + * array (for example {@link #toList}) + *
  • element extraction methods which facilitate the retrieval of certain elements (for example + * {@link #last}) + *
+ *

+ *

Here is an example that merges the lists returned by two separate database calls, transforms + * it by invoking {@code toString()} on each element, and returns the first 10 elements as an + * {@code List}:

   {@code
+ *   FluentIterable
+ *       .from(database.getClientList())
+ *       .filter(activeInLastMonth())
+ *       .transform(Functions.toStringFunction())
+ *       .toList();}
+ *

+ *

Anything which can be done using {@code FluentIterable} could be done in a different fashion + * (often with {@link Iterables}), however the use of {@code FluentIterable} makes many sets of + * operations significantly more concise. + * + * @author Marcin Mikosik + */ +public abstract class FluentIterable implements Iterable { + // We store 'iterable' and use it instead of 'this' to allow Iterables to perform instanceof + // checks on the _original_ iterable when FluentIterable.from is used. + private final Iterable myIterable; + + /** + * Constructor for use by subclasses. + */ + protected FluentIterable() { + myIterable = this; + } + + FluentIterable(@NotNull Iterable iterable) { + myIterable = iterable; + } + + /** + * Returns a fluent iterable that wraps {@code iterable}, or {@code iterable} itself if it + * is already a {@code FluentIterable}. + */ + public static FluentIterable from(final Iterable iterable) { + return iterable instanceof FluentIterable ? (FluentIterable)iterable : + new FluentIterable(iterable) { + @Override + public Iterator iterator() { + return iterable.iterator(); + } + }; + } + + /** + * Returns a fluent iterable containing {@code elements} in the specified order. + */ + public static FluentIterable of(E[] elements) { + return from(ContainerUtil.newArrayList(elements)); + } + + /** + * Returns a string representation of this fluent iterable, with the format + * {@code [e1, e2, ..., en]}. + */ + @Override + public String toString() { + return ContainerUtil.toCollection(myIterable).toString(); + } + + /** + * Returns the number of elements in this fluent iterable. + */ + public final int size() { + int count = 0; + for (E ignored : myIterable) { + count++; + } + return count; + } + + /** + * Returns {@code true} if this fluent iterable contains any object for which + * {@code equals(element)} is true. + */ + public final boolean contains(@Nullable Object element) { + if (myIterable instanceof Collection) { + return ((Collection)myIterable).contains(element); + } + for (E e : myIterable) { + if (Comparing.equal(e, element)) return true; + } + return false; + } + + /** + * Returns a fluent iterable whose iterators traverse first the elements of this fluent iterable, + * followed by those of {@code other}. The iterators are not polled until necessary. + *

+ *

The returned iterable's {@code Iterator} supports {@code remove()} when the corresponding + * {@code Iterator} supports it. + */ + public final FluentIterable append(Iterable other) { + return from(ContainerUtil.concat(myIterable, other)); + } + + /** + * Returns a fluent iterable whose iterators traverse first the elements of this fluent iterable, + * followed by {@code elements}. + */ + public final FluentIterable append(E... elements) { + return append(Arrays.asList(elements)); + } + + /** + * Returns the elements from this fluent iterable that satisfy a condition. The + * resulting fluent iterable's iterator does not support {@code remove()}. + */ + public final FluentIterable filter(final Condition condition) { + return from(new Iterable() { + @Override + public Iterator iterator() { + return FilteringIterator.create(FluentIterable.this.iterator(), condition); + } + }); + } + + /** + * Returns the elements from this fluent iterable that are instances of class {@code type}. + * @param type the type of elements desired + */ + public final FluentIterable filter(Class type) { + //noinspection unchecked + return (FluentIterable)filter(Conditions.instanceOf(type)); + } + + /** + * Returns a fluent iterable that applies {@code function} to each element of this + * fluent iterable. + *

+ *

The returned fluent iterable's iterator supports {@code remove()} if this iterable's + * iterator does. After a successful {@code remove()} call, this fluent iterable no longer + * contains the corresponding element. + */ + @NotNull + public final FluentIterable transform(@NotNull final Function function) { + return from(new Iterable() { + @Override + public Iterator iterator() { + final Iterator iterator = FluentIterable.this.iterator(); + return new Iterator() { + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public T next() { + return function.fun(iterator.next()); + } + + @Override + public void remove() { + iterator.remove(); + } + }; + } + }); + } + + /** + * Returns an {@link Optional} containing the first element in this fluent iterable. + * If the iterable is empty, {@code Optional.absent()} is returned. + */ + @Nullable + public final E first() { + Iterator iterator = myIterable.iterator(); + return iterator.hasNext() ? iterator.next() : null; + } + + /** + * Returns an {@link Optional} containing the last element in this fluent iterable. + * If the iterable is empty, {@code Optional.absent()} is returned. + */ + @Nullable + public final E last() { + if (myIterable instanceof List) { + return ContainerUtil.getLastItem((List)myIterable); + } + Iterator iterator = myIterable.iterator(); + E cur = null; + while (iterator.hasNext()) { + cur = iterator.next(); + } + return cur; + } + + /** + * Determines whether this fluent iterable is empty. + */ + public final boolean isEmpty() { + return !myIterable.iterator().hasNext(); + } + + /** + * Returns an {@code List} containing all of the elements from this fluent iterable in + * proper sequence. + */ + public final List toList() { + return Collections.unmodifiableList(ContainerUtil.newArrayList(myIterable)); + } + + /** + * Returns an {@code Set} containing all of the elements from this fluent iterable with + * duplicates removed. + */ + public final Set toSet() { + return Collections.unmodifiableSet(ContainerUtil.newHashSet(myIterable)); + } + + /** + * Returns an {@code Map} for which the elements of this {@code FluentIterable} are the keys in + * the same order, mapped to values by the given function. If this iterable contains duplicate + * elements, the returned map will contain each distinct element once in the order it first + * appears. + */ + public final Map toMap(Convertor valueFunction) { + return Collections.unmodifiableMap(ContainerUtil.newMapFromKeys(iterator(), valueFunction)); + } + + /** + * Copies all the elements from this fluent iterable to {@code collection}. This is equivalent to + * calling {@code Iterables.addAll(collection, this)}. + * + * @param collection the collection to copy elements to + * @return {@code collection}, for convenience + */ + public final > C copyInto(@NotNull C collection) { + if (myIterable instanceof Collection) { + collection.addAll((Collection)myIterable); + } + else { + for (E item : myIterable) { + collection.add(item); + } + } + return collection; + } +} diff --git a/platform/util/src/com/intellij/util/containers/TreeTraverser.java b/platform/util/src/com/intellij/util/containers/TreeTraverser.java new file mode 100644 index 000000000000..6b2912137ea0 --- /dev/null +++ b/platform/util/src/com/intellij/util/containers/TreeTraverser.java @@ -0,0 +1,215 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.containers; + +import com.intellij.util.ObjectUtils; +import com.intellij.util.UnmodifiableIterator; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Iterator; + +/** + * A pruned version of com.google.common.collect.TreeTraverser. + * + * Views elements of a type {@code T} as nodes in a tree, and provides methods to traverse the trees + * induced by this traverser. + * + *

For example, the tree + * + *

          {@code
+ *          h
+ *        / | \
+ *       /  e  \
+ *      d       g
+ *     /|\      |
+ *    / | \     f
+ *   a  b  c       }
+ * + *

can be iterated over in preorder (hdabcegf), postorder (abcdefgh), or breadth-first order + * (hdegabcf). + * + *

Null nodes are strictly forbidden. + * + * @author Louis Wasserman + */ +public abstract class TreeTraverser { + /** + * Returns the children of the specified node. Must not contain null. + */ + public abstract Iterable children(T root); + + /** + * Returns an unmodifiable iterable over the nodes in a tree structure, using pre-order + * traversal. That is, each node's subtrees are traversed after the node itself is returned. + * + *

No guarantees are made about the behavior of the traversal when nodes change while + * iteration is in progress or when the iterators generated by {@link #children} are advanced. + */ + public final FluentIterable preOrderTraversal(@NotNull final T root) { + return new FluentIterable() { + @Override + public Iterator iterator() { + return preOrderIterator(root); + } + }; + } + + Iterator preOrderIterator(@NotNull T root) { + return new PreOrderIterator(root); + } + + private final class PreOrderIterator extends UnmodifiableIterator { + private final Deque> stack; + + PreOrderIterator(@NotNull T root) { + super(null); + this.stack = new ArrayDeque>(); + stack.addLast(new SingletonIterator(root)); + } + + @Override + public boolean hasNext() { + return !stack.isEmpty(); + } + + @Override + public T next() { + Iterator itr = stack.getLast(); // throws NSEE if empty + T result = ObjectUtils.assertNotNull(itr.next()); + if (!itr.hasNext()) { + stack.removeLast(); + } + Iterator childItr = children(result).iterator(); + if (childItr.hasNext()) { + stack.addLast(childItr); + } + return result; + } + } + + /** + * Returns an unmodifiable iterable over the nodes in a tree structure, using post-order + * traversal. That is, each node's subtrees are traversed before the node itself is returned. + * + *

No guarantees are made about the behavior of the traversal when nodes change while + * iteration is in progress or when the iterators generated by {@link #children} are advanced. + */ + public final FluentIterable postOrderTraversal(@NotNull final T root) { + return new FluentIterable() { + @Override + public Iterator iterator() { + return postOrderIterator(root); + } + }; + } + + Iterator postOrderIterator(@NotNull T root) { + return new PostOrderIterator(root); + } + + private static final class PostOrderNode { + final T root; + final Iterator childIterator; + + PostOrderNode(@NotNull T root, @NotNull Iterator childIterator) { + this.root = root; + this.childIterator = childIterator; + } + } + + private final class PostOrderIterator extends UnmodifiableIterator { + private final ArrayDeque> stack; + + PostOrderIterator(T root) { + super(null); + this.stack = new ArrayDeque>(); + stack.addLast(expand(root)); + } + + @Override + public boolean hasNext() { + return !stack.isEmpty(); + } + + @Override + public T next() { + return computeNext(); + } + + private T computeNext() { + while (!stack.isEmpty()) { + PostOrderNode top = stack.getLast(); + if (top.childIterator.hasNext()) { + T child = top.childIterator.next(); + stack.addLast(expand(child)); + } else { + stack.removeLast(); + return top.root; + } + } + return null; + } + + private PostOrderNode expand(T t) { + return new PostOrderNode(t, children(t).iterator()); + } + } + + /** + * Returns an unmodifiable iterable over the nodes in a tree structure, using breadth-first + * traversal. That is, all the nodes of depth 0 are returned, then depth 1, then 2, and so on. + * + *

No guarantees are made about the behavior of the traversal when nodes change while + * iteration is in progress or when the iterators generated by {@link #children} are advanced. + */ + public final FluentIterable breadthFirstTraversal(@NotNull final T root) { + return new FluentIterable() { + @Override + public Iterator iterator() { + return new BreadthFirstIterator(root); + } + }; + } + + private final class BreadthFirstIterator extends UnmodifiableIterator { + private final Deque queue; + + BreadthFirstIterator(@NotNull T root) { + super(null); + this.queue = new ArrayDeque(); + queue.add(root); + } + + @Override + public boolean hasNext() { + return !queue.isEmpty(); + } + + //@Override + public T peek() { + return queue.element(); + } + + @Override + public T next() { + T result = queue.remove(); + ContainerUtil.addAll(queue, children(result)); + return result; + } + } +} diff --git a/platform/util/src/com/intellij/util/ui/JBSwingUtilities.java b/platform/util/src/com/intellij/util/ui/JBSwingUtilities.java index d48aa5fc4ad2..bc9fd3efae95 100644 --- a/platform/util/src/com/intellij/util/ui/JBSwingUtilities.java +++ b/platform/util/src/com/intellij/util/ui/JBSwingUtilities.java @@ -15,13 +15,25 @@ */ package com.intellij.util.ui; +import com.intellij.openapi.util.Key; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.TreeTraverser; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; +import java.util.Arrays; +import java.util.Collections; /** * @author gregsh */ public class JBSwingUtilities { + + public static final Key> NOT_IN_HIERARCHY_COMPONENTS = Key.create("NOT_IN_HIERARCHY_COMPONENTS"); + /** * Replaces SwingUtilities#isLeftMouseButton() for consistency with other button-related methods * @@ -50,4 +62,32 @@ public class JBSwingUtilities { public static boolean isRightMouseButton(MouseEvent anEvent) { return (anEvent.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) > 0; } + + @NotNull + public static TreeTraverser uiTraverser() { + return new TreeTraverser() { + @Override + public Iterable children(Component c) { + Iterable result = ContainerUtil.emptyIterable(); + if (c instanceof JMenu) { + result = Arrays.asList(((JMenu)c).getMenuComponents()); + } + else if (c instanceof Container) { + result = Arrays.asList(((Container)c).getComponents()); + } + if (c instanceof JComponent) { + JComponent jc = (JComponent)c; + Iterable orphans = UIUtil.getClientProperty(jc, NOT_IN_HIERARCHY_COMPONENTS); + if (orphans != null) { + result = ContainerUtil.concat(result, orphans); + } + JPopupMenu jpm = jc.getComponentPopupMenu(); + if (jpm != null && jpm.isVisible() && jpm.getInvoker() == jc) { + result = ContainerUtil.concat(result, Collections.singletonList(jpm)); + } + } + return result; + } + }; + } } diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 1363520875d8..9b3472f2d3ae 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -345,6 +345,10 @@ public class UIUtil { return (T)component.getClientProperty(key); } + public static void putClientProperty(@NotNull JComponent component, @NotNull Key key, T value) { + component.putClientProperty(key, value); + } + public static String getHtmlBody(String text) { int htmlIndex = 6 + text.indexOf(""); if (htmlIndex < 6) { diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcs.java b/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcs.java index c31dddf66aed..63c078802de0 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcs.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcs.java @@ -440,7 +440,9 @@ public abstract class AbstractVcs extends S } public interface RootsConvertor { - List convertRoots(List result); + + @NotNull + List convertRoots(@NotNull List result); } /** diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java index 57754f0190cc..6475fde5a34a 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java @@ -273,6 +273,7 @@ public class NewMappings { return FileUtil.startsWith(systemIndependentPath, mapping.systemIndependentPath()); } + @NotNull public List getMappingsAsFilesUnderVcs(@NotNull AbstractVcs vcs) { final List result = new ArrayList(); final String vcsName = vcs.getName(); diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsVcs2.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsVcs2.java index 5adf458b5369..c44bd3857de1 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsVcs2.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsVcs2.java @@ -354,7 +354,8 @@ public class CvsVcs2 extends AbstractVcs implements TransactionPr @Override public RootsConvertor getCustomConvertor() { return new RootsConvertor() { - public List convertRoots(List result) { + @NotNull + public List convertRoots(@NotNull List result) { return FindAllRootsHelper.findVersionedUnder(result); } }; diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRootsHandler.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgRootsHandler.java index 4aef2c466071..a7ccaf8a931e 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRootsHandler.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgRootsHandler.java @@ -22,6 +22,7 @@ import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcsUtil.VcsUtil; import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.util.HgUtil; @@ -44,8 +45,9 @@ public class HgRootsHandler implements AbstractVcs.RootsConvertor { return ServiceManager.getService(project, HgRootsHandler.class); } + @NotNull @Override - public List convertRoots(List original) { + public List convertRoots(@NotNull List original) { final Set result = new THashSet(original.size()); for (VirtualFile vf : original) { final VirtualFile root = convertRoot(vf); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java index 5c660643dc66..cdf7c05a6c45 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java @@ -191,8 +191,9 @@ public class SvnFileUrlMappingImpl implements SvnFileUrlMapping, PersistentState } } - public List convertRoots(final List result) { - if (ThreadLocalDefendedInvoker.isInside()) return result; + @NotNull + public List convertRoots(@NotNull List result) { + if (ThreadLocalDefendedInvoker.isInside()) return ContainerUtil.newArrayList(result); synchronized (myMonitor) { final List cachedRoots = myMoreRealMapping.getUnderVcsRoots(); @@ -200,11 +201,8 @@ public class SvnFileUrlMappingImpl implements SvnFileUrlMapping, PersistentState if (! lonelyRoots.isEmpty()) { myChecker.reportNoRoots(lonelyRoots); } - if (cachedRoots.isEmpty()) { - // todo +- - return result; - } - return cachedRoots; + + return ContainerUtil.newArrayList(cachedRoots.isEmpty() ? result : cachedRoots); } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/TaskBundle.properties b/plugins/tasks/tasks-core/src/com/intellij/tasks/TaskBundle.properties index 0154b2989ff0..ce617cbf01ca 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/TaskBundle.properties +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/TaskBundle.properties @@ -20,6 +20,6 @@ jira.failure.captcha=Login failed. Enter captcha in web-interface. youtrack.default.query=for: me sort by: updated #Unresolved ## Bugzilla -bugzilla.failure.malformed.response=Cannot decode server response. Check that XMLRPC plugin is enabled. +bugzilla.failure.malformed.response=Cannot decode server response. Check that XML-RPC plugin is enabled. bugzilla.failure.no.version=Cannot find Bugzilla version. Check that URL ends with "xmlrpc.cgi". diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/bugzilla/BugzillaRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/bugzilla/BugzillaRepository.java index af3df55b5397..86a511b166c2 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/bugzilla/BugzillaRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/bugzilla/BugzillaRepository.java @@ -346,7 +346,8 @@ public class BugzillaRepository extends BaseRepositoryImpl { return (T)new XmlRpcClient(getUrl()).execute(new XmlRpcRequest(myMethodName, parameters), myTransport); } catch (XmlRpcClientException e) { - if (e.getMessage().contains("Error decoding XML-RPC response")) { + // Unfortunately there is no standard error code to identify this kind of error in portable way + if (e.getMessage().equals("Error decoding XML-RPC response")) { throw new RequestFailedException(TaskBundle.message("bugzilla.failure.malformed.response"), e); } throw e; diff --git a/python/edu/build/resources/logo.bmp b/python/edu/build/resources/logo.bmp index 9ff6698b8e36..d209849c19af 100644 Binary files a/python/edu/build/resources/logo.bmp and b/python/edu/build/resources/logo.bmp differ diff --git a/python/edu/course-creator/resources/fileTemplates/internal/test_helper.py.ft b/python/edu/course-creator/resources/fileTemplates/internal/test_helper.py.ft index 313b9150c467..c08945e0a747 100644 --- a/python/edu/course-creator/resources/fileTemplates/internal/test_helper.py.ft +++ b/python/edu/course-creator/resources/fileTemplates/internal/test_helper.py.ft @@ -46,9 +46,9 @@ def check_importable_path(path): try: import_file(path) except: - failed("File contains syntax errors", test_file_importable.__name__) + failed("File contains syntax errors", test_file_importable.func_name) return - passed(test_file_importable.__name__) + passed(test_file_importable.func_name) def import_file(path): @@ -126,11 +126,11 @@ def test_text_equals(text, error_text): failed(error_text) -def test_window_text_deleted(error_text="Don't just delete task text"): +def test_answer_placeholders_text_deleted(error_text="Don't just delete task text"): """ - Checks that task windows are not empty + Checks that all answer placeholders are not empty """ - windows = get_task_windows() + windows = get_answer_placeholders() for window in windows: if len(window) == 0: @@ -153,9 +153,9 @@ def passed(name=None): print("#educational_plugin " + name + " test OK") -def get_task_windows(file_name=None): +def get_answer_placeholders(file_name=None): """ - Returns all task windows + Returns all answer placeholders text """ prefix = "#educational_plugin_window = " import os @@ -198,4 +198,4 @@ def run_common_tests(error_text="Please, reload file and try again"): test_file_importable() test_is_not_empty() test_is_initial_text(error_text) - test_window_text_deleted(error_text) \ No newline at end of file + test_answer_placeholders_text_deleted(error_text) \ No newline at end of file diff --git a/python/edu/course-creator/resources/fileTemplates/internal/tests.py.ft b/python/edu/course-creator/resources/fileTemplates/internal/tests.py.ft index 788d6f93c49c..c6e2c659a000 100644 --- a/python/edu/course-creator/resources/fileTemplates/internal/tests.py.ft +++ b/python/edu/course-creator/resources/fileTemplates/internal/tests.py.ft @@ -1,10 +1,10 @@ -from test_helper import run_common_tests, failed, passed, get_task_windows +from test_helper import run_common_tests, failed, passed, get_answer_placeholders -def test_task_windows(): - windows = get_task_windows() - window = windows[0] - if window == "": # TODO: your condition here +def test_answer_placeholders(): + placeholders = get_answer_placeholders() + placeholder = placeholders[0] + if placeholder == "": # TODO: your condition here passed() else: failed() @@ -12,6 +12,6 @@ def test_task_windows(): if __name__ == '__main__': run_common_tests() - # test_task_windows() # TODO: uncomment test call + # test_answer_placeholders() # TODO: uncomment test call diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCEditorFactoryListener.java b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCEditorFactoryListener.java index 24688c4b2709..c61ab10d7332 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCEditorFactoryListener.java +++ b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCEditorFactoryListener.java @@ -88,7 +88,7 @@ public class CCEditorFactoryListener implements EditorFactoryListener { @Override public void handle(ReadOnlyFragmentModificationException e) { - HintManager.getInstance().showErrorHint(myEditor, "Delete task window before editing its borders"); + HintManager.getInstance().showErrorHint(myEditor, "Delete answer placeholder before editing its borders"); } } } diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCAddTaskWindow.java b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCAddTaskWindow.java index 3df30b7a4608..244de123a33d 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCAddTaskWindow.java +++ b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCAddTaskWindow.java @@ -24,7 +24,7 @@ public class CCAddTaskWindow extends DumbAwareAction { private static final Logger LOG = Logger.getInstance(CCAddTaskWindow.class); public CCAddTaskWindow() { - super("Add Problem to Solve", "Add problem to solve", null); + super("Add Answer Placeholder", "Add answer placeholder", null); } diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateCourseArchive.java b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateCourseArchive.java index b5a0292db684..de76d5d287de 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateCourseArchive.java +++ b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCCreateCourseArchive.java @@ -204,7 +204,7 @@ public class CCCreateCourseArchive extends DumbAwareAction { @Override public boolean accept(File pathname) { String name = pathname.getName(); - return !name.contains(".answer") && !name.contains("__pycache__") && !name.contains("_windows"); + return !name.contains(".answer") && !name.contains("__pycache__") && !name.contains("_windows") && !name.contains(".pyc"); } }, null); } diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCDeleteTaskWindow.java b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCDeleteTaskWindow.java index c7d8cd91cf4b..f7245a05fe9f 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCDeleteTaskWindow.java +++ b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCDeleteTaskWindow.java @@ -18,7 +18,7 @@ public class CCDeleteTaskWindow extends CCTaskWindowAction { private static final Logger LOG = Logger.getInstance(CCDeleteTaskWindow.class); public CCDeleteTaskWindow() { - super("Delete Problem","Delete problem", null); + super("Delete Answer Placeholder","Delete answer placeholder", null); } @Override diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCShowTaskWindowDetails.java b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCShowTaskWindowDetails.java index 30ba802dbedc..62baf7c7399f 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCShowTaskWindowDetails.java +++ b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCShowTaskWindowDetails.java @@ -11,7 +11,7 @@ import org.jetbrains.plugins.coursecreator.ui.CreateTaskWindowDialog; public class CCShowTaskWindowDetails extends CCTaskWindowAction { public CCShowTaskWindowDetails() { - super("Show Problem Details", "Show problem details", null); + super("Edit Answer Placeholder", "Edit answer placeholder", null); } @Override diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateTaskWindowDialog.java b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateTaskWindowDialog.java index 213fc55e2cb7..3595e2c28a7b 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateTaskWindowDialog.java +++ b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/ui/CreateTaskWindowDialog.java @@ -18,7 +18,7 @@ import java.io.*; public class CreateTaskWindowDialog extends DialogWrapper { - public static final String TITLE = "Add Problem to Solve"; + public static final String TITLE = "Add Answer Placeholder"; private static final Logger LOG = Logger.getInstance(CreateTaskWindowDialog.class.getName()); private final TaskWindow myTaskWindow; private final CreateTaskWindowPanel myPanel; diff --git a/python/edu/learn-python/resources/META-INF/plugin.xml b/python/edu/learn-python/resources/META-INF/plugin.xml index 62f5bdc6ef85..81eb2cef801f 100644 --- a/python/edu/learn-python/resources/META-INF/plugin.xml +++ b/python/edu/learn-python/resources/META-INF/plugin.xml @@ -3,7 +3,6 @@ com.jetbrains.python.edu.learn-python Educational plugin for PyCharm 1.1 - YourCompany - + - + @@ -55,8 +54,8 @@ description="Refresh current task"/> - + diff --git a/python/edu/learn-python/resources/courses/introduction_course.zip b/python/edu/learn-python/resources/courses/introduction_course.zip index d6a4303a0a0f..d84a8d2a80cb 100644 Binary files a/python/edu/learn-python/resources/courses/introduction_course.zip and b/python/edu/learn-python/resources/courses/introduction_course.zip differ diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyDirectoryProjectGenerator.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyDirectoryProjectGenerator.java index a9630f6f730c..90a4b74521de 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyDirectoryProjectGenerator.java +++ b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyDirectoryProjectGenerator.java @@ -20,6 +20,7 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.vfs.newvfs.NewVirtualFile; import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl; import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter; import com.intellij.openapi.wm.ex.ToolWindowManagerEx; @@ -188,7 +189,6 @@ public class StudyDirectoryProjectGenerator extends PythonProjectGenerator imple final VirtualFile taskDir = firstTask.getTaskDir(myProject); if (taskDir == null) return; final Map taskFiles = firstTask.getTaskFiles(); - VirtualFile activeVirtualFile = null; for (Map.Entry entry : taskFiles.entrySet()) { final String name = entry.getKey(); @@ -204,8 +204,16 @@ public class StudyDirectoryProjectGenerator extends PythonProjectGenerator imple if (activeVirtualFile != null) { final PsiFile file = PsiManager.getInstance(myProject).findFile(activeVirtualFile); ProjectView.getInstance(project).select(file, activeVirtualFile, true); - initialized[0] = true; + } else { + String first = StudyUtils.getFirst(taskFiles.keySet()); + if (first != null) { + NewVirtualFile firstFile = ((VirtualDirectoryImpl)taskDir).refreshAndFindChild(first); + if (firstFile != null) { + FileEditorManager.getInstance(project).openFile(firstFile, true); + } + } } + initialized[0] = true; } }, ModalityState.current(), new Condition() { @Override diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorFactoryListener.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorFactoryListener.java index 30a04dd2f136..fb3fc5f3c6f1 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorFactoryListener.java +++ b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorFactoryListener.java @@ -117,7 +117,7 @@ class StudyEditorFactoryListener implements EditorFactoryListener { @Override public void handle(ReadOnlyFragmentModificationException e) { - HintManager.getInstance().showErrorHint(myEditor, "It's not allowed to delete task windows"); + HintManager.getInstance().showErrorHint(myEditor, "It's not allowed to delete answer placeholders"); } } } diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInstructionPainter.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInstructionPainter.java index 87f1f7a35454..95ecfb49651f 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInstructionPainter.java +++ b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInstructionPainter.java @@ -33,10 +33,10 @@ public class StudyInstructionPainter extends EditorEmptyTextPainter { UIUtil.TextPainter painter = new UIUtil.TextPainter().withLineSpacing(1.5f); painter.appendLine("PyCharm Educational Edition").underlined(new JBColor(Gray._150, Gray._180)); - addAction(painter, "Navigate to the next task window", StudyNextWindowAction.ACTION_ID, StudyNextWindowAction.SHORTCUT2, true); + addAction(painter, "Navigate to the next answer placeholder", StudyNextWindowAction.ACTION_ID, StudyNextWindowAction.SHORTCUT2, true); String shortcut1 = getShortcutText(StudyPrevWindowAction.ACTION_ID, StudyPrevWindowAction.SHORTCUT, false, false); String shortcut2 = getShortcutText(StudyNextWindowAction.ACTION_ID, StudyNextWindowAction.SHORTCUT, false, false); - String text = "Navigate between task windows with " + shortcut1 + + String text = "Navigate between answer placeholders with " + shortcut1 + " and " + shortcut2; painter.appendLine(text).smaller().withBullet(); shortcut1 = getShortcutText(StudyPreviousStudyTaskAction.ACTION_ID, StudyPreviousStudyTaskAction.SHORTCUT, false, false); @@ -44,7 +44,7 @@ public class StudyInstructionPainter extends EditorEmptyTextPainter { painter.appendLine("Navigate between tasks with " + shortcut1 + " and " + shortcut2).smaller().withBullet(); addAction(painter, "Reset current task file", StudyRefreshTaskFileAction.ACTION_ID, StudyRefreshTaskFileAction.SHORTCUT, false); addAction(painter, "Check task", StudyCheckAction.ACTION_ID, StudyCheckAction.SHORTCUT, false); - addAction(painter, "Get hint for the task window", StudyShowHintAction.ACTION_ID, StudyShowHintAction.SHORTCUT, false); + addAction(painter, "Get hint for the answer placeholder", StudyShowHintAction.ACTION_ID, StudyShowHintAction.SHORTCUT, false); painter.appendLine("To see your progress open the 'Course Description' panel").smaller().withBullet(); painter.draw(g, new PairFunction>() { @Override diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextWindowAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextWindowAction.java index 16036a7ba91b..e4d3bb79d7a3 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextWindowAction.java +++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextWindowAction.java @@ -16,7 +16,7 @@ public class StudyNextWindowAction extends StudyWindowNavigationAction { public static final String SHORTCUT2 = "ctrl pressed ENTER"; public StudyNextWindowAction() { - super("NextWindowAction", "Select next window", AllIcons.Actions.Forward); + super("Navigate to the Next Answer Placeholder", "Navigate to the next answer placeholder", AllIcons.Actions.Forward); } @Override diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPrevWindowAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPrevWindowAction.java index 1e602bd059ff..01f6e1688b02 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPrevWindowAction.java +++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPrevWindowAction.java @@ -17,7 +17,7 @@ public class StudyPrevWindowAction extends StudyWindowNavigationAction { public static final String SHORTCUT = "ctrl shift pressed COMMA"; public StudyPrevWindowAction() { - super("PrevWindowAction", "Select previous window", StudyIcons.Prev); + super("Navigate to the Previous Answer Placeholder", "Navigate to the previous answer placeholder", StudyIcons.Prev); } diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyShowHintAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyShowHintAction.java index 7a7c4408f795..c07888519d15 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyShowHintAction.java +++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyShowHintAction.java @@ -28,8 +28,8 @@ import java.io.File; public class StudyShowHintAction extends DumbAwareAction { public static final String ACTION_ID = "ShowHintAction"; public static final String SHORTCUT = "ctrl pressed 7"; - public static final String OUTSIDE_TASK_WINDOW_MESSAGE = "Put caret to the task window to get hint."; - public static final String HINT_NOT_AVAILABLE = "There is no hint for this task window"; + public static final String OUTSIDE_TASK_WINDOW_MESSAGE = "Put caret to answer placeholder to get hint"; + public static final String HINT_NOT_AVAILABLE = "There is no hint for this answer placeholder"; public StudyShowHintAction() { super("Show hint", "Show hint", StudyIcons.ShowHint); diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyDirectoryNode.java b/python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyDirectoryNode.java index bb23f5e918fc..4bd8df9baee7 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyDirectoryNode.java +++ b/python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyDirectoryNode.java @@ -19,7 +19,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; -import java.util.Set; +import java.util.Map; public class StudyDirectoryNode extends PsiDirectoryNode { private final PsiDirectory myValue; @@ -144,15 +144,24 @@ public class StudyDirectoryNode extends PsiDirectoryNode { FileEditorManager.getInstance(myProject).closeFile(openFile); } VirtualFile child = null; - Set fileNames = task.getTaskFiles().keySet(); - for (String name : fileNames) { - child = taskDir.findChild(name); - if (child != null) { - FileEditorManager.getInstance(myProject).openFile(child, true); + Map taskFiles = task.getTaskFiles(); + for (Map.Entry entry: taskFiles.entrySet()) { + VirtualFile file = taskDir.findChild(entry.getKey()); + if (file != null) { + FileEditorManager.getInstance(myProject).openFile(file, true); + } + if (!entry.getValue().getTaskWindows().isEmpty()) { + child = file; } } if (child != null) { ProjectView.getInstance(myProject).select(child, child, false); + FileEditorManager.getInstance(myProject).openFile(child, true); + } else { + VirtualFile[] children = taskDir.getChildren(); + if (children.length > 0) { + ProjectView.getInstance(myProject).select(children[0], children[0], false); + } } } } diff --git a/python/helpers/pydev/import_hook.py b/python/helpers/pydev/pydev_import_hook.py similarity index 100% rename from python/helpers/pydev/import_hook.py rename to python/helpers/pydev/pydev_import_hook.py diff --git a/python/helpers/pydev/pydev_ipython/matplotlibtools.py b/python/helpers/pydev/pydev_ipython/matplotlibtools.py index 075c43781ab3..31a7f06fb994 100644 --- a/python/helpers/pydev/pydev_ipython/matplotlibtools.py +++ b/python/helpers/pydev/pydev_ipython/matplotlibtools.py @@ -1,6 +1,5 @@ import sys -from import_hook import import_hook_manager backends = {'tk': 'TkAgg', 'gtk': 'GTKAgg', @@ -57,6 +56,16 @@ def patch_use(interpreter): setattr(matplotlib, "use", patched_use) +def patch_is_interactive(): + """ Patch matplotlib function 'use' """ + matplotlib = sys.modules['matplotlib'] + def patched_is_interactive(): + return matplotlib.rcParams['interactive'] + + setattr(matplotlib, "real_is_interactive", getattr(matplotlib, "is_interactive")) + setattr(matplotlib, "is_interactive", patched_is_interactive) + + def activate_matplotlib(interpreter): """Set interactive to True for interactive backends.""" def activate_matplotlib_inner(): @@ -73,13 +82,10 @@ def activate_matplotlib(interpreter): sys.stdout.write("Backend %s is non-interactive backend. Turning interactive mode off.\n" % backend) matplotlib.interactive(False) patch_use(interpreter) + patch_is_interactive() return activate_matplotlib_inner -def init_matplotlib(interpreter): - import_hook_manager.add_module_name("matplotlib", activate_matplotlib(interpreter)) - - def flag_calls(func): """Wrap a function to detect and flag when it gets called. @@ -116,17 +122,9 @@ def activate_pylab(): pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive) -def init_pylab(): - import_hook_manager.add_module_name("pylab", activate_pylab) - - def activate_pyplot(): pyplot = sys.modules['matplotlib.pyplot'] pyplot.show._needmain = False # We need to detect at runtime whether show() is called by the user. # For this, we wrap it into a decorator which adds a 'called' flag. pyplot.draw_if_interactive = flag_calls(pyplot.draw_if_interactive) - - -def init_pyplot(): - import_hook_manager.add_module_name("pyplot", activate_pyplot) \ No newline at end of file diff --git a/python/helpers/pydev/pydevconsole.py b/python/helpers/pydev/pydevconsole.py index b38847a82925..f48f975f703f 100644 --- a/python/helpers/pydev/pydevconsole.py +++ b/python/helpers/pydev/pydevconsole.py @@ -171,10 +171,11 @@ def process_exec_queue(interpreter): set_return_control_callback(return_control) - from pydev_ipython.matplotlibtools import init_matplotlib, init_pylab, init_pyplot - init_matplotlib(interpreter) - init_pylab() - init_pyplot() + from pydev_import_hook import import_hook_manager + from pydev_ipython.matplotlibtools import activate_matplotlib, activate_pylab, activate_pyplot + import_hook_manager.add_module_name("matplotlib", activate_matplotlib(interpreter)) + import_hook_manager.add_module_name("pylab", activate_pylab) + import_hook_manager.add_module_name("pyplot", activate_pyplot) while 1: # Running the request may have changed the inputhook in use diff --git a/python/src/com/jetbrains/python/inspections/PyPep8NamingInspection.java b/python/src/com/jetbrains/python/inspections/PyPep8NamingInspection.java index 9cdd4b036aea..17780edb50b6 100644 --- a/python/src/com/jetbrains/python/inspections/PyPep8NamingInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyPep8NamingInspection.java @@ -20,47 +20,50 @@ import com.intellij.codeInspection.ProblemsHolder; import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; import com.intellij.lang.ASTNode; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.QualifiedName; -import com.intellij.util.containers.hash.HashMap; +import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache; import com.jetbrains.python.codeInsight.dataflow.scope.Scope; import com.jetbrains.python.inspections.quickfix.PyRenameElementQuickFix; import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.PyBuiltinCache; import com.jetbrains.python.psi.search.PySuperMethodsSearch; +import com.jetbrains.python.sdk.PythonSdkType; import com.jetbrains.python.testing.pytest.PyTestUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.Map; import java.util.regex.Pattern; /** - * * User : ktisha */ public class PyPep8NamingInspection extends PyInspection { + private static final Pattern LOWERCASE_REGEX = Pattern.compile("[_\\p{javaLowerCase}][_\\p{javaLowerCase}0-9]*"); + private static final Pattern UPPERCASE_REGEX = Pattern.compile("[_\\p{javaUpperCase}][_\\p{javaUpperCase}0-9]*"); + private static final Pattern MIXEDCASE_REGEX = Pattern.compile("_?[\\p{javaUpperCase}][\\p{javaLowerCase}\\p{javaUpperCase}0-9]*"); + public boolean ignoreOverriddenFunctions = true; - public boolean ignoreTestFunctions = false; - private static Pattern LOWERCASE_REGEX = Pattern.compile("[_\\p{javaLowerCase}][_\\p{javaLowerCase}0-9]*"); - private static Pattern UPPERCASE_REGEX = Pattern.compile("[_\\p{javaUpperCase}][_\\p{javaUpperCase}0-9]*"); - private static Pattern MIXEDCASE_REGEX = Pattern.compile("_?[\\p{javaUpperCase}][\\p{javaLowerCase}\\p{javaUpperCase}0-9]*"); + public boolean ignoreDescendantsOfStandardClasses = false; @NotNull @Override public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly, @NotNull LocalInspectionToolSession session) { - if (ApplicationManager.getApplication().isUnitTestMode()) - ignoreTestFunctions = true; + if (ApplicationManager.getApplication().isUnitTestMode()) { + ignoreDescendantsOfStandardClasses = true; + } return new Visitor(holder, session); } public class Visitor extends PyInspectionVisitor { - private final Map myHasSupers = new HashMap(); - public Visitor(@NotNull final ProblemsHolder holder, LocalInspectionToolSession session) { super(holder, session); } @@ -95,22 +98,42 @@ public class PyPep8NamingInspection extends PyInspection { } @Override - public void visitPyFunction(PyFunction node) { - final PyClass containingClass = node.getContainingClass(); - if (hasSupers(node) && ignoreOverriddenFunctions) return; - if(containingClass != null && PyTestUtil.isPyTestClass(containingClass) && ignoreTestFunctions) return; - final String name = node.getName(); + public void visitPyFunction(PyFunction function) { + final PyClass containingClass = function.getContainingClass(); + if (ignoreOverriddenFunctions && isOverriddenMethod(function)) return; + final String name = function.getName(); if (name == null) return; - if (containingClass != null && name.startsWith("__") && name.endsWith("__")) { + if (containingClass != null && PyUtil.isSpecialName(name)) { + return; + } + if (containingClass != null && ignoreDescendantsOfStandardClasses && isStandardClassDescendant(containingClass)) { return; } if (!LOWERCASE_REGEX.matcher(name).matches()) { - final ASTNode nameNode = node.getNameNode(); + final ASTNode nameNode = function.getNameNode(); if (nameNode != null) registerProblem(nameNode.getPsi(), "Function name should be lowercase", new PyRenameElementQuickFix()); } } + private boolean isOverriddenMethod(@NotNull PyFunction function) { + return PySuperMethodsSearch.search(function).findFirst() != null; + } + + private boolean isStandardClassDescendant(@NotNull final PyClass cls) { + if (PyTestUtil.isPyTestClass(cls)) { + return true; + } + return ContainerUtil.exists(cls.getAncestorClasses(myTypeEvalContext), new Condition() { + @Override + public boolean value(PyClass ancestor) { + final PsiFile ancestorsModule = ancestor.getContainingFile(); + final Sdk sdk = PyBuiltinCache.findSdkForFile(ancestorsModule); + return PythonSdkType.isStdLib(ancestorsModule.getVirtualFile(), sdk) && !PyBuiltinCache.getInstance(cls).isBuiltin(ancestor); + } + }); + } + @Override public void visitPyClass(PyClass node) { final String name = node.getName(); @@ -147,16 +170,6 @@ public class PyPep8NamingInspection extends PyInspection { registerProblem(node.getAsNameElement(), "CamelCase variable imported as constant", new PyRenameElementQuickFix()); } } - - private boolean hasSupers(@NotNull PyFunction function) { - final Boolean cached = myHasSupers.get(function); - if (cached != null) { - return cached; - } - final boolean result = PySuperMethodsSearch.search(function).findFirst() != null; - myHasSupers.put(function, result); - return result; - } } @Nullable @@ -164,7 +177,7 @@ public class PyPep8NamingInspection extends PyInspection { public JComponent createOptionsPanel() { MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this); panel.addCheckbox("Ignore overridden functions", "ignoreOverriddenFunctions"); - panel.addCheckbox("Ignore test functions", "ignoreTestFunctions"); + panel.addCheckbox("Ignore descendants of standard classes", "ignoreDescendantsOfStandardClasses"); return panel; } } diff --git a/python/src/com/jetbrains/python/psi/search/PyProjectScopeBuilder.java b/python/src/com/jetbrains/python/psi/search/PyProjectScopeBuilder.java index a433a9a73315..e3042e0e527a 100644 --- a/python/src/com/jetbrains/python/psi/search/PyProjectScopeBuilder.java +++ b/python/src/com/jetbrains/python/psi/search/PyProjectScopeBuilder.java @@ -16,6 +16,7 @@ package com.jetbrains.python.psi.search; import com.intellij.injected.editor.VirtualFileWindow; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; @@ -186,6 +187,10 @@ public class PyProjectScopeBuilder extends ProjectScopeBuilderImpl { file.findChild("xml") != null && file.findChild("email") != null) { return file; } + // Mock SDK does not have aforementioned modules + if (ApplicationManager.getApplication().isUnitTestMode() && file.getName().equals("Lib")) { + return file; + } } return null; } diff --git a/python/src/com/jetbrains/python/testing/pytest/PyTestUtil.java b/python/src/com/jetbrains/python/testing/pytest/PyTestUtil.java index c2324282546e..4bc36647257c 100644 --- a/python/src/com/jetbrains/python/testing/pytest/PyTestUtil.java +++ b/python/src/com/jetbrains/python/testing/pytest/PyTestUtil.java @@ -15,23 +15,26 @@ */ package com.jetbrains.python.testing.pytest; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileSystemItem; -import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.PyClass; +import com.jetbrains.python.psi.PyFile; +import com.jetbrains.python.psi.PyFunction; +import com.jetbrains.python.psi.PyStatement; import com.jetbrains.python.psi.types.PyClassLikeType; import com.jetbrains.python.psi.types.TypeEvalContext; -import java.util.HashSet; import java.util.List; +import java.util.Set; /** * User: catherine */ public class PyTestUtil { - private static final HashSet PYTHON_TEST_QUALIFIED_CLASSES = Sets.newHashSet("unittest.TestCase", "unittest.case.TestCase"); + private static final Set PYTHON_TEST_QUALIFIED_CLASSES = ImmutableSet.of("unittest.TestCase", "unittest.case.TestCase"); public static List getPyTestCasesFromFile(PsiFileSystemItem file) { List result = Lists.newArrayList(); diff --git a/python/testData/inspections/PyPep8NamingInspection/descendantOfStandardClass.py b/python/testData/inspections/PyPep8NamingInspection/descendantOfStandardClass.py new file mode 100644 index 000000000000..a3604d351b7f --- /dev/null +++ b/python/testData/inspections/PyPep8NamingInspection/descendantOfStandardClass.py @@ -0,0 +1,7 @@ +import collections + +class MyDict(collections.OrderedDict): + def getLast(self): + if self: + return list(self.values)[-1] + raise ValueError() \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/inspections/PyPep8NamingInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyPep8NamingInspectionTest.java index e522af7aa9bb..8e2a6bfa2010 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyPep8NamingInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyPep8NamingInspectionTest.java @@ -65,6 +65,11 @@ public class PyPep8NamingInspectionTest extends PyTestCase { doTest(); } + // PY-13537 + public void testDescendantOfStandardClass() { + doTest(); + } + public void testTest() { doTest(); } diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java index bbee880bfde1..0ae4b53b8694 100644 --- a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java +++ b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java @@ -16,6 +16,8 @@ package com.intellij.xml.breadcrumbs; import com.intellij.application.options.editor.WebEditorOptions; +import com.intellij.codeInsight.daemon.impl.tagTreeHighlighting.XmlTagTreeHighlightingUtil; +import com.intellij.codeInsight.highlighting.HighlightManager; import com.intellij.ide.ui.UISettings; import com.intellij.ide.ui.UISettingsListener; import com.intellij.lang.Language; @@ -25,10 +27,14 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.editor.colors.EditorColors; +import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorFontType; import com.intellij.openapi.editor.event.CaretAdapter; import com.intellij.openapi.editor.event.CaretEvent; import com.intellij.openapi.editor.event.CaretListener; +import com.intellij.openapi.editor.markup.RangeHighlighter; +import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; @@ -52,10 +58,7 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; -import java.util.Collection; -import java.util.Comparator; -import java.util.LinkedList; -import java.util.PriorityQueue; +import java.util.*; /** * @author spleaner @@ -64,6 +67,7 @@ public class BreadcrumbsXmlWrapper implements BreadcrumbsItemListener myComponent; private final Project myProject; private Editor myEditor; + private Collection myHighlighed; private final VirtualFile myFile; private boolean myUserCaretChange; private final MergingUpdateQueue myQueue; @@ -383,6 +387,27 @@ public class BreadcrumbsXmlWrapper implements BreadcrumbsItemListener(1); + HighlightManager.getInstance(myProject).addRangeHighlight(myEditor, range.getStartOffset(), range.getEndOffset(), + attributes, true, true, myHighlighed); + } + } + @Nullable public static BreadcrumbsXmlWrapper getBreadcrumbsComponent(@NotNull Editor editor) { return editor.getUserData(BREADCRUMBS_COMPONENT_KEY); diff --git a/xml/openapi/src/com/intellij/xml/breadcrumbs/BreadcrumbsComponent.java b/xml/openapi/src/com/intellij/xml/breadcrumbs/BreadcrumbsComponent.java index 9cb570842442..a70254639ba7 100644 --- a/xml/openapi/src/com/intellij/xml/breadcrumbs/BreadcrumbsComponent.java +++ b/xml/openapi/src/com/intellij/xml/breadcrumbs/BreadcrumbsComponent.java @@ -121,6 +121,9 @@ public class BreadcrumbsComponent extends JComponent } myHovered = crumb; + for (BreadcrumbsItemListener listener : myListeners) { + listener.itemHovered(myHovered != null ? myHovered.myItem : null); + } repaint(); } diff --git a/xml/openapi/src/com/intellij/xml/breadcrumbs/BreadcrumbsItemListener.java b/xml/openapi/src/com/intellij/xml/breadcrumbs/BreadcrumbsItemListener.java index 0b74d342de56..e85b4d876113 100644 --- a/xml/openapi/src/com/intellij/xml/breadcrumbs/BreadcrumbsItemListener.java +++ b/xml/openapi/src/com/intellij/xml/breadcrumbs/BreadcrumbsItemListener.java @@ -16,12 +16,12 @@ package com.intellij.xml.breadcrumbs; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author spleaner */ public interface BreadcrumbsItemListener { - void itemSelected(@NotNull final T item, final int modifiers); - + void itemHovered(@Nullable final T item); } diff --git a/xml/xml-analysis-impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingUtil.java b/xml/xml-analysis-impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingUtil.java index bddbcd7bc4ef..289ae5e58507 100644 --- a/xml/xml-analysis-impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingUtil.java +++ b/xml/xml-analysis-impl/src/com/intellij/codeInsight/daemon/impl/tagTreeHighlighting/XmlTagTreeHighlightingUtil.java @@ -33,7 +33,7 @@ import java.util.Set; /** * @author Eugene.Kudelevsky */ -class XmlTagTreeHighlightingUtil { +public class XmlTagTreeHighlightingUtil { private XmlTagTreeHighlightingUtil() { } @@ -76,7 +76,7 @@ class XmlTagTreeHighlightingUtil { return false; } - static Color makeTransparent(@NotNull Color color, @NotNull Color backgroundColor, double transparency) { + public static Color makeTransparent(@NotNull Color color, @NotNull Color backgroundColor, double transparency) { int r = makeTransparent(transparency, color.getRed(), backgroundColor.getRed()); int g = makeTransparent(transparency, color.getGreen(), backgroundColor.getGreen()); int b = makeTransparent(transparency, color.getBlue(), backgroundColor.getBlue());