diff --git a/bin/WinLauncher/WinLauncher.exe b/bin/WinLauncher/WinLauncher.exe index 38287df29145..3a0855660c6c 100644 Binary files a/bin/WinLauncher/WinLauncher.exe and b/bin/WinLauncher/WinLauncher.exe differ diff --git a/bin/WinLauncher/WinLauncher64.exe b/bin/WinLauncher/WinLauncher64.exe index e2e4348505ce..1daf83cdccf7 100644 Binary files a/bin/WinLauncher/WinLauncher64.exe and b/bin/WinLauncher/WinLauncher64.exe differ diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index d23727fb896d..df4487148e04 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -268,7 +268,7 @@ public def layoutCommunityPlugins(String home) { } } - dir("properties") { + pluginDir("properties") { dir("lib") { jar("properties.jar") { module("properties-psi-api") diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerRunner.java b/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerRunner.java index 138da8074e53..cb280fc4f497 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerRunner.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerRunner.java @@ -46,10 +46,10 @@ public class GenericDebuggerRunner extends JavaPatchableProgramRunner myTemplatesMap; private boolean myRemoteTemplatesLoaded; private Cards myCurrentCard; - private boolean myNeedDownload; public ProjectTypeStep(WizardContext context, NewProjectWizard wizard, ModulesProvider modulesProvider) { myContext = context; @@ -163,7 +162,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements Disposable { myConfigurationUpdater = new ModuleBuilder.ModuleConfigurationUpdater() { @Override public void update(@NotNull Module module, @NotNull ModifiableRootModel rootModel) { - if (myCurrentCard == Cards.FRAMEWORKS) { + if (isFrameworksMode()) { myFrameworksPanel.addSupport(module, rootModel); } } @@ -210,6 +209,10 @@ public class ProjectTypeStep extends ModuleWizardStep implements Disposable { myTemplatesList.restoreSelection(); } + private boolean isFrameworksMode() { + return myCurrentCard == Cards.FRAMEWORKS && getSelectedBuilder().equals(myContext.getProjectBuilder()); + } + private List fillTemplatesMap(WizardContext context) { List builders = ModuleBuilder.getAllBuilders(); @@ -306,7 +309,6 @@ public class ProjectTypeStep extends ModuleWizardStep implements Disposable { // new TemplatesGroup selected public void projectTypeChanged() { - myNeedDownload = false; TemplatesGroup group = getSelectedGroup(); if (group == null) return; PropertiesComponent.getInstance().setValue(PROJECT_WIZARD_GROUP, group.getId() ); @@ -332,7 +334,6 @@ public class ProjectTypeStep extends ModuleWizardStep implements Disposable { myFrameworksPanel.setProviders(providers); } getSelectedBuilder().addModuleConfigurationUpdater(myConfigurationUpdater); - myNeedDownload = true; showCard(FRAMEWORKS_CARD); } @@ -412,7 +413,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements Disposable { } public void onWizardFinished() throws CommitStepException { - if (myNeedDownload) { + if (isFrameworksMode()) { boolean ok = myFrameworksPanel.downloadLibraries(); if (!ok) { int answer = Messages.showYesNoDialog(getComponent(), diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java index 8ee44f43c275..a2100e7e7ce3 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java @@ -579,7 +579,7 @@ public class AnnotationsHighlightUtil { public static HighlightInfo checkFunctionalInterface(@NotNull PsiAnnotation annotation, @NotNull LanguageLevel languageLevel) { final String errorMessage = LambdaUtil.checkFunctionalInterface(annotation, languageLevel); if (errorMessage != null) { - return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(annotation).descriptionAndTooltip(errorMessage).create(); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(annotation).descriptionAndTooltip(errorMessage).create(); } return null; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java index eae38cc03a17..715da62323de 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -50,7 +50,7 @@ public class ImplementMethodsFix extends LocalQuickFixAndIntentionActionOnPsiEle @Override @NotNull public String getFamilyName() { - return QuickFixBundle.message("implement.methods.fix"); + return getText(); } @Override diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java index 510a79e4705a..957893ffe680 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java @@ -113,6 +113,7 @@ public abstract class ImportClassFixBase classList = new ArrayList(classes.length); boolean isAnnotationReference = myElement.getParent() instanceof PsiAnnotation; + final PsiFile file = myElement.getContainingFile(); for (PsiClass aClass : classes) { if (isAnnotationReference && !aClass.isAnnotationType()) continue; if (JavaCompletionUtil.isInExcludedPackage(aClass, false)) continue; @@ -120,7 +121,7 @@ public abstract class ImportClassFixBase() { + @Override public String fun(final PsiExpression expr) { return expr.getText(); } @@ -294,8 +295,10 @@ public class InlineUtil { public static boolean allUsagesAreTailCalls(final PsiMethod method) { final List nonTailCallUsages = Collections.synchronizedList(new ArrayList()); boolean result = ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + @Override public void run() { ReferencesSearch.search(method).forEach(new Processor() { + @Override public boolean process(final PsiReference psiReference) { ProgressManager.checkCanceled(); if (getTailCallType(psiReference) == TailCallType.None) { diff --git a/java/java-psi-api/src/com/intellij/codeInsight/ImportFilter.java b/java/java-psi-api/src/com/intellij/codeInsight/ImportFilter.java index 4863b8217dc8..a862c9d1e2ef 100644 --- a/java/java-psi-api/src/com/intellij/codeInsight/ImportFilter.java +++ b/java/java-psi-api/src/com/intellij/codeInsight/ImportFilter.java @@ -1,7 +1,9 @@ package com.intellij.codeInsight; import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author Eugene.Kudelevsky @@ -9,11 +11,11 @@ import org.jetbrains.annotations.NotNull; public abstract class ImportFilter { public static final ExtensionPointName EP_NAME = new ExtensionPointName("com.intellij.importFilter"); - public abstract boolean shouldUseFullyQualifiedName(@NotNull String classQualifiedName); + public abstract boolean shouldUseFullyQualifiedName(@Nullable PsiFile targetFile, @NotNull String classQualifiedName); - public static boolean shouldImport(@NotNull String classQualifiedName) { + public static boolean shouldImport(@Nullable PsiFile targetFile, @NotNull String classQualifiedName) { for (ImportFilter filter : EP_NAME.getExtensions()) { - if (filter.shouldUseFullyQualifiedName(classQualifiedName)) { + if (filter.shouldUseFullyQualifiedName(targetFile, classQualifiedName)) { return false; } } diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java index cd67ed954f5c..86137d0ce565 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java @@ -40,8 +40,6 @@ public class LambdaHighlightingUtil { if (signatures == null) return interfaceNonFunctionalMessage; if (signatures.isEmpty()) return "No target method found"; if (signatures.size() == 1) { - final MethodSignature functionalMethod = signatures.get(0); - if (functionalMethod.getTypeParameters().length > 0) return "Target method is generic"; return null; } return "Multiple non-overriding abstract methods found"; @@ -106,6 +104,12 @@ public class LambdaHighlightingUtil { final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(functionalInterfaceType)); final PsiClass aClass = resolveResult.getElement(); if (aClass != null) { + if (aClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference + final List signatures = LambdaUtil.findFunctionCandidates(aClass); + if (signatures != null && signatures.size() == 1) { + final MethodSignature functionalMethod = signatures.get(0); + if (functionalMethod.getTypeParameters().length > 0) return "Target method is generic"; + } if (checkReturnTypeApplicable(resolveResult, aClass)) { return "No instance of type " + functionalInterfaceType.getPresentableText() + " exists so that lambda expression can be type-checked"; } diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index b09e65ac6916..16ff7c4569fe 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -250,7 +250,7 @@ public class LambdaUtil { } @Nullable - static List findFunctionCandidates(PsiClass psiClass) { + public static List findFunctionCandidates(PsiClass psiClass) { if (psiClass instanceof PsiAnonymousClass) { psiClass = PsiUtil.resolveClassInType(((PsiAnonymousClass)psiClass).getBaseClassType()); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java index adb86e5ad49a..0de45be17786 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.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. @@ -370,7 +370,7 @@ public class PsiImplUtil { // todo[r.sh] cache? @Nullable - public static Set getAnnotationTargets(PsiClass annotationType) { + public static Set getAnnotationTargets(@NotNull PsiClass annotationType) { if (!annotationType.isAnnotationType()) return null; PsiModifierList modifierList = annotationType.getModifierList(); if (modifierList == null) return null; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java index d9623a31876d..b7dc1e65ec6a 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java @@ -34,7 +34,6 @@ import com.intellij.psi.util.PsiTypesUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.ArrayUtilRt; -import com.intellij.util.ReflectionUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -327,6 +326,13 @@ public class InferenceSession { } } } + + for (PsiClassType thrownType : method.getThrowsList().getReferencedTypes()) { + final InferenceVariable variable = getInferenceVariable(thrownType); + if (variable != null) { + variable.setThrows(); + } + } } private InferenceVariable shouldResolveAndInstantiate(PsiType returnType, PsiType targetType) { @@ -341,7 +347,8 @@ public class InferenceSession { } private static boolean hasPrimitiveWrapperBound(InferenceVariable inferenceVariable) { - for (InferenceBound inferenceBound : InferenceBound.values()) { + final InferenceBound[] boundTypes = {InferenceBound.UPPER, InferenceBound.LOWER}; + for (InferenceBound inferenceBound : boundTypes) { final List bounds = inferenceVariable.getBounds(inferenceBound); for (PsiType bound : bounds) { if (PsiPrimitiveType.getUnboxedType(bound) != null) { @@ -593,7 +600,7 @@ public class InferenceSession { else { boolean inferred = false; PsiType glb = null; - if (isThrowable(upperBounds)) { + if (inferenceVariable.isThrownBound() && isThrowable(upperBounds)) { glb = PsiType.getJavaLangRuntimeException(myManager, GlobalSearchScope.allScope(myManager.getProject())); inferred = true; } else { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java index 80db95af3226..e0e0486afd08 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java @@ -27,6 +27,7 @@ public class InferenceVariable { return myParameter; } + private boolean myThrownBound = false; private final Map> myBounds = new HashMap>(); private final PsiTypeParameter myParameter; @@ -47,6 +48,9 @@ public class InferenceVariable { } public boolean addBound(PsiType classType, InferenceBound inferenceBound) { + if (inferenceBound == InferenceBound.EQ && classType instanceof PsiClassType && ((PsiClassType)classType).resolve() == myParameter) { + return false; + } List list = myBounds.get(inferenceBound); if (list == null) { list = new ArrayList(); @@ -74,4 +78,12 @@ public class InferenceVariable { } return dependencies; } + + public boolean isThrownBound() { + return myThrownBound; + } + + public void setThrows() { + myThrownBound = true; + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java index 4fe5dfb9722d..4a75428861e0 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java @@ -21,7 +21,6 @@ import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession; import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable; import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil; -import com.intellij.psi.impl.source.tree.java.PsiMethodReferenceExpressionImpl; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.Function; @@ -74,11 +73,17 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai } final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, PsiUtil.resolveGenericsClassInType(myT)); - for (PsiParameter parameter : interfaceMethod.getParameterList().getParameters()) { - if (!session.isProperType(substitutor.substitute(parameter.getType()))) return false; + if (myExpression instanceof PsiLambdaExpression && !((PsiLambdaExpression)myExpression).hasFormalParameterTypes() || + myExpression instanceof PsiMethodReferenceExpression && !((PsiMethodReferenceExpression)myExpression).isExact()) { + for (PsiParameter parameter : interfaceMethod.getParameterList().getParameters()) { + if (!session.isProperType(substitutor.substitute(parameter.getType()))) return false; + } } + final PsiType returnType = interfaceMethod.getReturnType(); - if (!session.isProperType(substitutor.substitute(returnType))) return false; + if (myExpression instanceof PsiLambdaExpression || !((PsiMethodReferenceExpression)myExpression).isExact()) { + if (!session.isProperType(substitutor.substitute(returnType))) return false; + } final List expectedThrownTypes = ContainerUtil.map(interfaceMethod.getThrowsList().getReferencedTypes(), new Function() { @@ -133,10 +138,16 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai for (PsiType thrownType : thrownTypes) { if (!isAddressed(expectedProperTypes, thrownType)) { for (PsiType expectedNonProperThrownType : expectedNonProperThrownTypes) { - constraints.add(new TypeCompatibilityConstraint(expectedNonProperThrownType, thrownType)); + constraints.add(new StrictSubtypingConstraint(expectedNonProperThrownType, thrownType)); } } } + + for (PsiType expectedNonProperThrownType : expectedNonProperThrownTypes) { + final InferenceVariable variable = session.getInferenceVariable(expectedNonProperThrownType); + LOG.assertTrue(variable != null); + variable.setThrows(); + } } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java index aefa6219de57..bdaced7efc97 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java @@ -28,10 +28,8 @@ public class LambdaExpressionCompatibilityConstraint implements ConstraintFormul return false; } - if (myExpression.hasFormalParameterTypes()) { - } - final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType( - FunctionalInterfaceParameterizationUtil.getGroundTargetType(myT, myExpression, false)); + final PsiType groundTargetType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(myT, myExpression, false); + final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(groundTargetType); final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult); if (interfaceMethod == null) { return false; @@ -47,6 +45,7 @@ public class LambdaExpressionCompatibilityConstraint implements ConstraintFormul for (int i = 0; i < lambdaParameters.length; i++) { constraints.add(new TypeEqualityConstraint(lambdaParameters[i].getType(), substitutor.substitute(parameters[i].getType()))); } + constraints.add(new StrictSubtypingConstraint(myT, groundTargetType)); } else { for (PsiParameter parameter : parameters) { if (!session.isProperType(substitutor.substitute(parameter.getType()))) { @@ -55,7 +54,7 @@ public class LambdaExpressionCompatibilityConstraint implements ConstraintFormul } } - final PsiType returnType = interfaceMethod.getReturnType(); + PsiType returnType = interfaceMethod.getReturnType(); if (returnType != null) { final List returnExpressions = LambdaUtil.getReturnExpressions(myExpression); if (returnType.equals(PsiType.VOID)) { @@ -66,8 +65,11 @@ public class LambdaExpressionCompatibilityConstraint implements ConstraintFormul if (returnExpressions.isEmpty() && !myExpression.isValueCompatible()) { //not value-compatible return false; } - for (PsiExpression returnExpression : returnExpressions) { - constraints.add(new ExpressionCompatibilityConstraint(returnExpression, GenericsUtil.eliminateWildcards(substitutor.substitute(returnType)))); + returnType = substitutor.substitute(returnType); + if (!session.isProperType(returnType)) { + for (PsiExpression returnExpression : returnExpressions) { + constraints.add(new ExpressionCompatibilityConstraint(returnExpression, GenericsUtil.eliminateWildcards(returnType))); + } } } } diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java index eaaa8b8d475c..47e99bbe4077 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java @@ -713,7 +713,11 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ ProgressManager.checkCanceled(); LOG.assertTrue(typeParameter != null); if (!substitutor.getSubstitutionMap().containsKey(typeParameter)) { - substitutor = substitutor.put(typeParameter, TypeConversionUtil.erasure(siteSubstitutor.substitute(typeParameter), substitutor)); + PsiType type = siteSubstitutor.substitute(typeParameter); + if (type instanceof PsiClassType && ((PsiClassType)type).resolve() instanceof PsiTypeParameter) { + type = TypeConversionUtil.erasure(type, substitutor); + } + substitutor = substitutor.put(typeParameter, type); } } return substitutor; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA120153.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA120153.java new file mode 100644 index 000000000000..afca96396931 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA120153.java @@ -0,0 +1,23 @@ +import java.util.Collection; +import java.util.List; + +class Idea { + class Library { + public void f(Base x) { + } + public void f(Derived x) { + } + } + + class Wrapper { + } + + class Base { + } + class Derived extends Base { + } + + public void main(Derived> x) { + new Library>().f(x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/LambdaGroundTest.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/LambdaGroundTest.java new file mode 100644 index 000000000000..d5b0dad55764 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/LambdaGroundTest.java @@ -0,0 +1,13 @@ +import java.util.List; + +public class Sample { + interface Fun, B> { + B f(A a); + } + + void foo(Fun f) {} + + { + foo((List ls) -> ls.size()); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation.java index 379e5868381c..05b2585c8405 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation.java @@ -1,4 +1,4 @@ -@FunctionalInterface +@FunctionalInterface interface Test { void foo(); void bar(); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java index 968d078f6e10..89d37921f11c 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.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. @@ -49,7 +49,7 @@ import java.io.File; import java.util.Collection; /** - * This class intended for "heavily-loaded" tests only, e.g. those need to setup separate project directory structure to run. + * This class intended for "heavy-loaded" tests only, e.g. those need to setup separate project directory structure to run. * For "lightweight" tests use LightAdvHighlightingTest. */ public class AdvHighlightingTest extends DaemonAnalyzerTestCase { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index f0cac18d908e..9455c0ec0493 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -336,6 +336,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testIDEA118037() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } public void testIDEA119546() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } public void testIDEA118527() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } + public void testIDEA120153() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ConstraintsInferenceMiscTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ConstraintsInferenceMiscTest.java index de39d99efffd..42433d327e2d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ConstraintsInferenceMiscTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ConstraintsInferenceMiscTest.java @@ -50,6 +50,10 @@ public class ConstraintsInferenceMiscTest extends LightDaemonAnalyzerTestCase { doTest(false); } + public void testLambdaGroundTest() throws Exception { + doTest(false); + } + private void doTest(final boolean checkWarnings) { doTestNewInference(BASE_PATH + "/" + getTestName(false) + ".java", checkWarnings, false); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalInterfaceTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalInterfaceTest.java index 88412778ea29..8eaf7c316b5f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalInterfaceTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalInterfaceTest.java @@ -31,7 +31,7 @@ public class FunctionalInterfaceTest extends LightDaemonAnalyzerTestCase { final PsiClass psiClass = getJavaFacade().findClass("Foo", GlobalSearchScope.projectScope(getProject())); assertNotNull("Class Foo not found", psiClass); - final String errorMessage = LambdaHighlightingUtil.checkInterfaceFunctional(psiClass); + final String errorMessage = LambdaHighlightingUtil.checkInterfaceFunctional(getJavaFacade().getElementFactory().createType(psiClass)); assertEquals(expectedErrorMessage, errorMessage); } diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java index 7d28d8ed12bd..eafc24d7d15f 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.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. @@ -189,7 +189,7 @@ public abstract class LightQuickFixTestCase extends LightDaemonAnalyzerTestCase return findActionWithText(getAvailableActions(), text); } - public static IntentionAction findActionWithText(final List actions, final String text) { + public static IntentionAction findActionWithText(@NotNull List actions, final String text) { for (IntentionAction action : actions) { if (text.equals(action.getText())) { return action; diff --git a/native/WinLauncher/WinLauncher/WinLauncher.cpp b/native/WinLauncher/WinLauncher/WinLauncher.cpp index 8d5ff13a46ed..a934a88da3d0 100644 --- a/native/WinLauncher/WinLauncher/WinLauncher.cpp +++ b/native/WinLauncher/WinLauncher/WinLauncher.cpp @@ -17,7 +17,7 @@ #include "stdafx.h" #include "WinLauncher.h" -typedef JNIIMPORT jint (JNICALL *JNI_createJavaVM)(JavaVM **pvm, JNIEnv **env, void *args); +typedef JNIIMPORT jint(JNICALL *JNI_createJavaVM)(JavaVM **pvm, JNIEnv **env, void *args); HINSTANCE hInst; // current instance char jvmPath[_MAX_PATH]; @@ -45,7 +45,7 @@ std::string LoadStdString(int id) { wchar_t *buf = NULL; int len = LoadStringW(hInst, id, reinterpret_cast(&buf), 0); - if (len) + if (len) { int cbANSI = WideCharToMultiByte(CP_ACP, 0, buf, len, NULL, 0, NULL, NULL); char* ansiBuf = new char[cbANSI]; @@ -65,7 +65,7 @@ bool FileExists(const std::string& path) bool IsValidJRE(const char* path) { std::string dllPath(path); - if (dllPath[dllPath.size()-1] != '\\') + if (dllPath[dllPath.size() - 1] != '\\') { dllPath += "\\"; } @@ -83,16 +83,16 @@ bool FindValidJVM(const char* path) { if (IsValidJRE(path)) { - strcpy_s(jvmPath, _MAX_PATH-1, path); + strcpy_s(jvmPath, _MAX_PATH - 1, path); return true; } char jrePath[_MAX_PATH]; strcpy_s(jrePath, path); - if (jrePath[strlen(jrePath)-1] != '\\') + if (jrePath[strlen(jrePath) - 1] != '\\') { strcat_s(jrePath, "\\"); } - strcat_s(jrePath, _MAX_PATH-1, "jre"); + strcat_s(jrePath, _MAX_PATH - 1, "jre"); if (IsValidJRE(jrePath)) { strcpy_s(jvmPath, jrePath); @@ -104,13 +104,13 @@ bool FindValidJVM(const char* path) std::string GetAdjacentDir(const char* suffix) { char libDir[_MAX_PATH]; - GetModuleFileNameA(NULL, libDir, _MAX_PATH-1); + GetModuleFileNameA(NULL, libDir, _MAX_PATH - 1); char* lastSlash = strrchr(libDir, '\\'); if (!lastSlash) return ""; *lastSlash = '\0'; lastSlash = strrchr(libDir, '\\'); if (!lastSlash) return ""; - strcpy(lastSlash+1, suffix); + strcpy(lastSlash + 1, suffix); strcat_s(libDir, "\\"); return std::string(libDir); } @@ -118,7 +118,7 @@ std::string GetAdjacentDir(const char* suffix) bool FindJVMInEnvVar(const char* envVarName, bool& result) { char envVarValue[_MAX_PATH]; - if (GetEnvironmentVariableA(envVarName, envVarValue, _MAX_PATH-1)) + if (GetEnvironmentVariableA(envVarName, envVarValue, _MAX_PATH - 1)) { if (FindValidJVM(envVarValue)) { @@ -145,9 +145,9 @@ bool FindJVMInRegistryKey(const char* key, bool wow64_32) if (wow64_32) flags |= KEY_WOW64_32KEY; if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hKey) != ERROR_SUCCESS) return false; char javaHome[_MAX_PATH]; - DWORD javaHomeSize = _MAX_PATH-1; + DWORD javaHomeSize = _MAX_PATH - 1; bool success = false; - if (RegQueryValueExA(hKey, "JavaHome", NULL, NULL, (LPBYTE) javaHome, &javaHomeSize) == ERROR_SUCCESS) + if (RegQueryValueExA(hKey, "JavaHome", NULL, NULL, (LPBYTE)javaHome, &javaHomeSize) == ERROR_SUCCESS) { success = FindValidJVM(javaHome); } @@ -157,7 +157,7 @@ bool FindJVMInRegistryKey(const char* key, bool wow64_32) bool FindJVMInRegistryWithVersion(const char* version, bool wow64_32) { - const char* keyName = LoadStdString(IDS_JDK_ONLY) == std::string("true") + const char* keyName = LoadStdString(IDS_JDK_ONLY) == std::string("true") ? "Java Development Kit" : "Java Runtime Environment"; @@ -217,7 +217,7 @@ void TrimLine(char* line) { *p-- = '\0'; } - while(p >= line && (*p == ' ' || *p == '\t')) + while (p >= line && (*p == ' ' || *p == '\t')) { *p-- = '\0'; } @@ -227,9 +227,9 @@ bool LoadVMOptionsFile(const TCHAR* path, std::vector& vmOptionLine { FILE *f = _tfopen(path, _T("rt")); if (!f) return false; - + char line[_MAX_PATH]; - while(fgets(line, _MAX_PATH-1, f)) + while (fgets(line, _MAX_PATH - 1, f)) { TrimLine(line); if (line[0] == '#') continue; @@ -253,7 +253,7 @@ std::string FindToolsJar() size_t lastSlash = toolsJarPath.rfind('\\'); if (lastSlash != std::string::npos) { - toolsJarPath = toolsJarPath.substr(0, lastSlash+1) + "lib\\tools.jar"; + toolsJarPath = toolsJarPath.substr(0, lastSlash + 1) + "lib\\tools.jar"; if (FileExists(toolsJarPath)) { return toolsJarPath; @@ -272,7 +272,7 @@ std::string CollectLibJars(const std::string& jarList) std::string result; int pos = 0; - while(pos < jarList.size()) + while (pos < jarList.size()) { int delimiterPos = jarList.find(';', pos); if (delimiterPos == std::string::npos) @@ -284,8 +284,8 @@ std::string CollectLibJars(const std::string& jarList) result += ";"; } result += libDir; - result += jarList.substr(pos, delimiterPos-pos); - pos = delimiterPos+1; + result += jarList.substr(pos, delimiterPos - pos); + pos = delimiterPos + 1; } return result; } @@ -324,17 +324,17 @@ bool AddClassPathOptions(std::vector& vmOptionLines) void AddPredefinedVMOptions(std::vector& vmOptionLines) { std::string vmOptions = LoadStdString(IDS_VM_OPTIONS); - while(vmOptions.size() > 0) + while (vmOptions.size() > 0) { int pos = vmOptions.find(' '); if (pos == std::string::npos) pos = vmOptions.size(); vmOptionLines.push_back(vmOptions.substr(0, pos)); - while(pos < vmOptions.size() && vmOptions[pos] == ' ') pos++; + while (pos < vmOptions.size() && vmOptions[pos] == ' ') pos++; vmOptions = vmOptions.substr(pos); } char ideaProperties[_MAX_PATH]; - if (GetEnvironmentVariableA("IDEA_PROPERTIES", ideaProperties, _MAX_PATH-1)) + if (GetEnvironmentVariableA("IDEA_PROPERTIES", ideaProperties, _MAX_PATH - 1)) { vmOptionLines.push_back(std::string("-Didea.properties.file=") + ideaProperties); } @@ -343,17 +343,17 @@ void AddPredefinedVMOptions(std::vector& vmOptionLines) bool LoadVMOptions() { TCHAR optionsFileName[_MAX_PATH]; - if (LoadString(hInst, IDS_VM_OPTIONS_PATH, optionsFileName, _MAX_PATH-1)) + if (LoadString(hInst, IDS_VM_OPTIONS_PATH, optionsFileName, _MAX_PATH - 1)) { TCHAR fullOptionsFileName[_MAX_PATH]; - ExpandEnvironmentStrings(optionsFileName, fullOptionsFileName, _MAX_PATH-1); - + ExpandEnvironmentStrings(optionsFileName, fullOptionsFileName, _MAX_PATH - 1); + if (GetFileAttributes(fullOptionsFileName) == INVALID_FILE_ATTRIBUTES) { - GetModuleFileName(NULL, fullOptionsFileName, _MAX_PATH-1); + GetModuleFileName(NULL, fullOptionsFileName, _MAX_PATH - 1); _tcscat_s(fullOptionsFileName, _T(".vmoptions")); } - + std::vector vmOptionLines; if (LoadVMOptionsFile(fullOptionsFileName, vmOptionLines)) { @@ -361,8 +361,8 @@ bool LoadVMOptions() AddPredefinedVMOptions(vmOptionLines); vmOptionCount = vmOptionLines.size(); - vmOptions = (JavaVMOption*) malloc(vmOptionCount * sizeof(JavaVMOption)); - for(int i=0; iFindClass("java/lang/String"); - jobjectArray args = env->NewObjectArray(numArgs-1, stringClass, NULL); - for(int i=1; iNewObjectArray(numArgs - 1, stringClass, NULL); + for (int i = 1; i < numArgs; i++) { const wchar_t* arg = argv[i]; - env->SetObjectArrayElement(args, i-1, env->NewString((const jchar *) arg, wcslen(argv[i]))); + env->SetObjectArrayElement(args, i - 1, env->NewString((const jchar *)arg, wcslen(argv[i]))); } return args; } @@ -484,7 +484,7 @@ void CallCommandLineProcessor(const std::wstring& curDir, const std::wstring& ar attachArgs.version = JNI_VERSION_1_2; attachArgs.name = "WinLauncher external command processing thread"; attachArgs.group = NULL; - jvm->AttachCurrentThread((void**) &env, &attachArgs); + jvm->AttachCurrentThread((void**)&env, &attachArgs); std::string processorClassName = LoadStdString(IDS_COMMAND_LINE_PROCESSOR_CLASS); jclass processorClass = env->FindClass(processorClassName.c_str()); @@ -493,8 +493,8 @@ void CallCommandLineProcessor(const std::wstring& curDir, const std::wstring& ar jmethodID processMethodID = env->GetStaticMethodID(processorClass, "processWindowsLauncherCommandLine", "(Ljava/lang/String;Ljava/lang/String;)V"); if (processMethodID) { - jstring jCurDir = env->NewString((const jchar *) curDir.c_str(), curDir.size()); - jstring jArgs = env->NewString((const jchar *) args.c_str(), args.size()); + jstring jCurDir = env->NewString((const jchar *)curDir.c_str(), curDir.size()); + jstring jArgs = env->NewString((const jchar *)args.c_str(), args.size()); env->CallStaticVoidMethod(processorClass, processMethodID, jCurDir, jArgs); jthrowable exc = env->ExceptionOccurred(); if (exc) @@ -509,7 +509,7 @@ void CallCommandLineProcessor(const std::wstring& curDir, const std::wstring& ar DWORD WINAPI SingleInstanceThread(LPVOID args) { - while(true) + while (true) { WaitForSingleObject(hEvent, INFINITE); if (terminating) break; @@ -521,7 +521,7 @@ DWORD WINAPI SingleInstanceThread(LPVOID args) if (pos >= 0) { std::wstring curDir = command.substr(0, pos); - std::wstring args = command.substr(pos+1); + std::wstring args = command.substr(pos + 1); CallCommandLineProcessor(curDir, args); } @@ -534,7 +534,7 @@ DWORD WINAPI SingleInstanceThread(LPVOID args) void SendCommandLineToFirstInstance() { wchar_t curDir[_MAX_PATH]; - GetCurrentDirectoryW(_MAX_PATH-1, curDir); + GetCurrentDirectoryW(_MAX_PATH - 1, curDir); std::wstring command(curDir); command += _T("\n"); command += GetCommandLineW(); @@ -542,17 +542,17 @@ void SendCommandLineToFirstInstance() void *view = MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (view) { - memcpy(view, command.c_str(), (command.size()+1) * sizeof(wchar_t)); + memcpy(view, command.c_str(), (command.size() + 1) * sizeof(wchar_t)); UnmapViewOfFile(view); } - SetEvent(hEvent); + SetEvent(hEvent); } bool CheckSingleInstance() { char moduleFileName[_MAX_PATH]; - GetModuleFileNameA(NULL, moduleFileName, _MAX_PATH-1); - for(char *p = moduleFileName; *p; p++) + GetModuleFileNameA(NULL, moduleFileName, _MAX_PATH - 1); + for (char *p = moduleFileName; *p; p++) { if (*p == ':' || *p == '\\') *p = '_'; } @@ -564,7 +564,7 @@ bool CheckSingleInstance() hFileMapping = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, mappingName.c_str()); if (!hFileMapping) { - hFileMapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, FILE_MAPPING_SIZE, + hFileMapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, FILE_MAPPING_SIZE, mappingName.c_str()); return true; } @@ -579,11 +579,11 @@ bool CheckSingleInstance() void DrawSplashImage(HWND hWnd) { - HBITMAP hSplashBitmap = (HBITMAP) GetWindowLongPtr(hWnd, GWLP_USERDATA); + HBITMAP hSplashBitmap = (HBITMAP)GetWindowLongPtr(hWnd, GWLP_USERDATA); PAINTSTRUCT ps; HDC hDC = BeginPaint(hWnd, &ps); HDC hMemDC = CreateCompatibleDC(hDC); - HBITMAP hOldBmp = (HBITMAP) SelectObject(hMemDC, hSplashBitmap); + HBITMAP hOldBmp = (HBITMAP)SelectObject(hMemDC, hSplashBitmap); BITMAP splashBitmap; GetObject(hSplashBitmap, sizeof(splashBitmap), &splashBitmap); BitBlt(hDC, 0, 0, splashBitmap.bmWidth, splashBitmap.bmHeight, hMemDC, 0, 0, SRCCOPY); @@ -594,12 +594,12 @@ void DrawSplashImage(HWND hWnd) LRESULT CALLBACK SplashScreenWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch(uMsg) + switch (uMsg) { case WM_PAINT: DrawSplashImage(hWnd); break; - } + } return DefWindowProc(hWnd, uMsg, wParam, lParam); } @@ -616,7 +616,7 @@ void RegisterSplashScreenWndClass() wcx.hInstance = hInst; wcx.hIcon = 0; wcx.hCursor = LoadCursor(NULL, IDC_WAIT); - wcx.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH); + wcx.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); wcx.lpszMenuName = 0; wcx.lpszClassName = splashClassName; wcx.hIconSm = 0; @@ -632,86 +632,120 @@ HWND ShowSplashScreenWindow(HBITMAP hSplashBitmap) GetObject(hSplashBitmap, sizeof(splashBitmap), &splashBitmap); int x = workArea.left + ((workArea.right - workArea.left) - splashBitmap.bmWidth) / 2; int y = workArea.top + ((workArea.bottom - workArea.top) - splashBitmap.bmHeight) / 2; - + HWND splashWindow = CreateWindowEx(WS_EX_TOOLWINDOW, splashClassName, splashClassName, WS_POPUP, x, y, splashBitmap.bmWidth, splashBitmap.bmHeight, NULL, NULL, NULL, NULL); - SetWindowLongPtr(splashWindow, GWLP_USERDATA, (LONG_PTR) hSplashBitmap); + SetWindowLongPtr(splashWindow, GWLP_USERDATA, (LONG_PTR)hSplashBitmap); ShowWindow(splashWindow, SW_SHOW); UpdateWindow(splashWindow); return splashWindow; } +DWORD parentProcId; +HANDLE parentProcHandle; + +BOOL IsParentProcessRunning(HANDLE hProcess) +{ + if (hProcess == NULL) return FALSE; + DWORD ret = WaitForSingleObject(hProcess, 0); + return ret == WAIT_TIMEOUT; +} + BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) { - static DWORD currentProcId = GetCurrentProcessId(); DWORD procId = 0; GetWindowThreadProcessId(hWnd, &procId); - if(currentProcId == procId) + if (parentProcId == procId) { - TCHAR className[_MAX_PATH]; - GetClassName(hWnd, className, _MAX_PATH-1); - if (_tcscmp(className, splashClassName) != 0) + WINDOWINFO wi; + wi.cbSize = sizeof(WINDOWINFO); + GetWindowInfo(hWnd, &wi); + if ((wi.dwStyle & WS_VISIBLE) != 0) { - WINDOWINFO wi; - wi.cbSize = sizeof(WINDOWINFO); - GetWindowInfo(hWnd, &wi); - if((wi.dwStyle & WS_VISIBLE) != 0) - { - HWND *phNewWindow = (HWND *) lParam; - *phNewWindow = hWnd; - return FALSE; - } + HWND *phNewWindow = (HWND *)lParam; + *phNewWindow = hWnd; + return FALSE; } } return TRUE; } - -DWORD WINAPI SplashScreenThread(LPVOID args) +DWORD WINAPI SplashScreen(HBITMAP hSplashBitmap) { - HBITMAP hSplashBitmap = static_cast(args); RegisterSplashScreenWndClass(); HWND splashWindow = ShowSplashScreenWindow(hSplashBitmap); - MSG msg; - while(true) + while (true) { - while (PeekMessage(&msg, splashWindow, 0, 0, PM_REMOVE)) + while (PeekMessage(&msg, splashWindow, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } Sleep(50); HWND hNewWindow = NULL; - EnumWindows(EnumWindowsProc, (LPARAM) &hNewWindow); + EnumWindows(EnumWindowsProc, (LPARAM)&hNewWindow); if (hNewWindow) { BringWindowToTop(hNewWindow); + Sleep(100); DeleteObject(hSplashBitmap); DestroyWindow(splashWindow); + break; } + if (!IsParentProcessRunning(parentProcHandle)) break; } return 0; } +void StartSplashProcess() +{ + TCHAR ownPath[_MAX_PATH]; + TCHAR params[_MAX_PATH]; + + PROCESS_INFORMATION splashProcessInformation; + STARTUPINFO startupInfo; + memset(&splashProcessInformation, 0, sizeof(splashProcessInformation)); + memset(&startupInfo, 0, sizeof(startupInfo)); + startupInfo.cb = sizeof(startupInfo); + startupInfo.dwFlags = STARTF_USESHOWWINDOW; + startupInfo.wShowWindow = SW_SHOW; + + GetModuleFileName(NULL, ownPath, (sizeof(ownPath))); + _snwprintf(params, _MAX_PATH, _T("SPLASH %d"), GetCurrentProcessId()); + if (CreateProcess(ownPath, params, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &splashProcessInformation)) + { + CloseHandle(splashProcessInformation.hProcess); + CloseHandle(splashProcessInformation.hThread); + } +} + int APIENTRY _tWinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPTSTR lpCmdLine, - int nCmdShow) + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); - UNREFERENCED_PARAMETER(lpCmdLine); hInst = hInstance; - if (!CheckSingleInstance()) return 1; - - HANDLE hSplashBitmap = static_cast(LoadImage(hInst, MAKEINTRESOURCE(IDB_SPLASH), IMAGE_BITMAP, 0, 0, 0)); - if (hSplashBitmap) + if (__argc == 2 && _wcsicmp(__wargv[0], _T("SPLASH")) == 0) { - CreateThread(NULL, 0, SplashScreenThread, hSplashBitmap, 0, NULL); + HBITMAP hSplashBitmap = static_cast(LoadImage(hInst, MAKEINTRESOURCE(IDB_SPLASH), IMAGE_BITMAP, 0, 0, 0)); + if (hSplashBitmap) + { + parentProcId = _wtoi(__wargv[1]); + parentProcHandle = OpenProcess(SYNCHRONIZE, FALSE, parentProcId); + if (IsParentProcessRunning(parentProcHandle)) SplashScreen(hSplashBitmap); + } + CloseHandle(parentProcHandle); + return 0; } + if (!CheckSingleInstance()) return 1; + + if (wcsstr(lpCmdLine, _T("nosplash")) == NULL) StartSplashProcess(); + if (!LocateJVM()) return 1; if (!LoadVMOptions()) return 1; if (!LoadJVMLibrary()) return 1; @@ -731,4 +765,3 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, return 0; } - \ No newline at end of file diff --git a/platform/lang-api/src/com/intellij/lang/ExternalAnnotatorsFilter.java b/platform/analysis-api/src/com/intellij/lang/ExternalAnnotatorsFilter.java similarity index 96% rename from platform/lang-api/src/com/intellij/lang/ExternalAnnotatorsFilter.java rename to platform/analysis-api/src/com/intellij/lang/ExternalAnnotatorsFilter.java index e4050f0f491a..1ca4a369cc0d 100644 --- a/platform/lang-api/src/com/intellij/lang/ExternalAnnotatorsFilter.java +++ b/platform/analysis-api/src/com/intellij/lang/ExternalAnnotatorsFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 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. diff --git a/platform/lang-api/src/com/intellij/lang/ExternalLanguageAnnotators.java b/platform/analysis-api/src/com/intellij/lang/ExternalLanguageAnnotators.java similarity index 97% rename from platform/lang-api/src/com/intellij/lang/ExternalLanguageAnnotators.java rename to platform/analysis-api/src/com/intellij/lang/ExternalLanguageAnnotators.java index 4a46297597b9..90bd7a13f89a 100644 --- a/platform/lang-api/src/com/intellij/lang/ExternalLanguageAnnotators.java +++ b/platform/analysis-api/src/com/intellij/lang/ExternalLanguageAnnotators.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. diff --git a/platform/lang-api/src/com/intellij/lang/annotation/ExternalAnnotator.java b/platform/analysis-api/src/com/intellij/lang/annotation/ExternalAnnotator.java similarity index 98% rename from platform/lang-api/src/com/intellij/lang/annotation/ExternalAnnotator.java rename to platform/analysis-api/src/com/intellij/lang/annotation/ExternalAnnotator.java index 9f8644c02708..9381a2a04c1b 100644 --- a/platform/lang-api/src/com/intellij/lang/annotation/ExternalAnnotator.java +++ b/platform/analysis-api/src/com/intellij/lang/annotation/ExternalAnnotator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ExternalAnnotatorInspectionVisitor.java b/platform/analysis-impl/src/com/intellij/codeInspection/ExternalAnnotatorInspectionVisitor.java similarity index 75% rename from platform/lang-impl/src/com/intellij/codeInspection/ExternalAnnotatorInspectionVisitor.java rename to platform/analysis-impl/src/com/intellij/codeInspection/ExternalAnnotatorInspectionVisitor.java index 54caec4262e6..f2a7c67be5c4 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ExternalAnnotatorInspectionVisitor.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/ExternalAnnotatorInspectionVisitor.java @@ -1,3 +1,18 @@ +/* + * 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.codeInspection; import com.intellij.codeInsight.daemon.impl.AnnotationHolderImpl; @@ -19,7 +34,7 @@ public class ExternalAnnotatorInspectionVisitor extends PsiElementVisitor { private final ProblemsHolder myHolder; private final ExternalAnnotator myAnnotator; - private boolean myOnTheFly; + private final boolean myOnTheFly; public ExternalAnnotatorInspectionVisitor(ProblemsHolder holder, ExternalAnnotator annotator, boolean onTheFly) { myHolder = holder; @@ -27,17 +42,19 @@ public class ExternalAnnotatorInspectionVisitor extends PsiElementVisitor { myOnTheFly = onTheFly; } - public static ProblemDescriptor[] checkFileWithExternalAnnotator(PsiFile file, - InspectionManager manager, - boolean isOnTheFly, ExternalAnnotator annotator) { + @NotNull + public static ProblemDescriptor[] checkFileWithExternalAnnotator(@NotNull PsiFile file, + @NotNull InspectionManager manager, + boolean isOnTheFly, + @NotNull ExternalAnnotator annotator) { if (isOnTheFly) { // concrete JSLinterExternalAnnotator implementation does this work return ProblemDescriptor.EMPTY_ARRAY; } - Object info = annotator.collectInformation(file); + Init info = annotator.collectInformation(file); if (info != null) { - Object annotationResult = annotator.doAnnotate(info); + Result annotationResult = annotator.doAnnotate(info); if (annotationResult == null) { return ProblemDescriptor.EMPTY_ARRAY; } @@ -48,10 +65,11 @@ public class ExternalAnnotatorInspectionVisitor extends PsiElementVisitor { return ProblemDescriptor.EMPTY_ARRAY; } + @NotNull private static ProblemDescriptor[] convertToProblemDescriptors(@NotNull final List annotations, @NotNull final InspectionManager manager, @NotNull final PsiFile file) { - if (annotations.size() == 0) { + if (annotations.isEmpty()) { return ProblemDescriptor.EMPTY_ARRAY; } diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.java b/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.java index 45997b0579af..3ac277c96d8e 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.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. @@ -102,6 +102,7 @@ public class ProblemDescriptorBase extends CommonProblemDescriptorImpl implement return PsiTreeUtil.findCommonParent(startElement, endElement); } + @Override @Nullable public TextRange getTextRangeInElement() { return myTextRangeInElement; diff --git a/platform/bootstrap/src/com/intellij/idea/Main.java b/platform/bootstrap/src/com/intellij/idea/Main.java index 5517bb7e2dd5..6dfd695cd299 100644 --- a/platform/bootstrap/src/com/intellij/idea/Main.java +++ b/platform/bootstrap/src/com/intellij/idea/Main.java @@ -153,7 +153,7 @@ public class Main { System.getProperty("java.home") + "/bin/java", "-Xmx500m", "-classpath", - copyPatchFile.getPath() + File.pathSeparator + copyPatchFile.getPath() + "/lib/log4j.jar", + copyPatchFile.getPath() + File.pathSeparator + PathManager.getLibPath() + "/log4j.jar", "-Djava.io.tmpdir=" + tempDir, "com.intellij.updater.Runner", "install", diff --git a/platform/core-api/src/com/intellij/openapi/application/ModalityState.java b/platform/core-api/src/com/intellij/openapi/application/ModalityState.java index fde756290433..7ade35e7ca71 100644 --- a/platform/core-api/src/com/intellij/openapi/application/ModalityState.java +++ b/platform/core-api/src/com/intellij/openapi/application/ModalityState.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 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. @@ -63,4 +63,7 @@ public abstract class ModalityState { } public abstract boolean dominates(@NotNull ModalityState anotherState); + + @Override + public abstract String toString(); } diff --git a/platform/core-api/src/com/intellij/patterns/ObjectPattern.java b/platform/core-api/src/com/intellij/patterns/ObjectPattern.java index a76ee94c6b73..cf9f751c9852 100644 --- a/platform/core-api/src/com/intellij/patterns/ObjectPattern.java +++ b/platform/core-api/src/com/intellij/patterns/ObjectPattern.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -58,11 +58,13 @@ public abstract class ObjectPattern> impl } public Self andNot(final ElementPattern pattern) { - return and(StandardPatterns.not(pattern)); + ElementPattern not = StandardPatterns.not(pattern); + return and(not); } - public Self andOr(final ElementPattern... patterns) { - return and(StandardPatterns.or(patterns)); + public Self andOr(@NotNull ElementPattern... patterns) { + ElementPattern or = StandardPatterns.or(patterns); + return and(or); } public Self and(final ElementPattern pattern) { diff --git a/platform/core-impl/src/com/intellij/mock/MockApplication.java b/platform/core-impl/src/com/intellij/mock/MockApplication.java index 5a888c827aa1..f331a7dd9c8f 100644 --- a/platform/core-impl/src/com/intellij/mock/MockApplication.java +++ b/platform/core-impl/src/com/intellij/mock/MockApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 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. @@ -195,6 +195,11 @@ public class MockApplication extends MockComponentManager implements Application public boolean dominates(@NotNull ModalityState anotherState) { return false; } + + @Override + public String toString() { + return "NONE"; + } }; } return MODALITY_STATE_NONE; diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/Editor.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/Editor.java index 3a5d9d415257..bd63b43f1af3 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/editor/Editor.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/Editor.java @@ -22,7 +22,6 @@ import com.intellij.openapi.editor.event.EditorMouseMotionListener; import com.intellij.openapi.editor.markup.MarkupModel; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.UserDataHolder; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.java index 18e84d26c036..90ca62f1bd54 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.java @@ -48,10 +48,10 @@ public class ExternalSystemTaskRunner extends GenericProgramRunner { @Nullable @Override - protected RunContentDescriptor doExecute(Project project, - RunProfileState state, + protected RunContentDescriptor doExecute(@NotNull Project project, + @NotNull RunProfileState state, RunContentDescriptor contentToReuse, - ExecutionEnvironment env) throws ExecutionException + @NotNull ExecutionEnvironment env) throws ExecutionException { ExecutionResult executionResult = state.execute(env.getExecutor(), this); if (executionResult == null) return null; diff --git a/platform/lang-api/src/com/intellij/execution/actions/ConsoleActionsPostProcessor.java b/platform/lang-api/src/com/intellij/execution/actions/ConsoleActionsPostProcessor.java index 859cd8162108..792208811bd3 100644 --- a/platform/lang-api/src/com/intellij/execution/actions/ConsoleActionsPostProcessor.java +++ b/platform/lang-api/src/com/intellij/execution/actions/ConsoleActionsPostProcessor.java @@ -26,9 +26,9 @@ import org.jetbrains.annotations.NotNull; * @author Denis Zhdanov * @since 4/25/11 1:16 PM */ -public interface ConsoleActionsPostProcessor { +public abstract class ConsoleActionsPostProcessor { - ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.consoleActionsPostProcessor"); + public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.consoleActionsPostProcessor"); /** * Allows to adjust actions to use within the given console instance. @@ -40,5 +40,12 @@ public interface ConsoleActionsPostProcessor { * @return actions to use within the given console instance (given actions may be returned by default) */ @NotNull - AnAction[] postProcess(@NotNull ConsoleView console, @NotNull AnAction[] actions); + public AnAction[] postProcess(@NotNull ConsoleView console, @NotNull AnAction[] actions) { + return actions; + } + + @NotNull + public AnAction[] postProcessPopupActions(@NotNull ConsoleView console, @NotNull AnAction[] actions) { + return actions; + } } diff --git a/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java b/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java index 87a933fdf285..0c7d033c5d5d 100644 --- a/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java +++ b/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java @@ -33,7 +33,8 @@ public abstract class GenericProgramRunner impl @Deprecated public static final DataKey CONTENT_TO_REUSE_DATA_KEY = DataKey.create("contentToReuse"); - @Deprecated @NonNls public static final String CONTENT_TO_REUSE = CONTENT_TO_REUSE_DATA_KEY.getName(); + @SuppressWarnings({"UnusedDeclaration", "deprecation"}) @Deprecated @NonNls + public static final String CONTENT_TO_REUSE = CONTENT_TO_REUSE_DATA_KEY.getName(); @Override @Nullable diff --git a/platform/lang-api/src/com/intellij/ide/util/projectWizard/AbstractModuleBuilder.java b/platform/lang-api/src/com/intellij/ide/util/projectWizard/AbstractModuleBuilder.java index 020ff5658a98..485514fd9e58 100644 --- a/platform/lang-api/src/com/intellij/ide/util/projectWizard/AbstractModuleBuilder.java +++ b/platform/lang-api/src/com/intellij/ide/util/projectWizard/AbstractModuleBuilder.java @@ -53,4 +53,9 @@ public abstract class AbstractModuleBuilder extends ProjectBuilder { public abstract void setModuleFilePath(@NonNls String path); public abstract void setContentEntryPath(String moduleRootPath); + + @Override + public boolean equals(Object obj) { + return obj instanceof AbstractModuleBuilder && getBuilderId() != null && getBuilderId().equals(((AbstractModuleBuilder)obj).getBuilderId()); + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java index f07d31847302..f4563f47e53e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -107,9 +107,11 @@ public class PsiChangeHandler extends PsiTreeChangeAdapter implements Disposable application.invokeLater(new Runnable() { @Override public void run() { - EditorMarkupModel markupModel = (EditorMarkupModel)editor.getMarkupModel(); - PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(editor.getDocument()); - TrafficLightRenderer.setOrRefreshErrorStripeRenderer(markupModel, myProject, editor.getDocument(), file); + if (!editor.isDisposed()) { + EditorMarkupModel markupModel = (EditorMarkupModel)editor.getMarkupModel(); + PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(editor.getDocument()); + TrafficLightRenderer.setOrRefreshErrorStripeRenderer(markupModel, myProject, editor.getDocument(), file); + } } }, ModalityState.stateForComponent(editor.getComponent()), myProject.getDisposed()); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java index 26d46527065b..9d6426fa02ee 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java @@ -279,7 +279,7 @@ public class TemplateBuilderImpl implements TemplateBuilder { public void run() { final Project project = myFile.getProject(); VirtualFile file = myFile.getVirtualFile(); - assert file != null; + assert file != null: "Virtual file is null for " + file; OpenFileDescriptor descriptor = new OpenFileDescriptor(project, file); final Editor editor = FileEditorManager.getInstance(project).openTextEditor(descriptor, true); diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index c5ad2799230e..79e0220c1174 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -922,7 +922,21 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo if (group == null) { group = (ActionGroup)actionManager.getAction(CONSOLE_VIEW_POPUP_MENU); } - final ActionPopupMenu menu = actionManager.createActionPopupMenu(ActionPlaces.EDITOR_POPUP, group); + final ConsoleActionsPostProcessor[] postProcessors = Extensions.getExtensions(ConsoleActionsPostProcessor.EP_NAME); + AnAction[] result = group.getChildren(null); + + for (ConsoleActionsPostProcessor postProcessor : postProcessors) { + result = postProcessor.postProcessPopupActions(this, result); + } + final AnAction[] processedActions = result; + final ActionGroup processedGroup = new ActionGroup() { + @NotNull + @Override + public AnAction[] getChildren(@Nullable AnActionEvent e) { + return processedActions; + } + }; + final ActionPopupMenu menu = actionManager.createActionPopupMenu(ActionPlaces.EDITOR_POPUP, processedGroup); menu.getComponent().show(mouseEvent.getComponent(), mouseEvent.getX(), mouseEvent.getY()); } diff --git a/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java b/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java index 6be1ad45f409..e2f8a5a717fe 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java @@ -22,6 +22,7 @@ import com.intellij.execution.configurations.RunProfileState; import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; /** * @author spleaner @@ -29,10 +30,10 @@ import com.intellij.openapi.project.Project; public abstract class DefaultProgramRunner extends GenericProgramRunner { @Override - protected RunContentDescriptor doExecute(final Project project, - final RunProfileState state, + protected RunContentDescriptor doExecute(@NotNull final Project project, + @NotNull final RunProfileState state, final RunContentDescriptor contentToReuse, - final ExecutionEnvironment env) throws ExecutionException { + @NotNull final ExecutionEnvironment env) throws ExecutionException { FileDocumentManager.getInstance().saveAllDocuments(); ExecutionResult executionResult = state.execute(env.getExecutor(), this); if (executionResult == null) return null; diff --git a/platform/lang-impl/src/com/intellij/ide/actions/NewElementAction.java b/platform/lang-impl/src/com/intellij/ide/actions/NewElementAction.java index 85327a2fa45f..e7db94f42206 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/NewElementAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/NewElementAction.java @@ -84,23 +84,28 @@ public class NewElementAction extends AnAction implements DumbAware, PopupActio @Override public void update(AnActionEvent e){ - final Presentation presentation = e.getPresentation(); - final DataContext context = e.getDataContext(); - final Project project = CommonDataKeys.PROJECT.getData(context); + Presentation presentation = e.getPresentation(); + Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); if (project == null) { presentation.setEnabled(false); return; } - if (Boolean.TRUE.equals(LangDataKeys.NO_NEW_ACTION.getData(context))) { - presentation.setEnabled(false); - return; - } - if (PlatformDataKeys.FILE_EDITOR.getData(context) != null) { + if (!isEnabled(e)) { presentation.setEnabled(false); return; } - presentation.setEnabled(!ActionGroupUtil.isGroupEmpty(getGroup(context), e)); + presentation.setEnabled(!ActionGroupUtil.isGroupEmpty(getGroup(e.getDataContext()), e)); + } + + protected boolean isEnabled(AnActionEvent e) { + if (Boolean.TRUE.equals(LangDataKeys.NO_NEW_ACTION.getData(e.getDataContext()))) { + return false; + } + if (PlatformDataKeys.FILE_EDITOR.getData(e.getDataContext()) != null) { + return false; + } + return true; } protected ActionGroup getGroup(DataContext dataContext) { diff --git a/platform/lang-impl/src/com/intellij/ide/actions/NewElementSamePlaceAction.java b/platform/lang-impl/src/com/intellij/ide/actions/NewElementSamePlaceAction.java index a77e20980417..9ab0f8e5f6b7 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/NewElementSamePlaceAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/NewElementSamePlaceAction.java @@ -17,10 +17,17 @@ package com.intellij.ide.actions; import com.intellij.ide.IdeBundle; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.LangDataKeys; public class NewElementSamePlaceAction extends NewElementAction { @Override protected String getPopupTitle() { return IdeBundle.message("title.popup.new.element.same.place"); } + + @Override + protected boolean isEnabled(AnActionEvent e) { + return LangDataKeys.IDE_VIEW.getData(e.getDataContext()) != null; + } } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java index eeb09fbec56a..1d9ef8c6525b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.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. @@ -37,7 +37,6 @@ import com.intellij.psi.impl.PsiDocumentManagerImpl; import com.intellij.psi.impl.PsiManagerImpl; import com.intellij.psi.impl.PsiTreeChangeEventImpl; import com.intellij.psi.impl.smartPointers.SmartPointerManagerImpl; -import com.intellij.util.FileContentUtil; import com.intellij.util.FileContentUtilCore; import com.intellij.util.messages.MessageBusConnection; import org.jetbrains.annotations.NotNull; diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java b/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java index b18187610774..5595212c4519 100644 --- a/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java +++ b/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java @@ -8,6 +8,7 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.DoubleClickListener; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.table.JBTable; @@ -444,7 +445,7 @@ public class InstalledPackagesPanel extends JPanel { final int finalIndex = i; final InstalledPackage pkg = getInstalledPackageAt(finalIndex); restPackageCount.incrementAndGet(); - serviceEx.fetchLatestVersion(pkg.getName(), new CatchingConsumer() { + serviceEx.fetchLatestVersion(pkg, new CatchingConsumer() { private void decrement() { if (restPackageCount.decrementAndGet() == 0) { @@ -535,8 +536,10 @@ public class InstalledPackagesPanel extends JPanel { final JLabel cell = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); final String version = (String)table.getValueAt(row, 1); final String availableVersion = (String)table.getValueAt(row, 2); - cell.setIcon(PackageVersionComparator.VERSION_COMPARATOR.compare(version, availableVersion) < 0 && column == 2 ? - AllIcons.Vcs.Arrow_right : null); + boolean update = column == 2 && + StringUtil.isNotEmpty(availableVersion) && + PackageVersionComparator.VERSION_COMPARATOR.compare(version, availableVersion) < 0; + cell.setIcon(update ? AllIcons.Vcs.Arrow_right : null); final Object pyPackage = table.getValueAt(row, 0); if (pyPackage instanceof InstalledPackage) { cell.setToolTipText(((InstalledPackage) pyPackage).getTooltipText()); diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java b/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java index 7fb47ac0dbce..923bdf9655f2 100644 --- a/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java +++ b/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java @@ -15,6 +15,6 @@ public abstract class PackageManagementServiceEx extends PackageManagementServic public abstract boolean shouldFetchLatestVersionsForOnlyInstalledPackages(); - public abstract void fetchLatestVersion(@NotNull String packageName, @NotNull final CatchingConsumer consumer); + public abstract void fetchLatestVersion(@NotNull InstalledPackage pkg, @NotNull final CatchingConsumer consumer); } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/dialogs/AgreementDialog.java b/platform/platform-api/src/com/intellij/openapi/ui/dialogs/AgreementDialog.java new file mode 100644 index 000000000000..9addc1cf15ef --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/ui/dialogs/AgreementDialog.java @@ -0,0 +1,104 @@ +/* + * 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.openapi.ui.dialogs; + +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.ui.ScrollPaneFactory; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.text.MessageFormat; +import java.util.ResourceBundle; + +public class AgreementDialog extends DialogWrapper { + private final Font myFont = new Font("SansSerif", Font.PLAIN, 12); + private final ResourceBundle myBundle = ResourceBundle.getBundle("messages.LicenseCommonBundle"); + + private final String myText; + private JCheckBox myAcceptCheckBox; + private boolean myOK = false; + + public AgreementDialog(String text, String programName) { + super(null, false, true); + getPeer().setAppIcons(); + + myText = text; + String title; + if (programName != null) { + title = MessageFormat.format(myBundle.getString("license.agreement.title.for"), programName); + } + else { + title = myBundle.getString("license.agreement.title"); + } + + setTitle(title); + + init(); + + getOKAction().setEnabled(false); + } + + protected void doOKAction() { + myOK = true; + super.doOKAction(); + } + + protected JComponent createNorthPanel() { + JPanel panel = new JPanel(new BorderLayout()); + String text = myBundle.getString("license.agreement.prompt"); + JLabel licensePrompt = new JLabel(text); + licensePrompt.setFocusable(false); + licensePrompt.setFont(myFont); + licensePrompt.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 5)); + panel.add(licensePrompt, BorderLayout.WEST); + panel.add(new JPanel(), BorderLayout.CENTER); + return panel; + } + + public boolean isAgreed() { + return myOK && myAcceptCheckBox.isSelected(); + } + + protected JComponent createCenterPanel() { + JPanel optionsPanel = new JPanel(new BorderLayout()); + JTextArea licenseTextArea = new JTextArea(myText, 20, 50); + licenseTextArea.getCaret().setDot(0); + licenseTextArea.setFont(myFont); + licenseTextArea.setLineWrap(true); + licenseTextArea.setWrapStyleWord(true); + licenseTextArea.setEditable(false); + JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(licenseTextArea); + + optionsPanel.add(scrollPane, BorderLayout.CENTER); + JPanel agreePanel = new JPanel(new GridLayout(1, 1)); + agreePanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 5)); + myAcceptCheckBox = new JCheckBox(myBundle.getString("license.agreement.accept.checkbox")); + myAcceptCheckBox.setMnemonic(myAcceptCheckBox.getText().charAt(0)); + myAcceptCheckBox.setFont(myFont); + + agreePanel.add(myAcceptCheckBox); + optionsPanel.add(agreePanel, BorderLayout.SOUTH); + + myAcceptCheckBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + getOKAction().setEnabled(myAcceptCheckBox.isSelected()); + } + }); + return optionsPanel; + } +} diff --git a/platform/platform-api/src/com/intellij/ui/CollectionListModel.java b/platform/platform-api/src/com/intellij/ui/CollectionListModel.java index 15ea84583eee..663bf0e2d081 100644 --- a/platform/platform-api/src/com/intellij/ui/CollectionListModel.java +++ b/platform/platform-api/src/com/intellij/ui/CollectionListModel.java @@ -34,6 +34,10 @@ public class CollectionListModel extends AbstractListModel implements Editabl myItems = new ArrayList(items); } + public CollectionListModel(@NotNull final List items) { + this((Collection)items); + } + public CollectionListModel(final T... items) { myItems = ContainerUtilRt.newArrayList(items); } diff --git a/platform/platform-api/src/com/intellij/util/Alarm.java b/platform/platform-api/src/com/intellij/util/Alarm.java index 1605a167cc7f..9cafa8debef1 100644 --- a/platform/platform-api/src/com/intellij/util/Alarm.java +++ b/platform/platform-api/src/com/intellij/util/Alarm.java @@ -357,7 +357,7 @@ public class Alarm implements Disposable { @Override public String toString() { Runnable task = getTask(); - return super.toString() + (task != null ? " "+task:null); + return super.toString() + (task != null ? ": "+task : ""); } } diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/CertificateConfigurable.java b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateConfigurable.java index f28b103a5cd8..8c706bc59283 100644 --- a/platform/platform-api/src/com/intellij/util/net/ssl/CertificateConfigurable.java +++ b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateConfigurable.java @@ -27,7 +27,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; -import static com.intellij.util.net.ssl.CertificateWrapper.CommonField.COMMON_NAME; +import static com.intellij.util.net.ssl.CertificateUtil.getCommonName; import static com.intellij.util.net.ssl.ConfirmingTrustManager.MutableTrustManager; /** @@ -63,7 +63,7 @@ public class CertificateConfigurable implements SearchableConfigurable, Configur if (!new CertificateWrapper(certificate).isValid()) { setForeground(UIUtil.getLabelDisabledForeground()); } - setText(new CertificateWrapper(certificate).getSubjectField(COMMON_NAME)); + setText(getCommonName(certificate)); } }); @@ -136,7 +136,7 @@ public class CertificateConfigurable implements SearchableConfigurable, Configur myDetailsPanel.add(scrollPane, uniqueName); } - private String getCardName(X509Certificate certificate) { + private static String getCardName(X509Certificate certificate) { return certificate.getSubjectX500Principal().getName(); } @@ -203,13 +203,13 @@ public class CertificateConfigurable implements SearchableConfigurable, Configur for (X509Certificate certificate : added) { if (!myTrustManager.addCertificate(certificate)) { - throw new ConfigurationException("Cannot add certificate", "Cannot Add Certificate"); + throw new ConfigurationException("Cannot add certificate for " + getCommonName(certificate), "Cannot Add Certificate"); } } for (X509Certificate certificate : removed) { if (!myTrustManager.removeCertificate(certificate)) { - throw new ConfigurationException("Cannot remove certificate", "Cannot Remove Certificate"); + throw new ConfigurationException("Cannot remove certificate for " + getCommonName(certificate), "Cannot Remove Certificate"); } } @@ -256,12 +256,18 @@ public class CertificateConfigurable implements SearchableConfigurable, Configur @Override public void certificateAdded(X509Certificate certificate) { - getListModel().add(certificate); + CollectionListModel model = getListModel(); + if (model.getElementIndex(certificate) < 0) { + model.add(certificate); + } addCertificatePanel(certificate); } @Override public void certificateRemoved(X509Certificate certificate) { - getListModel().remove(certificate); + CollectionListModel model = getListModel(); + if (model.getElementIndex(certificate) >= 0) { + model.remove(certificate); + } } } diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/CertificateUtil.java b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateUtil.java index c02a9382a721..a1e36236c0e4 100644 --- a/platform/platform-api/src/com/intellij/util/net/ssl/CertificateUtil.java +++ b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateUtil.java @@ -63,4 +63,11 @@ public class CertificateUtil { StreamUtil.closeStream(stream); } } + + /** + * @return subjects common name, usually it's domain name pattern, e.g. *.github.com + */ + public static String getCommonName(@NotNull X509Certificate certificate) { + return new CertificateWrapper(certificate).getSubjectField(CertificateWrapper.CommonField.COMMON_NAME); + } } diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/ConfirmingTrustManager.java b/platform/platform-api/src/com/intellij/util/net/ssl/ConfirmingTrustManager.java index 8a8f05a44f0c..8d430ebe7c7b 100644 --- a/platform/platform-api/src/com/intellij/util/net/ssl/ConfirmingTrustManager.java +++ b/platform/platform-api/src/com/intellij/util/net/ssl/ConfirmingTrustManager.java @@ -260,7 +260,7 @@ public class ConfirmingTrustManager extends ClientOnlyTrustManager { } private static String createAlias(@NotNull X509Certificate certificate) { - return new CertificateWrapper(certificate).getSubjectField(CertificateWrapper.CommonField.COMMON_NAME); + return CertificateUtil.getCommonName(certificate); } /** @@ -287,6 +287,10 @@ public class ConfirmingTrustManager extends ClientOnlyTrustManager { } // for listeners X509Certificate certificate = getCertificate(alias); + if (certificate == null) { + LOG.error("No certificate found for alias: " + alias); + return false; + } myKeyStore.deleteEntry(alias); flushKeyStore(); // trust manager should be updated each time its key store was modified diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties index 10113e560409..116adfe47398 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties @@ -151,6 +151,8 @@ Tree.paintLines=false Tree.textBackground=ffffff Tree.selectionBorderColor=3875d6 +EditorPane.background=ffffff + List.background=ffffff Hyperlink.linkColor=589df6 diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/LaterInvocator.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/LaterInvocator.java index 841cda70bc5a..adb76477f181 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/LaterInvocator.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/LaterInvocator.java @@ -57,10 +57,10 @@ public class LaterInvocator { } private static class RunnableInfo { - final Runnable runnable; - final ModalityState modalityState; - final Condition expired; - final ActionCallback callback; + @NotNull private final Runnable runnable; + @NotNull private final ModalityState modalityState; + @NotNull private final Condition expired; + @NotNull private final ActionCallback callback; public RunnableInfo(@NotNull Runnable runnable, @NotNull ModalityState modalityState, @@ -74,7 +74,7 @@ public class LaterInvocator { @NonNls public String toString() { - return "[runnable: " + runnable + "; state=" + modalityState + "] "; + return "[runnable: " + runnable + "; state=" + modalityState + (expired.value(null) ? "; expired" : "")+"] "; } } @@ -88,21 +88,12 @@ public class LaterInvocator { private static final EventDispatcher ourModalityStateMulticaster = EventDispatcher.create(ModalityStateListener.class); - - private static final ArrayList ourForcedFlushQueue = new ArrayList(); - - public static void addModalityStateListener(@NotNull ModalityStateListener listener) { - ourModalityStateMulticaster.addListener(listener); - } + private static final List ourForcedFlushQueue = new ArrayList(); public static void addModalityStateListener(@NotNull ModalityStateListener listener, @NotNull Disposable parentDisposable) { ourModalityStateMulticaster.addListener(listener, parentDisposable); } - public static void removeModalityStateListener(@NotNull ModalityStateListener listener) { - ourModalityStateMulticaster.removeListener(listener); - } - @NotNull static ModalityStateEx modalityStateForWindow(@NotNull Window window) { int index = ourModalEntities.indexOf(window); @@ -113,9 +104,7 @@ public class LaterInvocator { if (window instanceof Dialog && ((Dialog)window).isModal()) { return ownerState.appendEntity(window); } - else { - return ownerState; - } + return ownerState; } ArrayList result = new ArrayList(); @@ -132,27 +121,32 @@ public class LaterInvocator { return new ModalityStateEx(result.toArray()); } + @NotNull public static ActionCallback invokeLater(@NotNull Runnable runnable) { return invokeLater(runnable, Conditions.FALSE); } + @NotNull public static ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull Condition expired) { ModalityState modalityState = ModalityState.defaultModalityState(); return invokeLater(runnable, modalityState, expired); } + @NotNull public static ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull ModalityState modalityState) { return invokeLater(runnable, modalityState, Conditions.FALSE); } + @NotNull public static ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull ModalityState modalityState, @NotNull Condition expired) { ourFrequentEventDetector.eventHappened(); final ActionCallback callback = new ActionCallback(); + RunnableInfo runnableInfo = new RunnableInfo(runnable, modalityState, expired, callback); synchronized (LOCK) { - ourQueue.add(new RunnableInfo(runnable, modalityState, expired, callback)); + ourQueue.add(runnableInfo); } requestFlush(); return callback; @@ -177,7 +171,7 @@ public class LaterInvocator { @NonNls public String toString() { - return "InvokeAndWait[" + runnable.toString() + "]"; + return "InvokeAndWait[" + runnable + "]"; } }; invokeLater(runnable1, modalityState); @@ -326,7 +320,7 @@ public class LaterInvocator { lastInfo.callback.setDone(); } catch (ProcessCanceledException ex) { - // ignore + // ignore } catch (Throwable t) { if (t instanceof StackOverflowError) { @@ -348,20 +342,23 @@ public class LaterInvocator { @NonNls public String toString() { - return "LaterInvocator[lastRunnable=" + myLastInfo + "]"; + return "LaterInvocator.FlushQueue" + (myLastInfo == null ? "" : " lastInfo="+myLastInfo); } } @TestOnly - public static List dumpQueue() { + static String dumpQueue() { synchronized (LOCK) { - if (!ourQueue.isEmpty()) { - ArrayList r = new ArrayList(); - r.addAll(ourQueue); - Collections.reverse(r); - return r; + @NonNls String result = ""; + if (!ourForcedFlushQueue.isEmpty()) { + result = "(Forced queue: " + ourForcedFlushQueue + ") "; } + List r = new ArrayList(ourQueue); + result += r + (ourQueueSkipCount == 0 ? "" : " (ourQueueSkipCount="+ourQueueSkipCount+")") + + (ourModalEntities.isEmpty() ? " (non-modal)" : " (modal entities: "+ourModalEntities+")" + + (FLUSHER_SCHEDULED.get() ? " (Flusher scheduled)" : "") + ); + return result; } - return null; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/HighlightModeAction.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/HighlightModeAction.java new file mode 100644 index 000000000000..06e25a95fe57 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/HighlightModeAction.java @@ -0,0 +1,103 @@ +/* + * 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.openapi.diff.actions; + +import com.intellij.CommonBundle; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.openapi.actionSystem.ex.ComboBoxAction; +import com.intellij.openapi.diff.DiffBundle; +import com.intellij.openapi.diff.ex.DiffPanelEx; +import com.intellij.openapi.diff.impl.DiffPanelImpl; +import com.intellij.openapi.diff.impl.processing.HighlightMode; +import com.intellij.openapi.project.DumbAware; +import com.intellij.util.containers.HashMap; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; +import java.util.Map; + +public class HighlightModeAction extends ComboBoxAction implements DumbAware { + private final Map myActions = new HashMap(); + private static final HighlightMode[] ourActionOrder = + new HighlightMode[]{HighlightMode.BY_WORD, HighlightMode.BY_LINE, HighlightMode.NO_HIGHLIGHTING}; + + public HighlightModeAction() { + myActions.put(HighlightMode.BY_WORD, + new SetHighlightModeAction(DiffBundle.message("diff.acton.highlight.mode.action.by.word"), HighlightMode.BY_WORD)); + myActions.put(HighlightMode.BY_LINE, + new SetHighlightModeAction(DiffBundle.message("diff.acton.highlight.mode.action.by.line"), HighlightMode.BY_LINE)); + myActions.put(HighlightMode.NO_HIGHLIGHTING, + new SetHighlightModeAction(DiffBundle.message("diff.acton.highlight.mode.action.no.highlighting"), + HighlightMode.NO_HIGHLIGHTING)); + } + + @Override + public JComponent createCustomComponent(final Presentation presentation) { + JPanel panel = new JPanel(new BorderLayout()); + final JLabel label = new JLabel(CommonBundle.message("diff.acton.highlight.mode.action.name")); + label.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4)); + panel.add(label, BorderLayout.WEST); + panel.add(super.createCustomComponent(presentation), BorderLayout.CENTER); + return panel; + } + + @NotNull + protected DefaultActionGroup createPopupActionGroup(JComponent button) { + DefaultActionGroup actionGroup = new DefaultActionGroup(); + for (HighlightMode comparisonPolicy : ourActionOrder) { + actionGroup.add(myActions.get(comparisonPolicy)); + } + return actionGroup; + } + + public void update(AnActionEvent e) { + super.update(e); + Presentation presentation = e.getPresentation(); + DiffPanelEx diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext()); + if (diffPanel != null && diffPanel.getComponent().isDisplayable()) { + AnAction action = myActions.get(diffPanel.getHighlightMode()); + Presentation templatePresentation = action.getTemplatePresentation(); + presentation.setIcon(templatePresentation.getIcon()); + presentation.setText(templatePresentation.getText()); + presentation.setEnabled(true); + } + else { + presentation.setIcon(null); + presentation.setText(DiffBundle.message("diff.acton.highlight.mode.not.available.action.name")); + presentation.setEnabled(false); + } + } + + private static class SetHighlightModeAction extends AnAction implements DumbAware { + private final HighlightMode myHighlightMode; + + public SetHighlightModeAction(String text, HighlightMode mode) { + super(text); + myHighlightMode = mode; + } + + public void actionPerformed(AnActionEvent e) { + final DiffPanelImpl diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext()); + if (diffPanel != null) { + diffPanel.setHighlightMode(myHighlightMode); + } + } + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/IgnoreWhiteSpacesAction.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/IgnoreWhiteSpacesAction.java index 78c5ba756923..6a68ad75d5d8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/actions/IgnoreWhiteSpacesAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/IgnoreWhiteSpacesAction.java @@ -82,7 +82,7 @@ public class IgnoreWhiteSpacesAction extends ComboBoxAction implements DumbAware } } - private static class IgnoringPolicyAction extends AnAction { + private static class IgnoringPolicyAction extends AnAction implements DumbAware { private final ComparisonPolicy myPolicy; public IgnoringPolicyAction(String text, ComparisonPolicy policy) { diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/ToggleAutoScrollAction.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/ToggleAutoScrollAction.java new file mode 100644 index 000000000000..04ec31e10ff6 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/ToggleAutoScrollAction.java @@ -0,0 +1,50 @@ +/* + * 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.openapi.diff.actions; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.diff.ex.DiffPanelEx; +import com.intellij.openapi.diff.impl.DiffPanelImpl; +import com.intellij.openapi.project.DumbAware; +import com.intellij.ui.ToggleActionButton; + +import javax.swing.*; + +public class ToggleAutoScrollAction extends ToggleActionButton implements DumbAware { + public ToggleAutoScrollAction() { + super("Auto Scroll", AllIcons.General.AutoscrollToSource); + } + + @Override + public boolean isSelected(AnActionEvent e) { + DiffPanelEx diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext()); + if (diffPanel != null) { + return diffPanel.isAutoScrollEnabled(); + } + else { + return true; + } + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + final DiffPanelImpl diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext()); + if (diffPanel != null) { + diffPanel.setAutoScrollEnabled(state); + } + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java index e0df0bb7dc2b..933d017be2ef 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java @@ -27,6 +27,7 @@ package com.intellij.openapi.diff.ex; import com.intellij.openapi.Disposable; import com.intellij.openapi.diff.DiffPanel; import com.intellij.openapi.diff.impl.ComparisonPolicy; +import com.intellij.openapi.diff.impl.processing.HighlightMode; import com.intellij.openapi.editor.Editor; import org.jetbrains.annotations.Nullable; @@ -41,4 +42,12 @@ public interface DiffPanelEx extends DiffPanel, Disposable { void setComparisonPolicy(ComparisonPolicy comparisonPolicy); ComparisonPolicy getComparisonPolicy(); + + void setAutoScrollEnabled(boolean enabled); + + boolean isAutoScrollEnabled(); + + void setHighlightMode(HighlightMode highlightMode); + + HighlightMode getHighlightMode(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java index 9978b78f8533..913d5e7cc8f9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java @@ -26,6 +26,7 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.*; import com.intellij.openapi.diff.actions.MergeActionGroup; +import com.intellij.openapi.diff.actions.ToggleAutoScrollAction; import com.intellij.openapi.diff.ex.DiffPanelEx; import com.intellij.openapi.diff.ex.DiffPanelOptions; import com.intellij.openapi.diff.impl.external.DiffManagerImpl; @@ -33,6 +34,7 @@ import com.intellij.openapi.diff.impl.fragments.Fragment; import com.intellij.openapi.diff.impl.fragments.FragmentList; import com.intellij.openapi.diff.impl.highlighting.DiffPanelState; import com.intellij.openapi.diff.impl.highlighting.FragmentSide; +import com.intellij.openapi.diff.impl.processing.HighlightMode; import com.intellij.openapi.diff.impl.processing.HorizontalDiffSplitter; import com.intellij.openapi.diff.impl.settings.DiffMergeEditorSetting; import com.intellij.openapi.diff.impl.settings.DiffMergeSettings; @@ -110,6 +112,9 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid public void customize(DiffToolbar toolbar) { ActionManager actionManager = ActionManager.getInstance(); toolbar.addAction(actionManager.getAction("DiffPanel.Toolbar")); + toolbar.addSeparator(); + toolbar.addAction(new ToggleAutoScrollAction()); + toolbar.addSeparator(); toolbar.addAction(actionManager.getAction("ContextHelp")); toolbar.addAction(getEditSourceAction()); toolbar.addSeparator(); @@ -467,10 +472,27 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid } } + public void setAutoScrollEnabled(boolean enabled) { + myScrollSupport.setEnabled(enabled); + } + + public boolean isAutoScrollEnabled() { + return myScrollSupport.isEnabled(); + } + public void setComparisonPolicy(ComparisonPolicy comparisonPolicy) { setComparisonPolicy(comparisonPolicy, true); } + public void setHighlightMode(HighlightMode highlightMode) { + myData.setHighlightMode(highlightMode); + rediff(); + } + + public HighlightMode getHighlightMode() { + return myData.getHighlightMode(); + } + public Rediffers getDiffUpdater() { return myDiffUpdater; } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java index 5446f66e50c6..d90005d70678 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java @@ -24,6 +24,7 @@ import com.intellij.openapi.diff.impl.fragments.FragmentList; import com.intellij.openapi.diff.impl.fragments.FragmentListImpl; import com.intellij.openapi.diff.impl.fragments.LineFragment; import com.intellij.openapi.diff.impl.processing.DiffPolicy; +import com.intellij.openapi.diff.impl.processing.HighlightMode; import com.intellij.openapi.diff.impl.processing.TextCompareProcessor; import com.intellij.openapi.diff.impl.splitter.LineBlocks; import com.intellij.openapi.project.Project; @@ -37,6 +38,7 @@ import java.util.Iterator; public abstract class SimpleDiffPanelState implements Disposable { protected ComparisonPolicy myComparisonPolicy = ComparisonPolicy.DEFAULT; protected DiffPolicy myDiffPolicy; + protected HighlightMode myHighlightMode; protected final EditorPlaceHolder myAppender1; protected final EditorPlaceHolder myAppender2; protected FragmentList myFragmentList = FragmentList.EMPTY; @@ -47,6 +49,7 @@ public abstract class SimpleDiffPanelState implements Disposable { myAppender2 = createEditorWrapper(project, changeListener, FragmentSide.SIDE2); myProject = project; myDiffPolicy = DiffPolicy.LINES_WO_FORMATTING; + myHighlightMode = HighlightMode.BY_WORD; Disposer.register(parentDisposable, this); } @@ -72,6 +75,14 @@ public abstract class SimpleDiffPanelState implements Disposable { return myComparisonPolicy; } + public HighlightMode getHighlightMode() { + return myHighlightMode; + } + + public void setHighlightMode(HighlightMode highlightMode) { + myHighlightMode = highlightMode; + } + public void dispose() { } @@ -105,7 +116,12 @@ public abstract class SimpleDiffPanelState implements Disposable { return LineBlocks.EMPTY; } - return addMarkup(new TextCompareProcessor(myComparisonPolicy, myDiffPolicy).process(myAppender1.getText(), myAppender2.getText())); + if (myHighlightMode == HighlightMode.NO_HIGHLIGHTING) { + return LineBlocks.fromLineFragments(new ArrayList()); + } + + return addMarkup(new TextCompareProcessor(myComparisonPolicy, myDiffPolicy, myHighlightMode == HighlightMode.BY_WORD) + .process(myAppender1.getText(), myAppender2.getText())); } public Project getProject() { return myProject; } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/TextCompareProcessor.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/TextCompareProcessor.java index 1555656c3865..01534b487ff5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/TextCompareProcessor.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/TextCompareProcessor.java @@ -32,28 +32,38 @@ public class TextCompareProcessor { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.processing.Processor"); private final DiffPolicy myDiffPolicy; @NotNull private final ComparisonPolicy myComparisonPolicy; + private final boolean mySearchForSubFragments; - public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy, final DiffPolicy diffPolicy) { + public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy, + final DiffPolicy diffPolicy, + boolean searchForSubFragments) { myComparisonPolicy = comparisonPolicy; myDiffPolicy = diffPolicy; + mySearchForSubFragments = searchForSubFragments; } - public TextCompareProcessor(ComparisonPolicy comparisonPolicy) { + public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy, final DiffPolicy diffPolicy) { + this(comparisonPolicy, diffPolicy, true); + } + + public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy) { this(comparisonPolicy, DiffPolicy.LINES_WO_FORMATTING); } public ArrayList process(String text1, String text2) throws FilesTooBigForDiffException { DiffFragment[] woFormattingBlocks = myDiffPolicy.buildFragments(text1, text2); - DiffFragment[] step1lineFragments = new DiffCorrection.TrueLineBlocks(myComparisonPolicy). - correctAndNormalize(woFormattingBlocks); + DiffFragment[] step1lineFragments = new DiffCorrection.TrueLineBlocks(myComparisonPolicy).correctAndNormalize(woFormattingBlocks); ArrayList lineBlocks = new DiffFragmentsProcessor().process(step1lineFragments); - for (LineFragment lineBlock : lineBlocks) { - if (lineBlock.isOneSide() || lineBlock.isEqual()) continue; - String subText1 = lineBlock.getText(text1, FragmentSide.SIDE1); - String subText2 = lineBlock.getText(text2, FragmentSide.SIDE2); - ArrayList subFragments = findSubFragments(subText1, subText2); - lineBlock.setChildren(new ArrayList(subFragments)); - lineBlock.adjustTypeFromChildrenTypes(); + + if (mySearchForSubFragments) { + for (LineFragment lineBlock : lineBlocks) { + if (lineBlock.isOneSide() || lineBlock.isEqual()) continue; + String subText1 = lineBlock.getText(text1, FragmentSide.SIDE1); + String subText2 = lineBlock.getText(text2, FragmentSide.SIDE2); + ArrayList subFragments = findSubFragments(subText1, subText2); + lineBlock.setChildren(new ArrayList(subFragments)); + lineBlock.adjustTypeFromChildrenTypes(); + } } return lineBlocks; } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/SyncScrollSupport.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/SyncScrollSupport.java index ab45e1ec2ede..47ba0e817ced 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/SyncScrollSupport.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/SyncScrollSupport.java @@ -36,6 +36,7 @@ public class SyncScrollSupport implements Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.util.SyncScrollSupport"); private boolean myDuringVerticalScroll = false; private final ArrayList myScrollers = new ArrayList(); + private boolean myEnabled = true; public void install(EditingSides[] sideContainers) { Disposer.dispose(this); @@ -58,6 +59,14 @@ public class SyncScrollSupport implements Disposable { myScrollers.clear(); } + public void setEnabled(boolean enabled) { + myEnabled = enabled; + } + + public boolean isEnabled() { + return myEnabled; + } + private void install2(Editor[] editors, EditingSides[] sideContainers) { addSlavesScroller(editors[0], new Pair(FragmentSide.SIDE1, sideContainers[0])); addSlavesScroller(editors[1], new Pair(FragmentSide.SIDE2, sideContainers[0])); @@ -100,7 +109,7 @@ public class SyncScrollSupport implements Disposable { } public void visibleAreaChanged(VisibleAreaEvent e) { - if (myDuringVerticalScroll) return; + if (!myEnabled || myDuringVerticalScroll) return; Rectangle newRectangle = e.getNewRectangle(); Rectangle oldRectangle = e.getOldRectangle(); if (newRectangle == null || oldRectangle == null) return; diff --git a/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.java b/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.java index 7315999171c8..923935b0645c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.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. @@ -57,7 +57,7 @@ public class FileContentQueue { private final Object myProceedWithProcessingLock = new Object(); private static final boolean ourAllowParallelFileReading = SystemProperties.getBooleanProperty("idea.allow.parallel.file.reading", true); - public void queue(final Collection files, @NotNull final ProgressIndicator indicator) { + public void queue(@NotNull Collection files, @NotNull final ProgressIndicator indicator) { myFilesToLoadQueue.addAll(files); final Runnable contentLoadingRunnable = new Runnable() { @Override diff --git a/platform/platform-impl/src/com/intellij/ui/EditorComboBoxEditor.java b/platform/platform-impl/src/com/intellij/ui/EditorComboBoxEditor.java index 2b9dce102509..f4dfb1059651 100644 --- a/platform/platform-impl/src/com/intellij/ui/EditorComboBoxEditor.java +++ b/platform/platform-impl/src/com/intellij/ui/EditorComboBoxEditor.java @@ -38,6 +38,7 @@ public class EditorComboBoxEditor implements ComboBoxEditor{ myTextField.setName(NAME); } + @Override public void selectAll() { myTextField.selectAll(); myTextField.requestFocus(); @@ -48,18 +49,22 @@ public class EditorComboBoxEditor implements ComboBoxEditor{ return myTextField.getEditor(); } + @Override public EditorTextField getEditorComponent() { return myTextField; } + @Override public void addActionListener(ActionListener l) { } + @Override public void removeActionListener(ActionListener l) { } + @Override public Object getItem() { return getDocument(); } @@ -68,6 +73,7 @@ public class EditorComboBoxEditor implements ComboBoxEditor{ return myTextField.getDocument(); } + @Override public void setItem(Object anObject) { myTextField.setDocument((Document)anObject); } diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index 53b84612f59f..8f7600865961 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.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. @@ -95,7 +95,6 @@ public class AbstractPopup implements JBPopup { private boolean myCancelOnWindowDeactivation = true; private Dimension myForcedSize; private Point myForcedLocation; - private ChildFocusWatcher myFocusWatcher; private boolean myCancelKeyEnabled; private boolean myLocateByContent; protected FocusTrackback myFocusTrackback; @@ -1037,7 +1036,7 @@ public class AbstractPopup implements JBPopup { } - myFocusWatcher = new ChildFocusWatcher(myContent) { + ChildFocusWatcher focusWatcher = new ChildFocusWatcher(myContent) { @Override protected void onFocusGained(final FocusEvent event) { setWindowActive(true); @@ -1047,8 +1046,8 @@ public class AbstractPopup implements JBPopup { protected void onFocusLost(final FocusEvent event) { setWindowActive(false); } - }; + Disposer.register(this, focusWatcher); mySpeedSearchPatternField = new JTextField(); if (SystemInfo.isMac) { @@ -1058,7 +1057,7 @@ public class AbstractPopup implements JBPopup { } private Window updateMaskAndAlpha(Window window) { - if (window == null) return window; + if (window == null) return null; final WindowManagerEx wndManager = getWndManager(); if (wndManager == null) return window; @@ -1249,11 +1248,6 @@ public class AbstractPopup implements JBPopup { } myMouseOutCanceller = null; - if (myFocusWatcher != null) { - myFocusWatcher.dispose(); - myFocusWatcher = null; - } - resetWindow(); if (myFinalRunnable != null) { diff --git a/platform/platform-resources-en/src/messages/CommonBundle.properties b/platform/platform-resources-en/src/messages/CommonBundle.properties index a07d1631bad5..e027bc32a12d 100644 --- a/platform/platform-resources-en/src/messages/CommonBundle.properties +++ b/platform/platform-resources-en/src/messages/CommonBundle.properties @@ -175,4 +175,5 @@ This may lead to incorrect behaviour. Proxy should be set in Settings | HTTP Pro This JVM property is old and its usage is not recommended by Oracle.\n\ \n(Note: It could have been assigned by some code dynamically.) label.proxy.exceptions.text=Example\: *.domain.com, 192.168.* -checkbox.automatic.proxy.configuration.url=Automatic proxy configuration URL\: \ No newline at end of file +checkbox.automatic.proxy.configuration.url=Automatic proxy configuration URL\: +diff.acton.highlight.mode.action.name=Highlighting Mode \ No newline at end of file diff --git a/platform/platform-resources-en/src/messages/DiffBundle.properties b/platform/platform-resources-en/src/messages/DiffBundle.properties index cb6a0d72819b..b0515df7f6f2 100644 --- a/platform/platform-resources-en/src/messages/DiffBundle.properties +++ b/platform/platform-resources-en/src/messages/DiffBundle.properties @@ -83,3 +83,7 @@ diff.content.selected.value=Selected Value diff.clipboard.vs.value.dialog.title=Clipboard vs Selected Value diff.can.not.show.unknown=Can not show diff for unknown file type +diff.acton.highlight.mode.action.by.word=By Word +diff.acton.highlight.mode.action.by.line=By Line +diff.acton.highlight.mode.action.no.highlighting=No Highlighting +diff.acton.highlight.mode.not.available.action.name= diff --git a/platform/platform-resources/src/brokenPlugins.json b/platform/platform-resources/src/brokenPlugins.json deleted file mode 100644 index 360f89a1dc13..000000000000 --- a/platform/platform-resources/src/brokenPlugins.json +++ /dev/null @@ -1,392 +0,0 @@ -[ - { - "updateId": 11696, - "pluginId": "com.jetbrains.php", - "version": "121.12" - }, - { - "updateId": 11749, - "pluginId": "com.jetbrains.php", - "version": "121.62" - }, - { - "updateId": 11879, - "pluginId": "com.jetbrains.php", - "version": "121.215" - }, - { - "updateId": 12109, - "pluginId": "com.jetbrains.php", - "version": "121.390" - }, - { - "updateId": 12215, - "pluginId": "com.jetbrains.php", - "version": "122.875" - }, - { - "updateId": 12290, - "pluginId": "com.jetbrains.php", - "version": "123.66" - }, - { - "updateId": 12766, - "pluginId": "com.jetbrains.php", - "version": "126.334" - }, - { - "updateId": 12851, - "pluginId": "com.jetbrains.php", - "version": "127.67" - }, - { - "updateId": 12895, - "pluginId": "com.jetbrains.php", - "version": "127.100" - }, - { - "updateId": 12992, - "pluginId": "com.jetbrains.php", - "version": "129.91" - }, - { - "updateId": 13260, - "pluginId": "com.jetbrains.php", - "version": "129.362" - }, - { - "updateId": 13473, - "pluginId": "com.jetbrains.php", - "version": "129.672" - }, - { - "updateId": 13636, - "pluginId": "com.jetbrains.php", - "version": "129.814" - }, - { - "updateId": 13711, - "pluginId": "com.jetbrains.php", - "version": "130.1176" - }, - { - "updateId": 13843, - "pluginId": "com.jetbrains.php", - "version": "130.1481" - }, - { - "updateId": 13933, - "pluginId": "com.jetbrains.php", - "version": "130.1639" - }, - { - "updateId": 14135, - "pluginId": "com.jetbrains.php", - "version": "131.98" - }, - { - "updateId": 14236, - "pluginId": "com.jetbrains.php", - "version": "131.205" - }, - { - "updateId": 14260, - "pluginId": "com.jetbrains.php", - "version": "131.235" - }, - { - "updateId": 14350, - "pluginId": "com.jetbrains.php", - "version": "131.332" - }, - { - "updateId": 14379, - "pluginId": "com.jetbrains.php", - "version": "131.374" - }, - { - "updateId": 14616, - "pluginId": "com.jetbrains.php", - "version": "133.51" - }, - { - "updateId": 14858, - "pluginId": "com.jetbrains.php", - "version": "133.326" - }, - { - "updateId": 14011, - "pluginId": "NodeJS", - "version": "132.15" - }, - { - "updateId": 14203, - "pluginId": "NodeJS", - "version": "132.324" - }, - { - "updateId": 14375, - "pluginId": "NodeJS", - "version": "132.709" - }, - { - "updateId": 14482, - "pluginId": "NodeJS", - "version": "132.944" - }, - { - "updateId": 14516, - "pluginId": "NodeJS", - "version": "132.947" - }, - { - "updateId": 14548, - "pluginId": "NodeJS", - "version": "132.1054" - }, - { - "updateId": 14581, - "pluginId": "NodeJS", - "version": "133.50" - }, - { - "updateId": 14595, - "pluginId": "NodeJS", - "version": "133.74" - }, - { - "updateId": 14665, - "pluginId": "NodeJS", - "version": "133.134" - }, - { - "updateId": 14693, - "pluginId": "NodeJS", - "version": "133.162" - }, - { - "updateId": 14706, - "pluginId": "NodeJS", - "version": "133.195" - }, - { - "updateId": 14707, - "pluginId": "NodeJS", - "version": "133.193" - }, - { - "updateId": 14715, - "pluginId": "NodeJS", - "version": "133.168" - }, - { - "updateId": 14790, - "pluginId": "NodeJS", - "version": "133.260" - }, - { - "updateId": 14820, - "pluginId": "NodeJS", - "version": "133.293" - }, - { - "updateId": 14868, - "pluginId": "NodeJS", - "version": "133.373" - }, - { - "updateId": 14031, - "pluginId": "org.intellij.clojure", - "version": "0.7.34" - }, - { - "updateId": 14076, - "pluginId": "org.intellij.clojure", - "version": "0.7.36" - }, - { - "updateId": 14428, - "pluginId": "org.intellij.clojure", - "version": "0.7.57" - }, - { - "updateId": 14604, - "pluginId": "org.intellij.clojure", - "version": "0.7.60" - }, - { - "updateId": 8976, - "pluginId": "org.intellij.scala", - "version": "0.4.407" - }, - { - "updateId": 9009, - "pluginId": "org.intellij.scala", - "version": "0.4.442" - }, - { - "updateId": 9041, - "pluginId": "org.intellij.scala", - "version": "0.4.472" - }, - { - "updateId": 9214, - "pluginId": "org.intellij.scala", - "version": "0.4.589" - }, - { - "updateId": 9343, - "pluginId": "org.intellij.scala", - "version": "0.4.748" - }, - { - "updateId": 9470, - "pluginId": "org.intellij.scala", - "version": "0.4.820" - }, - { - "updateId": 9473, - "pluginId": "org.intellij.scala", - "version": "0.4.833" - }, - { - "updateId": 9669, - "pluginId": "org.intellij.scala", - "version": "0.4.1084" - }, - { - "updateId": 9968, - "pluginId": "org.intellij.scala", - "version": "0.4.1371" - }, - { - "updateId": 10010, - "pluginId": "org.intellij.scala", - "version": "0.5.16" - }, - { - "updateId": 14027, - "pluginId": "org.intellij.scala", - "version": "0.18.39" - }, - { - "updateId": 14075, - "pluginId": "org.intellij.scala", - "version": "0.21.45" - }, - { - "updateId": 14130, - "pluginId": "org.intellij.scala", - "version": "0.21.50" - }, - { - "updateId": 14289, - "pluginId": "org.intellij.scala", - "version": "0.23.252" - }, - { - "updateId": 14440, - "pluginId": "org.intellij.scala", - "version": "0.23.282" - }, - { - "updateId": 14493, - "pluginId": "org.intellij.scala", - "version": "0.23.289" - }, - { - "updateId": 14574, - "pluginId": "org.intellij.scala", - "version": "0.23.308" - }, - { - "updateId": 14612, - "pluginId": "org.intellij.scala", - "version": "0.23.311" - }, - { - "updateId": 14666, - "pluginId": "org.intellij.scala", - "version": "0.26.308" - }, - { - "updateId": 14672, - "pluginId": "org.intellij.scala", - "version": "0.26.310" - }, - { - "updateId": 14697, - "pluginId": "org.intellij.scala", - "version": "0.26.314" - }, - { - "updateId": 14711, - "pluginId": "org.intellij.scala", - "version": "0.26.315" - }, - { - "updateId": 14728, - "pluginId": "org.intellij.scala", - "version": "0.26.318" - }, - { - "updateId": 14743, - "pluginId": "org.intellij.scala", - "version": "0.26.321" - }, - { - "updateId": 14767, - "pluginId": "org.intellij.scala", - "version": "0.26.323" - }, - { - "updateId": 14779, - "pluginId": "org.intellij.scala", - "version": "0.26.327" - }, - { - "updateId": 14845, - "pluginId": "org.intellij.scala", - "version": "0.26.331" - }, - { - "updateId": 14859, - "pluginId": "org.intellij.scala", - "version": "0.26.333" - }, - { - "updateId": 14863, - "pluginId": "org.intellij.scala", - "version": "0.26.335" - }, - { - "updateId": 14627, - "pluginId": "org.jetbrains.plugins.ruby", - "version": "6.0.0.20131121" - }, - { - "updateId": 14812, - "pluginId": "org.jetbrains.plugins.ruby", - "version": "6.0.0.20131207" - }, - { - "updateId": 14036, - "pluginId": "Pythonid", - "version": "2.11.2" - }, - { - "updateId": 14295, - "pluginId": "Pythonid", - "version": "3.0.1" - }, - { - "updateId": 14654, - "pluginId": "Pythonid", - "version": "3.1 Beta" - }, - { - "updateId": 14824, - "pluginId": "Pythonid", - "version": "3.1 Beta 2" - } -] \ No newline at end of file diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt new file mode 100644 index 000000000000..2478f6f0f58a --- /dev/null +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -0,0 +1,6 @@ +// This file contains list of broken plugins. +// Each line contains plugin ID and list of versions that are broken. +// If plugin name or version contains a space you can quote it like in command line. + +NodeJS 134.680 134.31 134.307 134.262 134.198 134.125 +com.jetbrains.php 133.51 133.326 131.98 131.374 131.332 131.235 131.205 130.1639 130.1481 130.1176 129.91 129.814 129.672 129.362 127.67 127.100 126.334 123.66 122.875 121.62 121.390 121.215 121.12 diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index c2e5c4aafaac..ab70a8603df4 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -550,6 +550,8 @@ + + diff --git a/platform/util/src/com/intellij/openapi/diff/impl/processing/HighlightMode.java b/platform/util/src/com/intellij/openapi/diff/impl/processing/HighlightMode.java new file mode 100644 index 000000000000..441aca3517eb --- /dev/null +++ b/platform/util/src/com/intellij/openapi/diff/impl/processing/HighlightMode.java @@ -0,0 +1,20 @@ +/* + * 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.openapi.diff.impl.processing; + +public enum HighlightMode { + BY_WORD, BY_LINE, NO_HIGHLIGHTING +} diff --git a/platform/util/src/com/intellij/openapi/util/WriteExternalException.java b/platform/util/src/com/intellij/openapi/util/WriteExternalException.java index 3d61f6e3ac7d..76714142f974 100644 --- a/platform/util/src/com/intellij/openapi/util/WriteExternalException.java +++ b/platform/util/src/com/intellij/openapi/util/WriteExternalException.java @@ -15,6 +15,10 @@ */ package com.intellij.openapi.util; +/** + * Throw this exception from {@link JDOMExternalizable#writeExternal(org.jdom.Element)} method if you don't want to store any settings. + * If you simply return from the method empty '' tag will be written leading to unneeded modification of configuration files. + */ public class WriteExternalException extends Exception { public WriteExternalException() { super(); diff --git a/platform/util/src/com/intellij/util/containers/OrderedSet.java b/platform/util/src/com/intellij/util/containers/OrderedSet.java index ce03ffcba6eb..76cfc8c27480 100644 --- a/platform/util/src/com/intellij/util/containers/OrderedSet.java +++ b/platform/util/src/com/intellij/util/containers/OrderedSet.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. @@ -18,28 +18,26 @@ package com.intellij.util.containers; import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.RandomAccess; +import java.util.Set; -public class OrderedSet extends AbstractList implements Set, RandomAccess { +// have to extend ArrayList because otherwise the spliterator() methods declared in Set and List are in conflict +public class OrderedSet extends ArrayList implements Set, RandomAccess { private final OpenTHashSet myHashSet; - private final ArrayList myElements; public OrderedSet() { this(ContainerUtil.canonicalStrategy()); } - public OrderedSet(TObjectHashingStrategy hashingStrategy) { + public OrderedSet(@NotNull TObjectHashingStrategy hashingStrategy) { this(hashingStrategy, 4); } - public OrderedSet(TObjectHashingStrategy hashingStrategy, int capacity) { + public OrderedSet(@NotNull TObjectHashingStrategy hashingStrategy, int capacity) { + super(capacity); myHashSet = new OpenTHashSet(capacity, hashingStrategy); - myElements = new ArrayList(capacity); - } - - @Override - public int size() { - return myElements.size(); } @Override @@ -50,7 +48,7 @@ public class OrderedSet extends AbstractList implements Set, RandomAcce @Override public boolean add(T o) { if (myHashSet.add(o)){ - myElements.add(o); + super.add(o); return true; } return false; @@ -59,7 +57,7 @@ public class OrderedSet extends AbstractList implements Set, RandomAcce @Override public boolean remove(Object o) { if (myHashSet.remove(o)){ - myElements.remove(o); + super.remove(o); return true; } return false; @@ -68,19 +66,7 @@ public class OrderedSet extends AbstractList implements Set, RandomAcce @Override public void clear() { myHashSet.clear(); - myElements.clear(); - } - - @NotNull - @Override - public Object[] toArray() { - return myElements.toArray(); - } - - @NotNull - @Override - public T[] toArray(@NotNull T[] a) { - return myElements.toArray(a); + super.clear(); } @Override @@ -88,11 +74,6 @@ public class OrderedSet extends AbstractList implements Set, RandomAcce throw new UnsupportedOperationException(); } - @Override - public T get(final int index) { - return myElements.get(index); - } - @Override public T set(final int index, final T element) { final T removed = remove(index); @@ -103,13 +84,13 @@ public class OrderedSet extends AbstractList implements Set, RandomAcce @Override public void add(final int index, final T element) { if (myHashSet.add(element)){ - myElements.add(index, element); + super.add(index, element); } } @Override public T remove(final int index) { - final T t = myElements.remove(index); + final T t = super.remove(index); myHashSet.remove(t); return t; } @@ -117,24 +98,12 @@ public class OrderedSet extends AbstractList implements Set, RandomAcce @Override public int indexOf(final Object o) { final int index = myHashSet.index((T)o); - return index >= 0? myElements.indexOf(myHashSet.get(index)) : -1; + return index >= 0? super.indexOf(myHashSet.get(index)) : -1; } @Override public int lastIndexOf(final Object o) { final int index = myHashSet.index((T)o); - return index >= 0 ? myElements.lastIndexOf(myHashSet.get(index)) : -1; - } - - @NotNull - @Override - public ListIterator listIterator() { - return myElements.listIterator(); - } - - @NotNull - @Override - public ListIterator listIterator(final int index) { - return myElements.listIterator(index); + return index >= 0 ? super.lastIndexOf(myHashSet.get(index)) : -1; } } diff --git a/platform/util/src/com/intellij/util/io/URLUtil.java b/platform/util/src/com/intellij/util/io/URLUtil.java index dc9cb14d1a87..ad577ca87ec3 100644 --- a/platform/util/src/com/intellij/util/io/URLUtil.java +++ b/platform/util/src/com/intellij/util/io/URLUtil.java @@ -96,6 +96,7 @@ public class URLUtil { @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") final ZipFile zipFile = new ZipFile(FileUtil.unquote(paths.first)); ZipEntry zipEntry = zipFile.getEntry(paths.second); if (zipEntry == null) { + zipFile.close(); throw new FileNotFoundException("Entry " + paths.second + " not found in " + paths.first); } diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 1b3ad87b4a6d..b939c924968d 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -356,9 +356,9 @@ public class UIUtil { public static void setEnabled(Component component, boolean enabled, boolean recursively) { component.setEnabled(enabled); - if (component instanceof JComboBox) { + if (component instanceof JComboBox && isUnderAquaLookAndFeel()) { // On Mac JComboBox instances have children: com.apple.laf.AquaComboBoxButton and javax.swing.CellRendererPane. - // Disabling these children results in ugly UI. See WEB-10733 + // Disabling these children results in ugly UI: WEB-10733 return; } if (component instanceof JLabel) { diff --git a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java index b7ba2b988e97..d70588834481 100644 --- a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java +++ b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java @@ -809,6 +809,8 @@ public class XmlSerializerTest extends TestCase { public int COUNT = 3; @Attribute("name") public String name = "James"; + @Attribute("occupation") + public String occupation; } public void testBeanWithPrimitivePropertyBoundToAttribute() { final BeanWithPropertiesBoundToAttribute bean = new BeanWithPropertiesBoundToAttribute(); @@ -851,7 +853,7 @@ public class XmlSerializerTest extends TestCase { bean.STRING_V = "skip"; - assertSerializer(bean, "", "Serialization failure", null); + assertSerializer(bean, "", null); } public static class BeanWithJDOMElement { @@ -1145,13 +1147,13 @@ public class XmlSerializerTest extends TestCase { } //--------------------------------------------------------------------------------------------------- - private static void assertSerializer(Object bean, String expected, SerializationFilter filter) { - assertSerializer(bean, expected, "Serialization failure", filter); + private static Element assertSerializer(Object bean, String expected, SerializationFilter filter) { + return assertSerializer(bean, expected, "Serialization failure", filter); } private static Object doSerializerTest(String expectedText, Object bean) { try { - Element element = assertSerializer(bean, expectedText, "Serialization failure", null); + Element element = assertSerializer(bean, expectedText, null); //test deserializer diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootDetectorImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootDetectorImpl.java index 338023582e0f..8b600cbfed73 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootDetectorImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootDetectorImpl.java @@ -37,6 +37,7 @@ public class VcsRootDetectorImpl implements VcsRootDetector { @NotNull private final Project myProject; @NotNull private final ProjectRootManager myProjectManager; @NotNull private final ProjectLevelVcsManager myVcsManager; + @NotNull private final VcsRootChecker[] myCheckers; public VcsRootDetectorImpl(@NotNull Project project, @NotNull ProjectRootManager projectRootManager, @@ -44,6 +45,7 @@ public class VcsRootDetectorImpl implements VcsRootDetector { myProject = project; myProjectManager = projectRootManager; myVcsManager = projectLevelVcsManager; + myCheckers = Extensions.getExtensions(VcsRootChecker.EXTENSION_POINT_NAME); } @NotNull @@ -53,7 +55,7 @@ public class VcsRootDetectorImpl implements VcsRootDetector { @NotNull public Collection detect(@Nullable VirtualFile startDir) { - if (startDir == null) { + if (startDir == null || myCheckers.length == 0) { return Collections.emptyList(); } @@ -140,9 +142,8 @@ public class VcsRootDetectorImpl implements VcsRootDetector { @NotNull private List getVcsListFor(@NotNull VirtualFile dir) { - VcsRootChecker[] checkers = Extensions.getExtensions(VcsRootChecker.EXTENSION_POINT_NAME); List vcsList = new ArrayList(); - for (VcsRootChecker checker : checkers) { + for (VcsRootChecker checker : myCheckers) { if (checker.isRoot(dir.getPath())) { vcsList.add(myVcsManager.findVcsByName(checker.getSupportedVcs().getName())); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java index 1b17a3a815b0..8accea1d4c36 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -322,7 +322,7 @@ public class XDebugSessionImpl implements XDebugSession { return myValueMarkers; } - private static > XBreakpointType getBreakpointTypeClass(final XBreakpointHandler handler) { + private static XBreakpointType getBreakpointTypeClass(final XBreakpointHandler handler) { return XDebuggerUtil.getInstance().findBreakpointType(handler.getBreakpointTypeClass()); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java index 4fbc23431a5e..76a360f748ab 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java @@ -262,9 +262,13 @@ public class XDebuggerUtilImpl extends XDebuggerUtil { @Override @Nullable public PsiElement findContextElement(@NotNull VirtualFile virtualFile, int offset, @NotNull Project project, boolean checkXml) { + if (!virtualFile.isValid()) { + return null; + } + Document document = FileDocumentManager.getInstance().getDocument(virtualFile); - PsiFile file = PsiManager.getInstance(project).findFile(virtualFile); - if (file == null || document == null) { + PsiFile file = document == null ? null : PsiManager.getInstance(project).findFile(virtualFile); + if (file == null) { return null; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java index 90469e5ffb95..694ef28f8b37 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java @@ -60,6 +60,7 @@ public class XDebuggerExpressionComboBox extends XDebuggerEditorBase { return myComboBox; } + @Override public JComponent getComponent() { return myComboBox; } @@ -70,7 +71,7 @@ public class XDebuggerExpressionComboBox extends XDebuggerEditorBase { } public JComponent getEditorComponent() { - return (JComponent)myEditor.getEditorComponent(); + return myEditor.getEditorComponent(); } public void setEnabled(boolean enable) { @@ -89,13 +90,12 @@ public class XDebuggerExpressionComboBox extends XDebuggerEditorBase { private void initEditor() { myEditor = new EditorComboBoxEditor(getProject(), myDebuggerEditorsProvider.getFileType()) { + @Override public void setItem(Object anObject) { - if (anObject == null) { - anObject = ""; - } - super.setItem(createDocument((String)anObject)); + super.setItem(createDocument(StringUtil.notNullize((String)anObject))); } + @Override public Object getItem() { return ((Document)super.getItem()).getText(); } @@ -106,6 +106,7 @@ public class XDebuggerExpressionComboBox extends XDebuggerEditorBase { myComboBox.setMaximumRowCount(XDebuggerHistoryManager.MAX_RECENT_EXPRESSIONS); } + @Override protected void onHistoryChanged() { fillComboBox(); } @@ -120,6 +121,7 @@ public class XDebuggerExpressionComboBox extends XDebuggerEditorBase { } } + @Override protected void doSetText(String text) { if (myComboBox.getItemCount() > 0) { myComboBox.setSelectedIndex(0); @@ -133,15 +135,18 @@ public class XDebuggerExpressionComboBox extends XDebuggerEditorBase { } } + @Override public String getText() { final Object value = myComboBox.isPopupVisible() ? myComboBox.getPopup().getList().getSelectedValue() : myEditor.getItem(); return StringUtil.notNullize((String)value); } + @Override public JComponent getPreferredFocusedComponent() { return (JComponent)myComboBox.getEditor().getEditorComponent(); } + @Override public void selectAll() { myComboBox.getEditor().selectAll(); } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml index ab8740992e8f..dddb6e1d3988 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml @@ -454,10 +454,6 @@ key="missing.deprecated.annotation.display.name" groupBundle="messages.InspectionsBundle" groupKey="group.names.class.structure" enabledByDefault="false" level="WARNING" runForWholeFile="true" implementationClass="com.siyeh.ig.classlayout.MissingDeprecatedAnnotationInspection"/> - + + #ref() uses the platform's default charset implicit.default.charset.usage.constructor.problem.descriptor=new #ref() call uses the platform's default charset +interface.may.be.annotated.functional.display.name=Interface may be annotated @FunctionalInterface +interface.may.be.annotated.functional.problem.descriptor=Interface #ref may be annotated with @FunctionalInterface diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java index 5e9e6e5449d9..237ec31f748c 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,6 @@ import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.PsiReplacementUtil; -import com.siyeh.ig.psiutils.ClassUtils; import org.jetbrains.annotations.NotNull; public class StaticCallOnSubclassInspection extends BaseInspection { @@ -141,10 +140,8 @@ public class StaticCallOnSubclassInspection extends BaseInspection { if (declaringClass.equals(referencedClass)) { return; } - final PsiClass containingClass = - ClassUtils.getContainingClass(call); - if (!ClassUtils.isClassVisibleFromClass(containingClass, - declaringClass)) { + final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(call.getProject()).getResolveHelper(); + if (!resolveHelper.isAccessible(declaringClass, call, null)) { return; } registerMethodCallError(call, declaringClass, referencedClass); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspection.java index 934dc29c58a3..696df9bd2fb0 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,6 @@ import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.PsiReplacementUtil; -import com.siyeh.ig.psiutils.ClassUtils; import org.jetbrains.annotations.NotNull; public class StaticFieldReferenceOnSubclassInspection @@ -124,13 +123,14 @@ public class StaticFieldReferenceOnSubclassInspection if (declaringClass.equals(referencedClass)) { return; } - final PsiClass containingClass = - ClassUtils.getContainingClass(expression); - if (!ClassUtils.isClassVisibleFromClass(containingClass, - declaringClass)) { + final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(expression.getProject()).getResolveHelper(); + if (!resolveHelper.isAccessible(declaringClass, expression, null)) { return; } final PsiElement identifier = expression.getReferenceNameElement(); + if (identifier == null) { + return; + } registerError(identifier, declaringClass, referencedClass); } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspection.java new file mode 100644 index 000000000000..58fd9e3553aa --- /dev/null +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspection.java @@ -0,0 +1,91 @@ +/* + * 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.siyeh.ig.classlayout; + +import com.intellij.codeInsight.intention.AddAnnotationPsiFix; +import com.intellij.psi.LambdaHighlightingUtil; +import com.intellij.psi.LambdaUtil; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiNameValuePair; +import com.intellij.psi.util.MethodSignature; +import com.intellij.psi.util.PsiUtil; +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.BaseInspection; +import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.DelegatingFix; +import com.siyeh.ig.InspectionGadgetsFix; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * @author Bas Leijdekkers + */ +public class InterfaceMayBeAnnotatedFunctionalInspection extends BaseInspection { + @Nls + @NotNull + @Override + public String getDisplayName() { + return InspectionGadgetsBundle.message("interface.may.be.annotated.functional.display.name"); + } + + @NotNull + @Override + protected String buildErrorString(Object... infos) { + return InspectionGadgetsBundle.message("interface.may.be.annotated.functional.problem.descriptor"); + } + + @Nullable + @Override + protected InspectionGadgetsFix buildFix(Object... infos) { + final PsiClass aClass = (PsiClass)infos[0]; + return new DelegatingFix(new AddAnnotationPsiFix(LambdaUtil.JAVA_LANG_FUNCTIONAL_INTERFACE, aClass, PsiNameValuePair.EMPTY_ARRAY)); + + } + + @Override + public BaseInspectionVisitor buildVisitor() { + return new InterfaceMayBeAnnotatedFunctionalVisitor(); + } + + private static class InterfaceMayBeAnnotatedFunctionalVisitor extends BaseInspectionVisitor { + + @Override + public void visitClass(PsiClass aClass) { + if (!PsiUtil.isLanguageLevel8OrHigher(aClass)) { + return; + } + super.visitClass(aClass); + if (!aClass.isInterface()) { + return; + } + if (LambdaHighlightingUtil.checkInterfaceFunctional(aClass) != null) { + return; + } + final List candidates = LambdaUtil.findFunctionCandidates(aClass); + if (candidates == null || candidates.size() != 1) { + return; + } + final MethodSignature signature = candidates.get(0); + if (signature.getTypeParameters().length > 0) { + return; + } + registerClassError(aClass, aClass); + } + } +} diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingOverrideAnnotationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/MissingOverrideAnnotationInspection.java similarity index 99% rename from plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingOverrideAnnotationInspection.java rename to plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/MissingOverrideAnnotationInspection.java index 3c18cc3be937..fff5d2c6a244 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingOverrideAnnotationInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/MissingOverrideAnnotationInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 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. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.siyeh.ig.classlayout; +package com.siyeh.ig.inheritance; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ClassUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ClassUtils.java index 9bbc5b6065a5..40daa3332896 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ClassUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ClassUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -206,21 +206,4 @@ public class ClassUtils { final PsiClass parentClass = (PsiClass)parent; return !parentClass.isInterface(); } - - public static boolean isClassVisibleFromClass(PsiClass baseClass, - PsiClass referencedClass) { - if (referencedClass.hasModifierProperty(PsiModifier.PUBLIC)) { - return true; - } - else if (referencedClass.hasModifierProperty(PsiModifier.PROTECTED)) { - return inSamePackage(baseClass, referencedClass); - } - else if (referencedClass.hasModifierProperty(PsiModifier.PRIVATE)) { - return PsiTreeUtil.findCommonParent(baseClass, referencedClass) != - null; - } - else { - return inSamePackage(baseClass, referencedClass); - } - } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/InterfaceMayBeAnnotatedFunctional.html b/plugins/InspectionGadgets/src/inspectionDescriptions/InterfaceMayBeAnnotatedFunctional.html new file mode 100644 index 000000000000..66ea1b4ac432 --- /dev/null +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/InterfaceMayBeAnnotatedFunctional.html @@ -0,0 +1,10 @@ + + +Reports any interface that may be annotated as @FunctionalInterface, which is available in JDK 1.8. +Annotating an interface with @FunctionalInterface can be useful to indicate that the interface is supposed to be functional and +further abstract methods should not be added to it. +This inspection only reports if the project or module is configured to use a language level of 8.0 or higher. +

+New in 13.1 + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/StaticCallOnSubclass.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/StaticCallOnSubclass.java deleted file mode 100644 index 55dfea251b93..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/StaticCallOnSubclass.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.siyeh.igtest.bugs; - -import com.siyeh.igtest.abstraction.StaticCallOnSubclassChild; - -public class StaticCallOnSubclass { - - public void foo() throws InterruptedException { - Thread.sleep(1000L); - InnerThread.sleep(1000L, 1000); - final int priority = InnerThread.MAX_PRIORITY; - StaticCallOnSubclassChild.foo(); - } - - class InnerThread extends Thread - { - } -} diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspectionTest.java new file mode 100644 index 000000000000..33c74e4b4262 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspectionTest.java @@ -0,0 +1,54 @@ +/* + * 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.siyeh.ig.bugs; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; + +/** + * @author Bas Leijdekkers + */ +public class StaticFieldReferenceOnSubclassInspectionTest extends LightInspectionTestCase { + @Override + protected InspectionProfileEntry getInspection() { + return new StaticFieldReferenceOnSubclassInspection(); + } + + @Override + protected String[] getEnvironmentClasses() { + return new String[] { + "package a;" + + "public class A {" + + " private static class AA {\n" + + " public static final int VALUE = 5;\n" + + " }" + + " public static class AB extends AA {\n" + + " }" + + " public static final String S = \"\";" + + "}", + "package a;" + + "public class B extends A {}" + }; + } + + public void testSimple() { + doStatementTest("System.out.println(a.B./*Static field 'S' declared in class 'a.A' but referenced via subclass 'a.B'*/S/**/);"); + } + + public void testNoWarn() { + doStatementTest("System.out.println(a.A.AB.VALUE);"); + } +} diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspectionTest.java new file mode 100644 index 000000000000..ab4e3e8f77f5 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspectionTest.java @@ -0,0 +1,51 @@ +/* + * 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.siyeh.ig.classlayout; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; + +/** + * @author Bas Leijdekkers + */ +public class InterfaceMayBeAnnotatedFunctionalInspectionTest extends LightInspectionTestCase { + + public void testSimple() { + doTest("interface /*Interface 'Simple' may be annotated with @FunctionalInterface*/Simple/**/ {" + + " void f();" + + "}"); + } + + public void testLessSimple() { + doTest("interface /*Interface 'F' may be annotated with @FunctionalInterface*/F/**/ {" + + " boolean equals(Object o);" + + " static void f00() {}\n" + + " default void g() {}\n" + + " void f();\n" + + "}"); + } + + public void testNotFunctional() { + doTest("interface G {" + + " void f();" + + "}"); + } + + @Override + protected InspectionProfileEntry getInspection() { + return new InterfaceMayBeAnnotatedFunctionalInspection(); + } +} diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java index 14c7535f8044..c597fc840521 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java @@ -178,7 +178,7 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo } private static boolean doInjectInJava(final Project project, - final PsiElement psiElement, + @NotNull final PsiElement psiElement, PsiLanguageInjectionHost host, final String languageId) { final PsiElement target = ContextComputationProcessor.getTopLevelInjectionTarget(psiElement); @@ -245,7 +245,7 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo return false; } new WriteCommandAction(modifierListOwner.getProject(), modifierListOwner.getContainingFile()) { - protected void run(final Result result) throws Throwable { + protected void run(@NotNull final Result result) throws Throwable { JVMElementFactory factory = JVMElementFactories.getFactory(modifierListOwner.getLanguage(), modifierListOwner.getProject()); if (factory == null) { factory = JavaPsiFacade.getElementFactory(modifierListOwner.getProject()); @@ -484,7 +484,7 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo } } } - else { +// else { // todo tbd //for (InjectionPlace place : injection.getInjectionPlaces()) { // final Matcher matcher = pattern.matcher(place.getText()); @@ -492,7 +492,7 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo // // } //} - } +// } result.setMethodInfos(infos); result.generatePlaces(); return result; diff --git a/plugins/devkit/src/inspections/DevKitInspectionBase.java b/plugins/devkit/src/inspections/DevKitInspectionBase.java index c2e77ba71712..9ded8e216fc0 100644 --- a/plugins/devkit/src/inspections/DevKitInspectionBase.java +++ b/plugins/devkit/src/inspections/DevKitInspectionBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 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. @@ -75,7 +75,7 @@ public abstract class DevKitInspectionBase extends BaseJavaLocalInspectionTool { @Nullable private static Set checkModule(Module module, PsiClass psiClass, @Nullable Set types, boolean includeActions) { final XmlFile pluginXml = PluginModuleType.getPluginXml(module); - if (!isPluginXml(pluginXml)) return types; + if (!DescriptorUtil.isPluginXml(pluginXml)) return types; assert pluginXml != null; final XmlDocument document = pluginXml.getDocument(); @@ -100,17 +100,6 @@ public abstract class DevKitInspectionBase extends BaseJavaLocalInspectionTool { return types; } - public static boolean isPluginXml(PsiFile file) { - if (!(file instanceof XmlFile)) return false; - final XmlFile pluginXml = (XmlFile)file; - - final XmlDocument document = pluginXml.getDocument(); - if (document == null) return false; - final XmlTag rootTag = document.getRootTag(); - return rootTag != null && "idea-plugin".equals(rootTag.getLocalName()); - - } - @Nullable protected static PsiElement getAttValueToken(@NotNull XmlAttribute attribute) { final XmlAttributeValue valueElement = attribute.getValueElement(); diff --git a/plugins/devkit/src/inspections/RegistrationProblemsInspection.java b/plugins/devkit/src/inspections/RegistrationProblemsInspection.java index 8473dc0ad65f..d73c7b21598d 100644 --- a/plugins/devkit/src/inspections/RegistrationProblemsInspection.java +++ b/plugins/devkit/src/inspections/RegistrationProblemsInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 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. @@ -116,7 +116,7 @@ public class RegistrationProblemsInspection extends DevKitInspectionBase { @Nullable public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) { - if (CHECK_PLUGIN_XML && isPluginXml(file)) { + if (CHECK_PLUGIN_XML && DescriptorUtil.isPluginXml(file)) { return checkPluginXml((XmlFile)file, manager, isOnTheFly); } return null; diff --git a/plugins/devkit/src/references/extensions/ExtensionPointQuickDocProvider.java b/plugins/devkit/src/references/extensions/ExtensionPointQuickDocProvider.java index 9e5ce037d6f4..02d6107d1d97 100644 --- a/plugins/devkit/src/references/extensions/ExtensionPointQuickDocProvider.java +++ b/plugins/devkit/src/references/extensions/ExtensionPointQuickDocProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 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. @@ -29,7 +29,7 @@ import com.intellij.psi.xml.XmlTag; import com.intellij.psi.xml.XmlToken; import com.intellij.psi.xml.XmlTokenType; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.devkit.inspections.DevKitInspectionBase; +import org.jetbrains.idea.devkit.util.DescriptorUtil; import java.util.List; @@ -50,7 +50,7 @@ public class ExtensionPointQuickDocProvider implements DocumentationProvider { @Override public String generateDoc(PsiElement element, @Nullable PsiElement originalElement) { if (originalElement == null) return null; - if (originalElement.getLanguage() == XMLLanguage.INSTANCE || DevKitInspectionBase.isPluginXml(originalElement.getContainingFile())) { + if (originalElement.getLanguage() == XMLLanguage.INSTANCE || DescriptorUtil.isPluginXml(originalElement.getContainingFile())) { final PsiElement context = element.getContext(); String fqn = null; if (originalElement instanceof XmlToken && ((XmlToken)originalElement).getTokenType() == XmlTokenType.XML_NAME) { diff --git a/plugins/devkit/src/util/DescriptorUtil.java b/plugins/devkit/src/util/DescriptorUtil.java index 4fca8951084c..3a773e9e5fa9 100644 --- a/plugins/devkit/src/util/DescriptorUtil.java +++ b/plugins/devkit/src/util/DescriptorUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -15,16 +15,20 @@ */ package org.jetbrains.idea.devkit.util; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.vfs.ReadonlyStatusHandler; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiFile; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; -import com.intellij.psi.PsiClass; import com.intellij.util.IncorrectOperationException; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.ReadonlyStatusHandler; -import com.intellij.openapi.module.Module; -import org.jetbrains.idea.devkit.DevKitBundle; -import org.jetbrains.idea.devkit.module.PluginModuleType; +import com.intellij.util.xml.DomFileElement; +import com.intellij.util.xml.DomManager; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.devkit.DevKitBundle; +import org.jetbrains.idea.devkit.dom.IdeaPlugin; +import org.jetbrains.idea.devkit.module.PluginModuleType; /** * @author swr @@ -72,16 +76,18 @@ public class DescriptorUtil { assert PluginModuleType.isOfType(plugin); final XmlFile pluginXml = PluginModuleType.getPluginXml(plugin); - if (pluginXml != null) { - final XmlTag rootTag = pluginXml.getDocument().getRootTag(); - if (rootTag != null) { - final XmlTag idTag = rootTag.findFirstSubTag("id"); - if (idTag != null) return idTag.getValue().getTrimmedText(); - - final XmlTag nameTag = rootTag.findFirstSubTag("name"); - if (nameTag != null) return nameTag.getValue().getTrimmedText(); - } + if (pluginXml == null) { + return null; } - return null; + return getIdeaPlugin(pluginXml).getRootElement().getPluginId(); + } + + public static boolean isPluginXml(PsiFile file) { + if (!(file instanceof XmlFile)) return false; + return getIdeaPlugin((XmlFile)file) != null; + } + + private static DomFileElement getIdeaPlugin(XmlFile file) { + return DomManager.getDomManager(file.getProject()).getFileElement(file, IdeaPlugin.class); } } diff --git a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java index cc8cce768f9a..d5c4b3fa8505 100644 --- a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java +++ b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java @@ -110,22 +110,16 @@ public class GitCheckinEnvironment implements CheckinEnvironment { for (VirtualFile root : GitUtil.gitRoots(Arrays.asList(filesToCheckin))) { VirtualFile mergeMsg = root.findFileByRelativePath(GitRepositoryFiles.GIT_MERGE_MSG); VirtualFile squashMsg = root.findFileByRelativePath(GitRepositoryFiles.GIT_SQUASH_MSG); - VirtualFile normalMsg = root.findFileByRelativePath(GitRepositoryFiles.GIT_COMMIT_EDITMSG); try { - if (mergeMsg == null && squashMsg == null && normalMsg == null) { + if (mergeMsg == null && squashMsg == null) { continue; } - String encoding = GitConfigUtil.getCommitEncoding(myProject, root); - if (mergeMsg != null) { messages.add(loadMessage(mergeMsg, encoding)); } - else if (squashMsg != null) { - messages.add(loadMessage(squashMsg, encoding)); - } else { - messages.add(loadMessage(normalMsg, encoding)); + messages.add(loadMessage(squashMsg, encoding)); } } catch (IOException e) { diff --git a/plugins/gradle/gradle.iml b/plugins/gradle/gradle.iml index 6f6de2602ed6..9c852ed6ffc1 100644 --- a/plugins/gradle/gradle.iml +++ b/plugins/gradle/gradle.iml @@ -35,6 +35,7 @@ + diff --git a/plugins/gradle/lib/gradle-reporting-1.9.jar b/plugins/gradle/lib/gradle-reporting-1.9.jar new file mode 100644 index 000000000000..531552536833 Binary files /dev/null and b/plugins/gradle/lib/gradle-reporting-1.9.jar differ diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java index 03f0e66451dc..58120f90a4d4 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.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. @@ -187,8 +187,9 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver aClass = resolverCtx.isPreviewMode() ? BasicIdeaProject.class : IdeaProject.class; ModelBuilder modelBuilder = myHelper.getModelBuilder( - resolverCtx.isPreviewMode() ? BasicIdeaProject.class : IdeaProject.class, + aClass, resolverCtx.getExternalSystemTaskId(), resolverCtx.getSettings(), resolverCtx.getConnection(), diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectImportAction.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectImportAction.java index 52c6e3d47b74..407f12c6981a 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectImportAction.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectImportAction.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. @@ -48,7 +48,8 @@ public class ProjectImportAction implements BuildAction aClass1 = myIsPreviewMode ? BasicIdeaProject.class : IdeaProject.class; + final IdeaProject ideaProject = controller.getModel(aClass1); if (ideaProject == null || ideaProject.getModules().isEmpty()) { return null; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java index 815900804ec0..5c052f4beade 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.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. @@ -58,40 +58,18 @@ public class AlignmentProvider { } if (myAlignments.containsKey(set2)) { - for (Iterator iterator = set1.iterator(); iterator.hasNext(); ) { - PsiElement element = iterator.next(); - iterator.remove(); - - addInternal(set2, element); - } + addSet(set1, set2); } else { set1.addAll(set2); - for (Iterator iterator = set2.iterator(); iterator.hasNext(); ) { - PsiElement element = iterator.next(); - iterator.remove(); - - addInternal(set1, element); - } + addSet(set2, set1); } } else if (set1 != null) { - if (allowBackwardShift != null) { - assert myAllowBackwardShift.get(set1).booleanValue() == allowBackwardShift.booleanValue(); - } - if (anchor != null) { - assert myAnchor.get(set1) == anchor; - } - addInternal(set1, e2); + addElement(e2, allowBackwardShift, anchor, set1); } else if (set2 != null) { - if (allowBackwardShift != null) { - assert(myAllowBackwardShift.get(set2).booleanValue() == allowBackwardShift.booleanValue()); - } - if (anchor != null) { - assert(myAnchor.get(set2) == anchor); - } - addInternal(set2, e1); + addElement(e1, allowBackwardShift, anchor, set2); } else { final HashSet set = createHashSet(); @@ -102,6 +80,25 @@ public class AlignmentProvider { } } + private void addElement(PsiElement e, Boolean allowBackwardShift, Alignment.Anchor anchor, Set set) { + if (allowBackwardShift != null) { + assert myAllowBackwardShift.get(set).booleanValue() == allowBackwardShift.booleanValue(); + } + if (anchor != null) { + assert myAnchor.get(set) == anchor; + } + addInternal(set, e); + } + + private void addSet(Set set1, Set set2) { + for (Iterator iterator = set1.iterator(); iterator.hasNext(); ) { + PsiElement element = iterator.next(); + iterator.remove(); + + addInternal(set2, element); + } + } + private void addInternal(@NotNull Set set, @NotNull PsiElement element) { myTree.put(element, set); set.add(element); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/blocks/GroovyBlockGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/blocks/GroovyBlockGenerator.java index c2ac05abe6f7..721e482c5c5f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/blocks/GroovyBlockGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/blocks/GroovyBlockGenerator.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. @@ -301,12 +301,20 @@ public class GroovyBlockGenerator implements GroovyElementTypes { if (myContext.getSettings().ALIGN_MULTILINE_TERNARY_OPERATION) { final GrConditionalExpression conditional = (GrConditionalExpression)blockPsi; - final AlignmentProvider.Aligner aligner = myAlignmentProvider.createAligner(false); - aligner.append(conditional.getCondition()); + final AlignmentProvider.Aligner exprAligner = myAlignmentProvider.createAligner(false); + exprAligner.append(conditional.getCondition()); if (!(conditional instanceof GrElvisExpression)) { - aligner.append(conditional.getThenBranch()); + exprAligner.append(conditional.getThenBranch()); + } + exprAligner.append(conditional.getElseBranch()); + + ASTNode question = conditional.getNode().findChildByType(GroovyTokenTypes.mQUESTION); + ASTNode colon = conditional.getNode().findChildByType(GroovyTokenTypes.mCOLON); + if (question != null && colon != null) { + AlignmentProvider.Aligner questionColonAligner = myAlignmentProvider.createAligner(false); + questionColonAligner.append(question.getPsi()); + questionColonAligner.append(colon.getPsi()); } - aligner.append(conditional.getElseBranch()); } } @@ -508,7 +516,6 @@ public class GroovyBlockGenerator implements GroovyElementTypes { return blockPsi instanceof GrParameterList && myContext.getSettings().ALIGN_MULTILINE_PARAMETERS || blockPsi instanceof GrExtendsClause && myContext.getSettings().ALIGN_MULTILINE_EXTENDS_LIST || blockPsi instanceof GrThrowsClause && myContext.getSettings().ALIGN_MULTILINE_THROWS_LIST || - blockPsi instanceof GrConditionalExpression && myContext.getSettings().ALIGN_MULTILINE_TERNARY_OPERATION || blockPsi instanceof GrListOrMap && myContext.getGroovySettings().ALIGN_MULTILINE_LIST_OR_MAP; } @@ -516,7 +523,6 @@ public class GroovyBlockGenerator implements GroovyElementTypes { return blockPsi instanceof GrParameterList || blockPsi instanceof GrArgumentList || blockPsi instanceof GrAssignmentExpression || - blockPsi instanceof GrConditionalExpression || blockPsi instanceof GrExtendsClause || blockPsi instanceof GrThrowsClause || blockPsi instanceof GrListOrMap; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java index 84a6807b1594..e64154c3a14b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java @@ -370,27 +370,27 @@ public class GroovySpacingProcessor extends GroovyElementVisitor { @Override public void visitFile(GroovyFileBase file) { if (isAfterElementOrSemi(PACKAGE_DEFINITION)) { - myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_PACKAGE + 1, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2); + myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_PACKAGE + 1, mySettings.KEEP_LINE_BREAKS, keepBlankLines()); } else if (myType2 == PACKAGE_DEFINITION) { - myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_BEFORE_PACKAGE + 1, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2); + myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_BEFORE_PACKAGE + 1, mySettings.KEEP_LINE_BREAKS, keepBlankLines()); } else if (isLeftOrRight(TYPE_DEFINITION_TYPES)) { if (myType1 == GROOVY_DOC_COMMENT) { createLF(true); } else { - myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AROUND_CLASS + 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS); + myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AROUND_CLASS + 1, mySettings.KEEP_LINE_BREAKS, keepBlankLines()); } } else if (isAfterElementOrSemi(IMPORT_STATEMENT) && myType2 != IMPORT_STATEMENT) { //after imports - myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_IMPORTS + 1, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2); + myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_IMPORTS + 1, mySettings.KEEP_LINE_BREAKS, keepBlankLines()); } else if (myType1 != IMPORT_STATEMENT && !isSemiAfter(IMPORT_STATEMENT) && myType2 == IMPORT_STATEMENT) { //before imports - myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_BEFORE_IMPORTS, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2); + myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_BEFORE_IMPORTS, mySettings.KEEP_LINE_BREAKS, keepBlankLines()); } else if (isAfterElementOrSemi(IMPORT_STATEMENT) && myType2 == IMPORT_STATEMENT) { - myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2); + myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, keepBlankLines()); } else { processClassMembers(null); @@ -582,7 +582,7 @@ public class GroovySpacingProcessor extends GroovyElementVisitor { @Override public void visitTypeArgumentList(GrTypeArgumentList typeArgumentList) { if (myType1 == mLT || myType2 == mGT) { - createSpaceProperty(false, true, 1); + createSpaceInCode(false); } } @@ -858,7 +858,7 @@ public class GroovySpacingProcessor extends GroovyElementVisitor { } private void createLazySpace() { - myResult = Spacing.createSpacing(0, Integer.MAX_VALUE, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); + myResult = Spacing.createSpacing(0, Integer.MAX_VALUE, 0, mySettings.KEEP_LINE_BREAKS, keepBlankLines()); } public void visitDocTag(GrDocTag docTag) { @@ -1021,11 +1021,7 @@ public class GroovySpacingProcessor extends GroovyElementVisitor { } private void createSpaceInCode(final boolean space) { - createSpaceProperty(space, keepBlankLines()); - } - - private void createSpaceProperty(boolean space, int keepBlankLines) { - createSpaceProperty(space, mySettings.KEEP_LINE_BREAKS, keepBlankLines); + createSpaceProperty(space, mySettings.KEEP_LINE_BREAKS, keepBlankLines()); } private void createSpaceProperty(boolean space, boolean keepLineBreaks, final int keepBlankLines) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java index 2e1b0f81be05..a5383af62f6c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.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. @@ -270,7 +270,7 @@ public class GroovyIntroduceParameterMethodUsagesProcessor implements IntroduceP @NotNull Project project) { GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project); - final String typeText = forcedType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) ? null : forcedType.getCanonicalText(); + final String typeText = forcedType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) || forcedType == PsiType.NULL ? null : forcedType.getCanonicalText(); GrParameter parameter = factory.createParameter(parameterName, typeText, parametersOwner); parameter.getModifierList().setModifierProperty(PsiModifier.FINAL, isFinal); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.groovy index 72bb95deddbf..01cb0f735a43 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.groovy @@ -713,6 +713,15 @@ print abc ?: ''' } + void testConditional2() { + groovySettings.ALIGN_MULTILINE_TERNARY_OPERATION = true + checkFormatting('''\ +print abc ? cde +:xyz''', '''\ +print abc ? cde + : xyz''') + } + void testLabelsInBasicMode() { groovySettings.indentOptions.INDENT_SIZE = 4 groovySettings.indentOptions.LABEL_INDENT_SIZE = -2 @@ -770,6 +779,8 @@ def foo() { void testSpreadArg() { doTest() } + void testExtraLines() { doTest() } + void testLabelWithDescription() { GroovyCodeStyleSettings customSettings = myTempSettings.getCustomSettings(GroovyCodeStyleSettings.class) CommonCodeStyleSettings commonSettings = myTempSettings.getCommonSettings(GroovyFileType.GROOVY_LANGUAGE) diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.groovy index 8cc14aa1e0ee..3956cf8da7be 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.groovy @@ -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. @@ -356,6 +356,25 @@ class X { print new X(2) { } +''') + } + + + void testNullType() { + doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, null, false, '''\ +def foo() { + def a = '4' + print a +} + +foo() +''', '''\ +def foo(anObject) { + def a = '4' + anObject +} + +foo(print(a)) ''') } } diff --git a/plugins/groovy/testdata/groovy/formatter/extraLines.test b/plugins/groovy/testdata/groovy/formatter/extraLines.test new file mode 100644 index 000000000000..1fa2e574326d --- /dev/null +++ b/plugins/groovy/testdata/groovy/formatter/extraLines.test @@ -0,0 +1,14 @@ +package abc + + + + + + + +print 1 +----- +package abc + + +print 1 \ No newline at end of file diff --git a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties index 52b1203e06dd..1bd5aa4e0c6f 100644 --- a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties +++ b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties @@ -52,8 +52,8 @@ hg4idea.configuration.executable.error=\"{0}\" doesn''t appear to be a valid hg hg4idea.configuration.test.label=Test hg4idea.configuration.test=&Test hg4idea.unable.to.run.hg=Unable to run hg: {0} -hg4idea.run.success.title=Hg executed successfully -hg4idea.run.failed.title=Hg execution failed +hg4idea.run.success.title=Hg Executed Successfully +hg4idea.run.failed.title=Hg Execution Failed hg4idea.command.executable.error=Error executing \"{0}\". Make sure you have setup the right executable in Mercurial configuration diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java index e808b73ee25e..61cf991c20a5 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java @@ -32,7 +32,7 @@ public class HgBranchesAction extends HgAbstractGlobalAction { @Override protected void execute(@NotNull Project project, @NotNull Collection repositories, @Nullable VirtualFile selectedRepo) { - HgRepository repository; + HgRepository repository = null; if (selectedRepo != null) { repository = HgUtil.getRepositoryManager(project).getRepositoryForRoot(selectedRepo); } @@ -41,9 +41,6 @@ public class HgBranchesAction extends HgAbstractGlobalAction { if (selectedRoot != null) { repository = HgUtil.getRepositoryManager(project).getRepositoryForRoot(selectedRoot); } - else { - return; - } } if (repository != null) { HgBranchPopup.getInstance(project, repository).asListPopup().showInFocusCenter(); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java index cacf3257335a..921d4cf9fbc5 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java @@ -353,7 +353,7 @@ public abstract class HgUtil { //get file name in target revision if it was moved/renamed HgStatusCommand statCommand = new HgStatusCommand.Builder(false).copySource(true).baseRevision(vcsRevisionNumber).build(project); - Set changes = statCommand.execute(localHgFile.getRepo(), Arrays.asList(localHgFile.toFilePath())); + Set changes = statCommand.execute(localHgFile.getRepo(), Collections.singletonList(localHgFile.toFilePath())); for (HgChange change : changes) { if (change.afterFile().equals(localHgFile)) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java index e8cceeda7225..2f8e822190bc 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java @@ -70,10 +70,7 @@ public final class HgVersion implements Comparable { @NotNull private final Set myUnsupportedExtensions; public HgVersion(int major, int middle, int minor) { - myMajor = major; - myMiddle = middle; - myMinor = minor; - myUnsupportedExtensions = Collections.emptySet(); + this(major, middle, minor, Collections.emptySet()); } public HgVersion(int major, int middle, int minor, @NotNull Set unsupportedExtensions) { diff --git a/plugins/javaFX/FxBuilderEmbedder/lib/embedder.jar b/plugins/javaFX/FxBuilderEmbedder/lib/embedder.jar index 1ddf9204cf68..9400a2955c5b 100644 Binary files a/plugins/javaFX/FxBuilderEmbedder/lib/embedder.jar and b/plugins/javaFX/FxBuilderEmbedder/lib/embedder.jar differ diff --git a/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderImpl.java b/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderImpl.java index 025da2f708f0..fba7e4de778a 100644 --- a/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderImpl.java +++ b/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderImpl.java @@ -27,6 +27,7 @@ public class SceneBuilderImpl implements SceneBuilder { private final JFXPanel myPanel = new JFXPanel(); private EditorController myEditorController; private ChangeListener myListener; + private volatile boolean mySkipChanges; public SceneBuilderImpl(URL url, EditorCallback editorCallback) { myFileURL = url; @@ -88,7 +89,9 @@ public class SceneBuilderImpl implements SceneBuilder { myListener = new ChangeListener() { @Override public void changed(ObservableValue observable, Number oldValue, Number newValue) { - myEditorCallback.saveChanges(myEditorController.getFxmlText()); + if (!mySkipChanges) { + myEditorCallback.saveChanges(myEditorController.getFxmlText()); + } } }; @@ -103,6 +106,8 @@ public class SceneBuilderImpl implements SceneBuilder { } private void loadFile() { + mySkipChanges = true; + try { String fxmlText = FXOMDocument.readContentFromURL(myFileURL); myEditorController.setFxmlTextAndLocation(fxmlText, myFileURL); @@ -110,5 +115,8 @@ public class SceneBuilderImpl implements SceneBuilder { catch (Throwable e) { myEditorCallback.handleError(e); } + finally { + mySkipChanges = false; + } } } \ No newline at end of file diff --git a/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml b/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml index d6ef063029af..ffb957bff742 100644 --- a/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml +++ b/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml @@ -57,6 +57,7 @@ + diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/OpenInSceneBuilderAction.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/OpenInSceneBuilderAction.java index f41b9be4c614..6a56d6b60cdc 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/OpenInSceneBuilderAction.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/OpenInSceneBuilderAction.java @@ -17,35 +17,18 @@ package org.jetbrains.plugins.javaFX.actions; import com.intellij.CommonBundle; import com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.execution.configurations.JavaParameters; -import com.intellij.execution.configurations.PathEnvironmentVariableUtil; -import com.intellij.execution.process.OSProcessHandler; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.fileChooser.FileChooser; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.registry.Registry; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.ArrayUtil; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.javaFX.JavaFxSettings; -import org.jetbrains.plugins.javaFX.JavaFxSettingsConfigurable; import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; +import org.jetbrains.plugins.javaFX.sceneBuilder.SceneBuilderInfo; /** * User: anna @@ -53,84 +36,21 @@ import java.util.List; */ public class OpenInSceneBuilderAction extends AnAction { private static final Logger LOG = Logger.getInstance("#" + OpenInSceneBuilderAction.class.getName()); - public static final String ORACLE = "Oracle"; @Override public void actionPerformed(AnActionEvent e) { final VirtualFile virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE); LOG.assertTrue(virtualFile != null); final String path = virtualFile.getPath(); - - final JavaFxSettings settings = JavaFxSettings.getInstance(); - String pathToSceneBuilder = settings.getPathToSceneBuilder(); - if (StringUtil.isEmptyOrSpaces(settings.getPathToSceneBuilder())){ - final VirtualFile sceneBuilderFile = FileChooser.chooseFile(JavaFxSettingsConfigurable.createSceneBuilderDescriptor(), e.getProject(), getPredefinedPath()); - if (sceneBuilderFile == null) return; - - pathToSceneBuilder = sceneBuilderFile.getPath(); - settings.setPathToSceneBuilder(FileUtil.toSystemIndependentName(pathToSceneBuilder)); - } - final Project project = getEventProject(e); - if (project != null && !Registry.is("scene.builder.start.executable", true)) { - final Module module = ModuleUtilCore.findModuleForFile(virtualFile, project); - if (module != null) { - try { - final JavaParameters javaParameters = new JavaParameters(); - javaParameters.configureByModule(module, JavaParameters.JDK_AND_CLASSES); - final File sceneBuilderLibsFile; - if (SystemInfo.isMac) { - sceneBuilderLibsFile = new File(new File(pathToSceneBuilder, "Contents"), "Java"); - } else if (SystemInfo.isWindows) { - File sceneBuilderRoot = new File(pathToSceneBuilder); - File sceneBuilderRootDir = sceneBuilderRoot.getParentFile(); - if (sceneBuilderRootDir == null) { - final File foundInPath = PathEnvironmentVariableUtil.findInPath(pathToSceneBuilder); - if (foundInPath != null) { - sceneBuilderRootDir = foundInPath.getParentFile(); - } - } - sceneBuilderRoot = sceneBuilderRootDir != null ? sceneBuilderRootDir.getParentFile() : null; - if (sceneBuilderRoot != null) { - final File libFile = new File(sceneBuilderRoot, "lib"); - if (libFile.isDirectory()) { - sceneBuilderLibsFile = libFile; - } - else { - final File appFile = new File(sceneBuilderRootDir, "app"); - sceneBuilderLibsFile = appFile.isDirectory() ? appFile : null; - } - } - else { - sceneBuilderLibsFile = null; - } - } else { - sceneBuilderLibsFile = new File(new File(pathToSceneBuilder).getParent(), "app"); - } - if (sceneBuilderLibsFile != null) { - final File[] sceneBuilderLibs = sceneBuilderLibsFile.listFiles(); - if (sceneBuilderLibs != null) { - for (File jarFile : sceneBuilderLibs) { - javaParameters.getClassPath().add(jarFile.getPath()); - } - javaParameters.setMainClass("com.oracle.javafx.authoring.Main"); - javaParameters.getProgramParametersList().add(path); - - final OSProcessHandler processHandler = javaParameters.createOSProcessHandler(); - final String commandLine = processHandler.getCommandLine(); - LOG.info("scene builder command line: " + commandLine); - processHandler.startNotify(); - return; - } - } - } - catch (Throwable ex) { - LOG.info(ex); - } - } + final SceneBuilderInfo info = SceneBuilderInfo.get(project, true); + if (info == SceneBuilderInfo.EMPTY) { + return; } + String pathToSceneBuilder = info.path; + if (SystemInfo.isMac) { pathToSceneBuilder += "/Contents/MacOS/scenebuilder-launcher.sh"; } @@ -152,45 +72,11 @@ public class OpenInSceneBuilderAction extends AnAction { presentation.setEnabled(false); presentation.setVisible(false); final VirtualFile virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE); - if (virtualFile != null && + if (virtualFile != null && JavaFxFileTypeFactory.isFxml(virtualFile) && e.getProject() != null) { presentation.setEnabled(true); presentation.setVisible(true); } } - - @Nullable - private static VirtualFile getPredefinedPath() { - String path = null; - if (SystemInfo.isWindows) { - final String sb11 = File.separator + "JavaFX Scene Builder 1.1" + File.separator + "JavaFX Scene Builder 1.1.exe"; - final String sb10 = File.separator + "JavaFX Scene Builder 1.0" + File.separator + "bin" + File.separator + "scenebuilder.exe"; - final List suspiciousPaths = new ArrayList(); - final String programFiles = "C:\\Program Files"; - fillPaths(programFiles, sb11, sb10, suspiciousPaths); - fillPaths(programFiles + " (x86)", sb11, sb10, suspiciousPaths); - final File sb = FileUtil.findFirstThatExist(ArrayUtil.toStringArray(suspiciousPaths)); - if (sb != null) { - path = sb.getPath(); - } - } - else if (SystemInfo.isMac) { - final File sb = FileUtil.findFirstThatExist("/Applications/JavaFX Scene Builder 1.1.app", - "/Applications/JavaFX Scene Builder 1.0.app"); - if (sb != null) { - path = sb.getPath(); - } - } - else if (SystemInfo.isUnix) { - path = "/opt/JavaFXSceneBuilder1.1/JavaFXSceneBuilder1.1"; - } - - return path != null ? LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(path)) : null; - } - - private static void fillPaths(String programFilesPath, String sb11, String sb10, List suspiciousPaths) { - suspiciousPaths.add(new File(programFilesPath, ORACLE).getPath() + sb11); - suspiciousPaths.add(new File(programFilesPath, ORACLE).getPath() + sb10); - } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryType.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryType.java index 3d10a1c811ee..b4e2a0e9262b 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryType.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryType.java @@ -61,8 +61,7 @@ public class GenericRepositoryType extends BaseRepositoryType this, new AsanaRepository(), new AssemblaRepository(), - new SprintlyRepository(), - new GitlabRepository() + new SprintlyRepository() ); } @@ -127,10 +126,4 @@ public class GenericRepositoryType extends BaseRepositoryType super("Sprintly", TasksIcons.Sprintly); } } - - public final class GitlabRepository extends GenericSubtype { - public GitlabRepository() { - super("Gitlab", TasksIcons.Gitlab); - } - } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/gitlab.xml b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/gitlab.xml deleted file mode 100644 index b3ffd3c21111..000000000000 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/gitlab.xml +++ /dev/null @@ -1,75 +0,0 @@ - - {id} {summary} - diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/GitlabIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/GitlabIntegrationTest.java deleted file mode 100644 index 7c4e2d934206..000000000000 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/GitlabIntegrationTest.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.intellij.tasks.integration; - -import com.intellij.tasks.Task; -import com.intellij.tasks.TaskTestUtil; -import com.intellij.tasks.generic.GenericRepository; -import com.intellij.tasks.generic.GenericRepositoryType; -import org.jetbrains.annotations.NotNull; - -/** - * @author Mikhail Golubev - */ -public class GitlabIntegrationTest extends GenericSubtypeTestCase { - private static final String TASK_LIST_RESPONSE = "[\n" + - " {\n" + - " \"id\": 2,\n" + - " \"iid\": 2,\n" + - " \"project_id\": 1,\n" + - " \"title\": \"Drink more tea\",\n" + - " \"description\": \"It\\u0027s healthy.\",\n" + - " \"labels\": [],\n" + - " \"assignee\": {\n" + - " \"id\": 4,\n" + - " \"username\": \"deva\",\n" + - " \"email\": \"deva@somemail.com\",\n" + - " \"name\": \"John Smith\",\n" + - " \"state\": \"active\",\n" + - " \"created_at\": \"2013-11-14T12:34:37Z\"\n" + - " },\n" + - " \"author\": {\n" + - " \"id\": 1,\n" + - " \"username\": \"root\",\n" + - " \"email\": \"admin@local.host\",\n" + - " \"name\": \"Administrator\",\n" + - " \"state\": \"active\",\n" + - " \"created_at\": \"2013-11-14T12:19:43Z\"\n" + - " },\n" + - " \"state\": \"opened\",\n" + - " \"updated_at\": \"2013-11-14T12:38:51Z\",\n" + - " \"created_at\": \"2013-11-14T12:33:07Z\"\n" + - " },\n" + - " {\n" + - " \"id\": 1,\n" + - " \"iid\": 1,\n" + - " \"project_id\": 1,\n" + - " \"title\": \"Eat more bananas\",\n" + - " \"description\": \"They're tasty.\",\n" + - " \"labels\": [\n" + - " \"spam\"\n" + - " ],\n" + - " \"assignee\": {\n" + - " \"id\": 1,\n" + - " \"username\": \"root\",\n" + - " \"email\": \"admin@local.host\",\n" + - " \"name\": \"Administrator\",\n" + - " \"state\": \"active\",\n" + - " \"created_at\": \"2013-11-14T12:19:43Z\"\n" + - " },\n" + - " \"author\": {\n" + - " \"id\": 1,\n" + - " \"username\": \"root\",\n" + - " \"email\": \"admin@local.host\",\n" + - " \"name\": \"Administrator\",\n" + - " \"state\": \"active\",\n" + - " \"created_at\": \"2013-11-14T12:19:43Z\"\n" + - " },\n" + - " \"state\": \"opened\",\n" + - " \"updated_at\": \"2013-11-14T12:30:39Z\",\n" + - " \"created_at\": \"2013-11-14T12:30:39Z\"\n" + - " }\n" + - "] "; - - private static final String SINGLE_TASK_RESPONSE = "{\n" + - " \"id\": 2,\n" + - " \"iid\": 2,\n" + - " \"project_id\": 1,\n" + - " \"title\": \"Drink more tea\",\n" + - " \"description\": \"It\\u0027s healthy.\",\n" + - " \"labels\": [],\n" + - " \"assignee\": {\n" + - " \"id\": 4,\n" + - " \"username\": \"deva\",\n" + - " \"email\": \"deva@somemail.com\",\n" + - " \"name\": \"John Smith\",\n" + - " \"state\": \"active\",\n" + - " \"created_at\": \"2013-11-14T12:34:37Z\"\n" + - " },\n" + - " \"author\": {\n" + - " \"id\": 1,\n" + - " \"username\": \"root\",\n" + - " \"email\": \"admin@local.host\",\n" + - " \"name\": \"Administrator\",\n" + - " \"state\": \"active\",\n" + - " \"created_at\": \"2013-11-14T12:19:43Z\"\n" + - " },\n" + - " \"state\": \"opened\",\n" + - " \"updated_at\": \"2013-11-14T12:38:51Z\",\n" + - " \"created_at\": \"2013-11-14T12:33:07Z\"\n" + - "}"; - - private Task getTask1() { - return new TaskTestUtil.TaskBuilder("1", "Eat more bananas", myRepository) - .withDescription("They're tasty.") - .withUpdated("2013-11-14T12:30:39Z") - .withCreated("2013-11-14T12:30:39Z"); - } - - private Task getTask2() { - return new TaskTestUtil.TaskBuilder("2", "Drink more tea", myRepository) - .withDescription("It's healthy.") - .withUpdated("2013-11-14T12:38:51Z") - .withCreated("2013-11-14T12:33:07Z"); - } - - @NotNull - @Override - protected GenericRepository createRepository(GenericRepositoryType genericType) { - return (GenericRepository)genericType.new GitlabRepository().createRepository(); - } - - public void testParsingTaskList() throws Exception { - Task[] tasks = myRepository.getActiveResponseHandler().parseIssues(TASK_LIST_RESPONSE, 50); - TaskTestUtil.assertTasksEqual(new Task[]{getTask2(), getTask1()}, tasks); - } - - public void testParsingSingleTask() throws Exception { - Task task = myRepository.getActiveResponseHandler().parseIssue(SINGLE_TASK_RESPONSE); - TaskTestUtil.assertTasksEqual(getTask2(), task); - } -} diff --git a/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/XsltDebuggerRunner.java b/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/XsltDebuggerRunner.java index 7e72316d7f7a..f573f9442e64 100644 --- a/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/XsltDebuggerRunner.java +++ b/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/XsltDebuggerRunner.java @@ -2,7 +2,6 @@ package org.intellij.plugins.xsltDebugger; import com.intellij.execution.ExecutionException; import com.intellij.execution.ExecutionResult; -import com.intellij.execution.Executor; import com.intellij.execution.configurations.RunProfile; import com.intellij.execution.configurations.RunProfileState; import com.intellij.execution.runners.DefaultProgramRunner; @@ -44,10 +43,10 @@ public class XsltDebuggerRunner extends DefaultProgramRunner { } @Override - protected RunContentDescriptor doExecute(Project project, - RunProfileState state, + protected RunContentDescriptor doExecute(@NotNull Project project, + @NotNull RunProfileState state, RunContentDescriptor contentToReuse, - ExecutionEnvironment env) throws ExecutionException { + @NotNull ExecutionEnvironment env) throws ExecutionException { FileDocumentManager.getInstance().saveAllDocuments(); return createContentDescriptor(project, state, contentToReuse, env); } diff --git a/python/helpers/pycharm/nose_utils.py b/python/helpers/pycharm/nose_utils.py index 9a6d68251cb3..a7efa08d4f4e 100644 --- a/python/helpers/pycharm/nose_utils.py +++ b/python/helpers/pycharm/nose_utils.py @@ -116,7 +116,7 @@ class TeamcityPlugin(ErrorClassPlugin, TextTestResult, TeamcityTestResult): suite = strclass(test.__class__) suite_location = "python_nosetestid://" + suite try: - from nose_helper.util import func_lineno + from nose.util import func_lineno if hasattr(test.test, "descriptor") and test.test.descriptor: suite_location = "file://" + self.test_address( diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java index 53dd81ab746c..566fe0a2dbba 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java @@ -155,6 +155,7 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine List getClassAttributes(); + @Nullable PyTargetExpression findClassAttribute(@NotNull String name, boolean inherited); List getInstanceAttributes(); diff --git a/python/src/com/jetbrains/python/codeInsight/PyInjectionUtil.java b/python/src/com/jetbrains/python/codeInsight/PyInjectionUtil.java index 6030afc5a158..fe51d6468fd5 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyInjectionUtil.java +++ b/python/src/com/jetbrains/python/codeInsight/PyInjectionUtil.java @@ -81,7 +81,8 @@ public class PyInjectionUtil { */ @NotNull public static InjectionResult registerStringLiteralInjection(@NotNull PsiElement element, @NotNull MultiHostRegistrar registrar) { - return processStringLiteral(element, registrar, "", "", Formatting.NONE); + // Assume percent formatting since the MySQL parser cannot handle Python-style substitutions + return processStringLiteral(element, registrar, "", "", Formatting.PERCENT); } private static boolean isStringLiteralPart(@NotNull PsiElement element, @Nullable PsiElement context) { diff --git a/python/src/com/jetbrains/python/debugger/PyDebugRunner.java b/python/src/com/jetbrains/python/debugger/PyDebugRunner.java index 7ca044b0a90f..0f787a535810 100644 --- a/python/src/com/jetbrains/python/debugger/PyDebugRunner.java +++ b/python/src/com/jetbrains/python/debugger/PyDebugRunner.java @@ -76,9 +76,9 @@ public class PyDebugRunner extends GenericProgramRunner { ((AbstractPythonRunConfiguration)profile).canRunWithCoverage(); } - protected RunContentDescriptor doExecute(final Project project, RunProfileState profileState, + protected RunContentDescriptor doExecute(@NotNull final Project project, @NotNull RunProfileState profileState, RunContentDescriptor contentToReuse, - ExecutionEnvironment env) throws ExecutionException { + @NotNull ExecutionEnvironment env) throws ExecutionException { FileDocumentManager.getInstance().saveAllDocuments(); final PythonCommandLineState pyState = (PythonCommandLineState)profileState; diff --git a/python/src/com/jetbrains/python/inspections/quickfix/AddMethodQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/AddMethodQuickFix.java index 30d99103b887..6d90ec3be366 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/AddMethodQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/AddMethodQuickFix.java @@ -38,6 +38,7 @@ import org.jetbrains.annotations.NotNull; import static com.jetbrains.python.psi.PyUtil.sure; /** + * TODO: Refactor and move to {@link com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil#createMethod(String, com.jetbrains.python.psi.PyClass, com.jetbrains.python.psi.PyFunction.Modifier, String...)} * Adds a method foo to class X if X.foo() is unresolved. * User: dcheryasov * Date: Apr 5, 2009 6:51:26 PM diff --git a/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java b/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java index 9c34062d2f08..6ad33d60569e 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java @@ -238,6 +238,9 @@ public class PyNamedParameterImpl extends PyPresentableElementImpl entry : mapping.getPlainMappedParams().entrySet()) { - if (entry.getValue() == PyNamedParameterImpl.this) { - final PyExpression argument = entry.getKey(); - if (argument != null) { - final PyType type = context.getType(argument); - if (type != null) { - types.add(type); - return true; + final PyArgumentList argumentList = call.getArgumentList(); + if (argumentList != null) { + final CallArgumentsMapping mapping = argumentList.analyzeCall(resolveContext); + for (Map.Entry entry : mapping.getPlainMappedParams().entrySet()) { + if (entry.getValue() == PyNamedParameterImpl.this) { + final PyExpression argument = entry.getKey(); + if (argument != null) { + final PyType type = context.getType(argument); + if (type != null) { + types.add(type); + return true; + } } } } diff --git a/python/src/com/jetbrains/python/refactoring/classes/PyClassMembersRefactoringSupport.java b/python/src/com/jetbrains/python/refactoring/classes/PyClassMembersRefactoringSupport.java index 71f920c8399e..17588e666e25 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/PyClassMembersRefactoringSupport.java +++ b/python/src/com/jetbrains/python/refactoring/classes/PyClassMembersRefactoringSupport.java @@ -22,6 +22,7 @@ import com.intellij.refactoring.classMembers.DependentMembersCollectorBase; import com.intellij.refactoring.classMembers.MemberInfoBase; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyElement; +import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo; /** * @author Dennis.Ushakov diff --git a/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java b/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java index eda33558779f..360e9f8a10b0 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java +++ b/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java @@ -32,6 +32,7 @@ import com.jetbrains.python.codeInsight.PyCodeInsightSettings; import com.jetbrains.python.codeInsight.imports.AddImportHelper; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyBuiltinCache; +import com.jetbrains.python.psi.impl.PyFunctionBuilder; import com.jetbrains.python.psi.impl.PyImportedModule; import com.jetbrains.python.psi.impl.PyPsiUtils; import com.jetbrains.python.psi.resolve.QualifiedNameFinder; @@ -40,6 +41,9 @@ import org.jetbrains.annotations.Nullable; import java.util.*; +import static com.jetbrains.python.psi.PyFunction.Modifier.CLASSMETHOD; +import static com.jetbrains.python.psi.PyFunction.Modifier.STATICMETHOD; + /** * @author Dennis.Ushakov */ @@ -139,6 +143,22 @@ public class PyClassRefactoringUtil { return false; } + /** + * Moves class field declarations to some other place + * @param expressions list of class fields + * @param superClass where to move them + */ + public static void moveFieldDeclarationToStatement(@NotNull final Collection expressions, + @NotNull final PyStatementList superClassStatement) { + for (final PyTargetExpression expression : expressions) { + final PyAssignmentStatement expAssignmentStatement = PsiTreeUtil.getParentOfType(expression, PyAssignmentStatement.class); + assert expAssignmentStatement != null: "Target expression has no assignment statement"; + PyUtil.addElementToStatementList(expAssignmentStatement.copy(), superClassStatement, true); + expAssignmentStatement.delete(); + PyPsiUtils.removeRedundantPass(superClassStatement); + } + + } public static void moveMethods(Collection methods, PyClass superClass) { if (methods.size() == 0) return; for (PsiElement e : methods) { @@ -421,4 +441,41 @@ public class PyClassRefactoringUtil { } return null; } + + /** + * Creates class method + * @param methodName name if new method (be sure to check {@link com.jetbrains.python.PyNames} for special methods) + * @param pyClass class to add method + * @param modifier if method static or class or simple instance method (null)> + * @param parameterNames method parameters + * @return newly created method + */ + @NotNull + public static PyFunction createMethod(@NotNull final String methodName, + @NotNull final PyClass pyClass, + @Nullable final PyFunction.Modifier modifier, + @NotNull final String... parameterNames) { + final PyFunctionBuilder builder = new PyFunctionBuilder(methodName); + + + //TODO: Take names from codestyle? + if (modifier == null) { + builder.parameter(PyNames.CANONICAL_SELF); + } + else if (modifier == CLASSMETHOD) { + builder.parameter(PyNames.CANONICAL_CLS); + builder.decorate(PyNames.CLASSMETHOD); + } + else if (modifier == STATICMETHOD) { + builder.decorate(PyNames.STATICMETHOD); + } + + for (final String parameterName : parameterNames) { + builder.parameter(parameterName); + } + + final PyFunction function = builder.addFunction(pyClass.getStatementList(), LanguageLevel.getDefault()); + addMethods(pyClass, new PyElement[]{function}, true); + return function; + } } diff --git a/python/src/com/jetbrains/python/refactoring/classes/PyDependentMembersCollector.java b/python/src/com/jetbrains/python/refactoring/classes/PyDependentMembersCollector.java index 5c51118c0129..5efb3525d5ba 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/PyDependentMembersCollector.java +++ b/python/src/com/jetbrains/python/refactoring/classes/PyDependentMembersCollector.java @@ -29,6 +29,7 @@ public class PyDependentMembersCollector extends DependentMembersCollectorBase

{ - public PyMemberInfo(PyElement member) { - super(member); - final PyClass clazz = PyUtil.getContainingClassOrSelf(member); - assert clazz != null; - - if (member instanceof PyFunction) { - PyFunction function = (PyFunction)member; - displayName = buildDisplayMethodName(function); - for (PyClass aClass : clazz.getSuperClasses()) { - final PyFunction parentMethod = aClass.findMethodByName(function.getName(), true); - if (parentMethod != null) { - overrides = true; - } - } - } else if (member instanceof PyClass) { - displayName = RefactoringBundle.message("member.info.extends.0", PyClassCellRenderer.getClassText((PyClass)member)); - } - } - - private static String buildDisplayMethodName(PyFunction method) { - final StringBuilder builder = new StringBuilder(method.getName()); - builder.append("("); - final PyParameter[] arguments = method.getParameterList().getParameters(); - for (PyParameter parameter : arguments) { - builder.append(parameter.getName()); - if (arguments.length > 1 && parameter != arguments[arguments.length - 1]) { - builder.append(", "); - } - } - builder.append(")"); - return builder.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof PyMemberInfo) { - return getMember().equals(((PyMemberInfo)obj).getMember()); - } - return false; - } - - @Override - public int hashCode() { - return getMember().hashCode(); - } -} diff --git a/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfoStorage.java b/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfoStorage.java index 5c172e63b812..ae6d769f35ab 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfoStorage.java +++ b/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfoStorage.java @@ -22,6 +22,8 @@ import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyElement; import com.jetbrains.python.psi.PyFunction; import com.jetbrains.python.refactoring.PyRefactoringUtil; +import com.jetbrains.python.refactoring.classes.membersManager.MembersManager; +import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo; import java.util.ArrayList; @@ -60,12 +62,7 @@ public class PyMemberInfoStorage extends AbstractMemberInfoStorage temp) { - for (PyFunction function : aClass.getMethods()) { - temp.add(new PyMemberInfo(function)); - } - for (PyClass pyClass : aClass.getSuperClasses()) { - temp.add(new PyMemberInfo(pyClass)); - } + temp.addAll(MembersManager.getAllMembersCouldBeMoved(aClass)); } @Override diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassDialog.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassDialog.java index c0bc437b9498..05dab4f7aa7f 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassDialog.java +++ b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassDialog.java @@ -34,7 +34,7 @@ import com.jetbrains.python.PyBundle; import com.jetbrains.python.PythonLanguage; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyElement; -import com.jetbrains.python.refactoring.classes.PyMemberInfo; +import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo; import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage; import com.jetbrains.python.refactoring.classes.ui.UpDirectedMembersMovingDialog; import org.jetbrains.annotations.NotNull; diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHandler.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHandler.java index a68860d6e97f..8ed2fa8aef85 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHandler.java +++ b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHandler.java @@ -28,7 +28,7 @@ import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyUtil; import com.jetbrains.python.refactoring.classes.PyClassMembersRefactoringSupport; import com.jetbrains.python.refactoring.classes.PyClassRefactoringHandler; -import com.jetbrains.python.refactoring.classes.PyMemberInfo; +import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo; import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage; import java.util.Collection; diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java index 0d8033704728..98d016e50fa3 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java +++ b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java @@ -37,7 +37,7 @@ import com.jetbrains.python.PythonFileType; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyPsiUtils; import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil; -import com.jetbrains.python.refactoring.classes.PyMemberInfo; +import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/ClassFieldsManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/ClassFieldsManager.java new file mode 100644 index 000000000000..7d02461501d1 --- /dev/null +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/ClassFieldsManager.java @@ -0,0 +1,40 @@ +package com.jetbrains.python.refactoring.classes.membersManager; + +import com.jetbrains.python.psi.PyClass; +import com.jetbrains.python.psi.PyTargetExpression; +import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.List; + +/** + * Moves class attributes up + * + * @author Ilya.Kazakevich + */ +class ClassFieldsManager extends FieldsManager { + + ClassFieldsManager() { + super(true); + } + + + @Override + protected void moveMembers(@NotNull final PyClass from, + @NotNull final PyClass to, + @NotNull final Collection members) { + PyClassRefactoringUtil.moveFieldDeclarationToStatement(members, to.getStatementList()); + } + + @Override + protected boolean classHasField(@NotNull final PyClass pyClass, @NotNull final String fieldName) { + return pyClass.findClassAttribute(fieldName, true) != null; + } + + @NotNull + @Override + protected List getFieldsByClass(@NotNull PyClass pyClass) { + return pyClass.getClassAttributes(); + } +} diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/FieldsManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/FieldsManager.java new file mode 100644 index 000000000000..1721f738cbe4 --- /dev/null +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/FieldsManager.java @@ -0,0 +1,96 @@ +package com.jetbrains.python.refactoring.classes.membersManager; + +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; +import com.intellij.psi.PsiElement; +import com.jetbrains.python.psi.PyAssignmentStatement; +import com.jetbrains.python.psi.PyClass; +import com.jetbrains.python.psi.PyElement; +import com.jetbrains.python.psi.PyTargetExpression; +import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.List; + +/** + * Parent of all field-based plugins (like class fields, instance fields and so on) + * @author Ilya.Kazakevich + */ +abstract class FieldsManager extends MembersManager { + private static final SimpleAssignmentsOnly SIMPLE_ASSIGNMENTS_ONLY = new SimpleAssignmentsOnly(); + private final boolean myStatic; + + /** + * @param isStatic is field static or not? + */ + protected FieldsManager(final boolean isStatic) { + super(PyTargetExpression.class); + myStatic = isStatic; + } + + @NotNull + @Override + protected List getMembersCouldBeMoved(@NotNull final PyClass pyClass) { + return Lists.newArrayList(Collections2.filter(getFieldsByClass(pyClass), SIMPLE_ASSIGNMENTS_ONLY)); + } + + /** + * Checks if class has fields. Only child may know how to obtain field + * @param pyClass class to check + * @param fieldName field name + * @return true if has one + */ + protected abstract boolean classHasField(@NotNull PyClass pyClass, @NotNull String fieldName); + + /** + * Returns all fields by class. Only child may know how to obtain fields + * @param pyClass class to check + * @return list of fields in target expression (declaration) form + */ + @NotNull + protected abstract List getFieldsByClass(@NotNull PyClass pyClass); + + + @NotNull + @Override + public PyMemberInfo apply(@NotNull final PyElement input) { + return new PyMemberInfo(input, myStatic, input.getText(), isOverrides((PyTargetExpression)input), this); + } + + @Nullable + private Boolean isOverrides(@NotNull final PyTargetExpression input) { + final PyClass aClass = input.getContainingClass(); + final String name = input.getName(); + if (name == null) { + return null; //Field with out of name can't override something + } + + assert aClass != null : "Target expression declared outside of class:" + input; + + return classHasField(aClass, name) ? true : null; + } + + @Override + protected void moveMembers(@NotNull final PyClass from, + @NotNull final PyClass to, + @NotNull final Collection members) { + PyClassRefactoringUtil.moveFieldDeclarationToStatement(members, to.getStatementList()); + } + + + private static class SimpleAssignmentsOnly implements Predicate { + //Support only simplest cases like CLASS_VAR = 42. + //Tuples (CLASS_VAR_1, CLASS_VAR_2) = "spam", "eggs" are not supported by now + @Override + public boolean apply(@Nullable final PyTargetExpression input) { + if (input == null) { + return false; //Filter out empties (which probably would never be here) + } + final PsiElement parent = input.getParent(); + return (parent != null) && PyAssignmentStatement.class.isAssignableFrom(parent.getClass()); + } + } +} diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/InstanceFieldsManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/InstanceFieldsManager.java new file mode 100644 index 000000000000..27ca59f88c1e --- /dev/null +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/InstanceFieldsManager.java @@ -0,0 +1,46 @@ +package com.jetbrains.python.refactoring.classes.membersManager; + +import com.jetbrains.python.PyNames; +import com.jetbrains.python.psi.*; +import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.List; + +/** + * @author Ilya.Kazakevich + */ +class InstanceFieldsManager extends FieldsManager { + InstanceFieldsManager() { + super(false); + } + + + @Override + protected void moveMembers(@NotNull final PyClass from, + @NotNull final PyClass to, + @NotNull final Collection members) { + //We need __init__ method, and if there is no any -- we need to create it + PyFunction initMethod = to.findMethodByName(PyNames.INIT, false); + if (initMethod == null) { + initMethod = PyClassRefactoringUtil.createMethod(PyNames.INIT, to, null); + } + final PyStatementList statementList = initMethod.getStatementList(); + if (statementList == null) { + return; //TODO: Investigate how could it be + } + PyClassRefactoringUtil.moveFieldDeclarationToStatement(members, statementList); + } + + @Override + protected boolean classHasField(@NotNull final PyClass pyClass, @NotNull final String fieldName) { + return pyClass.findInstanceAttribute(fieldName, true) != null; + } + + @NotNull + @Override + protected List getFieldsByClass(@NotNull final PyClass pyClass) { + return pyClass.getInstanceAttributes(); + } +} diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MembersManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MembersManager.java new file mode 100644 index 000000000000..7bbefd9d2fa2 --- /dev/null +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MembersManager.java @@ -0,0 +1,172 @@ +package com.jetbrains.python.refactoring.classes.membersManager; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Collections2; +import com.google.common.collect.Multimap; +import com.intellij.psi.PsiNamedElement; +import com.jetbrains.python.psi.PyClass; +import com.jetbrains.python.psi.PyElement; +import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * Moves members between classes via its plugins (managers). + * To move members use {@link #getAllMembersCouldBeMoved(com.jetbrains.python.psi.PyClass)} and {@link #moveMembers(com.jetbrains.python.psi.PyClass, com.jetbrains.python.psi.PyClass, java.util.Collection)} + * To add new manager, extend this class and add it to {@link #MANAGERS} + * + * @author Ilya.Kazakevich + */ +public abstract class MembersManager implements Function { + /** + * List of managers. Class delegates all logic to them. + */ + private static final Collection> MANAGERS = + Arrays.asList(new MethodsManager(), new SuperClassesManager(), new ClassFieldsManager(), new InstanceFieldsManager()); + private static final PyMemberExtractor PY_MEMBER_EXTRACTOR = new PyMemberExtractor(); + + @NotNull + private final Class myExpectedClass; + + protected MembersManager(@NotNull final Class expectedClass) { + myExpectedClass = expectedClass; + } + + /** + * Get all members that could be moved out of certain class + * + * @param pyClass class to find members + * @return list of members could be moved + */ + @NotNull + public static List getAllMembersCouldBeMoved(@NotNull final PyClass pyClass) { + final List result = new ArrayList(); + + for (final MembersManager manager : MANAGERS) { + result.addAll(Collections2.transform(manager.getMembersCouldBeMoved(pyClass), manager)); + } + return result; + } + + + /** + * Moves members from one class to another + * + * @param from source + * @param to destination + * @param memberInfos members to move + */ + public static void moveAllMembers(@NotNull final PyClass from, + @NotNull final PyClass to, + @NotNull final Collection memberInfos) { + final Multimap, PyMemberInfo> managerToMember = ArrayListMultimap.create(); + //Collect map (manager)->(list_of_memebers) + for (final PyMemberInfo memberInfo : memberInfos) { + managerToMember.put(memberInfo.getMembersManager(), memberInfo); + } + //Move members via manager + for (final MembersManager membersManager : managerToMember.keySet()) { + moveSafely(from, to, membersManager, Collections2.transform(managerToMember.get(membersManager), PY_MEMBER_EXTRACTOR)); + } + PyClassRefactoringUtil.insertPassIfNeeded(from); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) //We check classes at runtime + private static void moveSafely(@NotNull final PyClass from, + @NotNull final PyClass to, + @NotNull final MembersManager manager, + @NotNull final Collection elementsToMove) { + for (final PyElement pyElement : elementsToMove) { + Preconditions.checkArgument(manager.myExpectedClass.isAssignableFrom(pyElement.getClass()), + String.format("Manager %s expected %s but got %s", manager, manager.myExpectedClass, pyElement)); + } + + manager.moveMembers(from, to, (Collection)elementsToMove); + } + + /** + * Finds member in class. It is here only for backward compatibility with some tests. + */ + //TODO: mark deprecated? + @TestOnly + @NotNull + public static PyMemberInfo findMember(@NotNull final PyClass pyClass, @NotNull final PyElement pyElement) { + for (final PyMemberInfo pyMemberInfo : getAllMembersCouldBeMoved(pyClass)) { + if (pyMemberInfo.getMember().equals(pyElement)) { + return pyMemberInfo; + } + } + throw new IllegalArgumentException(String.format("Element %s not found in class %s or can't be moved", pyElement, pyClass)); + } + + /** + * Get list of elements certain plugin could move out of the class + * + * @param pyClass class with members + * @return list of members + */ + @NotNull + protected abstract List getMembersCouldBeMoved(@NotNull PyClass pyClass); + + + /** + * Filters out named elements (ones that subclasses {@link com.intellij.psi.PsiNamedElement}) and {@link com.jetbrains.python.psi.PyElement}) + * that are null or has null name. + * You need it sometimes when code has errors (i.e. bad formatted code with annotation may treat annotation as method with null name. + * note: we should probably throw exceptions in such cases and display "refactoring not available" window in handler) + * + * @param elementsToFilter collection of elements to filter + * @param element type + * @return collection of T with out of nulls and elemens whos {@link com.intellij.psi.PsiNamedElement#getName()} returns null + */ + @NotNull + protected static Collection filterNameless(@NotNull final Collection elementsToFilter) { + return Collections2.filter(elementsToFilter, new NamelessFilter()); + } + + /** + * Moves element from one class to another + * + * @param from source + * @param to destination + * @param members collection of memebrs to move + */ + protected abstract void moveMembers(@NotNull PyClass from, @NotNull PyClass to, @NotNull Collection members); + + /** + * Creates {@link com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo} from {@link com.jetbrains.python.psi.PyElement} + * This process is plugin-specific and should be implemented in each plugin + * @param input element + * @return member info + */ + @SuppressWarnings("NullableProblems") //IDEA-120100 + @NotNull + @Override + public abstract PyMemberInfo apply(@NotNull PyElement input); + + private static class PyMemberExtractor implements Function { + @SuppressWarnings("NullableProblems") //IDEA-120100 + @Override + public PyElement apply(@NotNull final PyMemberInfo input) { + return input.getMember(); + } + } + + private static class NamelessFilter implements Predicate { + @Override + public boolean apply(@Nullable final T input) { + return (input != null) && (input.getName() != null); + } + } +} + + diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java new file mode 100644 index 000000000000..ee0c9ca17f42 --- /dev/null +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java @@ -0,0 +1,73 @@ +package com.jetbrains.python.refactoring.classes.membersManager; + +import com.google.common.collect.Lists; +import com.jetbrains.python.psi.*; +import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * Plugin that moves class methods + * + * @author Ilya.Kazakevich + */ +class MethodsManager extends MembersManager { + + MethodsManager() { + super(PyFunction.class); + } + + @NotNull + @Override + protected List getMembersCouldBeMoved(@NotNull final PyClass pyClass) { + return Lists.newArrayList(filterNameless(Arrays.asList(pyClass.getMethods()))); + } + + @Override + protected void moveMembers(@NotNull final PyClass from, @NotNull final PyClass to, @NotNull final Collection members) { + PyClassRefactoringUtil.moveMethods(members, to); + } + + @NotNull + @Override + public PyMemberInfo apply(@NotNull final PyElement input) { + //TODO: Use generics to prevent casting in each subclass + final PyFunction pyFunction = (PyFunction)input; + final PyUtil.MethodFlags flags = PyUtil.MethodFlags.of(pyFunction); + assert flags != null : "No flags return while element is function " + pyFunction; + final boolean isStatic = flags.isStaticMethod() || flags.isClassMethod(); + return new PyMemberInfo(input, isStatic, buildDisplayMethodName(pyFunction), isOverrides(pyFunction), this); + } + + @Nullable + private static Boolean isOverrides(final PyFunction pyFunction) { + final PyClass clazz = PyUtil.getContainingClassOrSelf(pyFunction); + assert clazz != null : "Refactoring called on function, not method: " + pyFunction; + for (final PyClass parentClass : clazz.getSuperClasses()) { + final PyFunction parentMethod = parentClass.findMethodByName(pyFunction.getName(), true); + if (parentMethod != null) { + return true; + } + } + return null; + } + + @NotNull + private static String buildDisplayMethodName(@NotNull final PyFunction pyFunction) { + final StringBuilder builder = new StringBuilder(pyFunction.getName()); + builder.append('('); + final PyParameter[] arguments = pyFunction.getParameterList().getParameters(); + for (final PyParameter parameter : arguments) { + builder.append(parameter.getName()); + if (arguments.length > 1 && parameter != arguments[arguments.length - 1]) { + builder.append(", "); + } + } + builder.append(')'); + return builder.toString(); + } +} diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMemberInfo.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMemberInfo.java new file mode 100644 index 000000000000..641025a3df94 --- /dev/null +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMemberInfo.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.python.refactoring.classes.membersManager; + +import com.intellij.refactoring.classMembers.MemberInfoBase; +import com.jetbrains.python.psi.PyElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Dennis.Ushakov + */ +public class PyMemberInfo extends MemberInfoBase { + @NotNull + private final MembersManager myMembersManager; + + /** + * @param member element itself + * @param isStatic is it static or not? + * @param displayName element display name + * @param overrides does it overrides something? TRUE if is overriden, FALSE if implemented, null if not implemented or overriden + * TODO: use primitive instead? "Implemeneted" has nothing to do with python duck-typing + * @param membersManager manager that knows how to handle this member + */ + PyMemberInfo(@NotNull final PyElement member, + final boolean isStatic, + @NotNull final String displayName, + @Nullable final Boolean overrides, + @NotNull final MembersManager membersManager) { + super(member); + this.isStatic = isStatic; + this.displayName = displayName; + this.overrides = overrides; + myMembersManager = membersManager; + } + + @NotNull + MembersManager getMembersManager() { + return myMembersManager; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof PyMemberInfo) { + return getMember().equals(((PyMemberInfo)obj).getMember()); + } + return false; + } + + @Override + public int hashCode() { + return getMember().hashCode(); + } +} diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/SuperClassesManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/SuperClassesManager.java new file mode 100644 index 000000000000..0caf927c9751 --- /dev/null +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/SuperClassesManager.java @@ -0,0 +1,74 @@ +package com.jetbrains.python.refactoring.classes.membersManager; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.Sets; +import com.intellij.psi.PsiNamedElement; +import com.intellij.refactoring.RefactoringBundle; +import com.jetbrains.python.psi.PyClass; +import com.jetbrains.python.psi.PyElement; +import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil; +import com.jetbrains.python.refactoring.classes.ui.PyClassCellRenderer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +/** + * Plugin that moves superclasses from one class to another + * + * @author Ilya.Kazakevich + */ +class SuperClassesManager extends MembersManager { + SuperClassesManager() { + super(PyClass.class); + } + + private static final NameExtractor NAME_EXTRACTOR = new NameExtractor(); + private static final NameFilter NAME_FILTER = new NameFilter(); + + @NotNull + @Override + protected List getMembersCouldBeMoved(@NotNull final PyClass pyClass) { + return Arrays.asList(pyClass.getSuperClasses()); + } + + @Override + protected void moveMembers(@NotNull final PyClass from, @NotNull final PyClass to, @NotNull final Collection members) { + final Set superClassesToMove = + Sets.newHashSet(Collections2.filter(Collections2.transform(members, NAME_EXTRACTOR), NAME_FILTER)); + + for (final PyElement member : members) { + superClassesToMove.add(member.getName()); + } + + PyClassRefactoringUtil.moveSuperclasses(from, superClassesToMove, to); + //TODO: Use generics! + PyClassRefactoringUtil.insertImport(to, new ArrayList(members)); + } + + @NotNull + @Override + public PyMemberInfo apply(@NotNull final PyElement input) { + final String name = RefactoringBundle.message("member.info.extends.0", PyClassCellRenderer.getClassText((PyClass)input)); + //TODO: Check for "overrides" + return new PyMemberInfo(input, false, name, false, this); + } + + private static class NameExtractor implements Function { + @SuppressWarnings("NullableProblems") //We sure collection has no null + @Nullable + @Override + public String apply(@NotNull final PyElement input) { + return input.getName(); + } + } + + private static class NameFilter implements Predicate { + @Override + public boolean apply(@Nullable final String input) { + return input != null; + } + } +} diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/package-info.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/package-info.java new file mode 100644 index 000000000000..b730fd4e3c06 --- /dev/null +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/package-info.java @@ -0,0 +1,12 @@ +/** + * Incapsulates knowledge about class members that could be moved to some other class. + * To use (get list of members to move or actually move them) use {@link com.jetbrains.python.refactoring.classes.membersManager.MembersManager#getAllMembersCouldBeMoved(com.jetbrains.python.psi.PyClass)} + * and {@link com.jetbrains.python.refactoring.classes.membersManager.MembersManager#moveAllMembers(com.jetbrains.python.psi.PyClass, com.jetbrains.python.psi.PyClass, java.util.Collection)} + * + * This class delegates its behaviour to its managers (some kind of plugins). There is one for each member type (one for method, one for field etc). + * You need to extend {@link com.jetbrains.python.refactoring.classes.membersManager.MembersManager} to add some. See its javadoc for more info. + * + * + * @author Ilya.Kazakevich + */ +package com.jetbrains.python.refactoring.classes.membersManager; \ No newline at end of file diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PullUpViewSwingImpl.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PullUpViewSwingImpl.java index 7707faab3f00..b0c38d31c8fa 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PullUpViewSwingImpl.java +++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PullUpViewSwingImpl.java @@ -26,7 +26,7 @@ import com.intellij.refactoring.ui.ConflictsDialog; import com.intellij.util.containers.MultiMap; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyElement; -import com.jetbrains.python.refactoring.classes.PyMemberInfo; +import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo; import com.jetbrains.python.refactoring.classes.ui.PyClassCellRenderer; import com.jetbrains.python.refactoring.classes.ui.PyMemberSelectionPanel; import com.jetbrains.python.refactoring.classes.ui.PyMemberSelectionTable; diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpConflictsUtil.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpConflictsUtil.java index 8d68255f1a1a..0cfd25fc1748 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpConflictsUtil.java +++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpConflictsUtil.java @@ -21,7 +21,7 @@ import com.intellij.refactoring.util.RefactoringUIUtil; import com.intellij.util.containers.MultiMap; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyFunction; -import com.jetbrains.python.refactoring.classes.PyMemberInfo; +import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -38,6 +38,7 @@ public class PyPullUpConflictsUtil { for (PyMemberInfo info : infos) { PsiElement member = info.getMember(); boolean isConflict = false; + //TODO: Delegate to MemeberManagers here if (member instanceof PyFunction) { final String name = ((PyFunction)member).getName(); if (name == null) continue; diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpHelper.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpHelper.java index 0046ba2eef92..37f3718b84ed 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpHelper.java +++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpHelper.java @@ -17,49 +17,31 @@ package com.jetbrains.python.refactoring.classes.pullUp; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.psi.PsiNamedElement; import com.intellij.refactoring.RefactoringBundle; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyElement; -import com.jetbrains.python.psi.PyFunction; -import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil; -import com.jetbrains.python.refactoring.classes.PyMemberInfo; +import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo; +import com.jetbrains.python.refactoring.classes.membersManager.MembersManager; -import java.util.*; +import java.util.Collection; /** * @author Dennis.Ushakov */ -public class PyPullUpHelper { - private static final Logger LOG = Logger.getInstance(PyPullUpHelper.class.getName()); - private PyPullUpHelper() {} +public final class PyPullUpHelper { + + private PyPullUpHelper() { + } public static PyElement pullUp(final PyClass clazz, final Collection selectedMemberInfos, final PyClass superClass) { - final Set superClasses = new HashSet(); - final Set extractedClasses = new HashSet(); - final List methods = new ArrayList(); - for (PyMemberInfo member : selectedMemberInfos) { - final PyElement element = member.getMember(); - if (element instanceof PyFunction) methods.add((PyFunction)element); - else if (element instanceof PyClass) { - superClasses.add(element.getName()); - extractedClasses.add((PyClass)element); - } - else LOG.error("unmatched member class " + element.getClass()); - } - + CommandProcessor.getInstance().executeCommand(clazz.getProject(), new Runnable() { + @Override public void run() { ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override public void run() { - // move methods - PyClassRefactoringUtil.moveMethods(methods, superClass); - - // move superclasses declarations - PyClassRefactoringUtil.moveSuperclasses(clazz, superClasses, superClass); - PyClassRefactoringUtil.insertImport(superClass, extractedClasses); - PyClassRefactoringUtil.insertPassIfNeeded(clazz); + MembersManager.moveAllMembers(clazz, superClass, selectedMemberInfos); } }); } diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterImpl.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterImpl.java index 8ab80cf5603a..ad8cdd5bde3f 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterImpl.java +++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterImpl.java @@ -25,12 +25,13 @@ import com.intellij.util.containers.MultiMap; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyElement; import com.jetbrains.python.psi.PyUtil; -import com.jetbrains.python.refactoring.classes.PyMemberInfo; +import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo; import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage; import org.jetbrains.annotations.NotNull; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; /** * Pull-up presenter implementation @@ -87,12 +88,13 @@ class PyPullUpPresenterImpl extends AbstractUsesDependencyMemberInfoModel.) is treated as method. + * member that starts with dash (#) is treated as attribute. * It is treated parent class otherwise * @return member or null if not found */ @NotNull protected PyElement findMember(@NotNull String className, @NotNull String memberName) { - boolean findMethod = memberName.contains("."); - PyElement result = (findMethod ? findMethod(className, memberName.substring(1)) : findClass(memberName)); + final PyElement result; + //TODO: Get rid of this chain of copy pastes + if (memberName.contains(".")) { + result = findMethod(className, memberName.substring(1)); + } + else if (memberName.contains("#")) { + result = findField(className, memberName.substring(1)); + } + else { + result = findClass(memberName); + } Assert.assertNotNull(String.format("No member %s found in class %s", memberName, className), result); return result; } + private PyElement findField(final String className, final String memberName) { + final PyClass aClass = findClass(className); + final PyTargetExpression attribute = aClass.findClassAttribute(memberName, false); + if (attribute != null) { + return attribute; + } + return aClass.findInstanceAttribute(memberName, false); + } + private PyFunction findMethod(final String className, final String name) { final PyClass clazz = findClass(className); return clazz.findMethodByName(name, false); diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/PyExtractSuperclassTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/PyExtractSuperclassTest.java index baab81cc5062..d143e966e077 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/classes/PyExtractSuperclassTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/classes/PyExtractSuperclassTest.java @@ -24,6 +24,8 @@ import com.jetbrains.python.PyNames; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyElement; import com.jetbrains.python.refactoring.classes.extractSuperclass.PyExtractSuperclassHelper; +import com.jetbrains.python.refactoring.classes.membersManager.MembersManager; +import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo; import java.io.File; import java.util.ArrayList; @@ -53,7 +55,7 @@ public class PyExtractSuperclassTest extends PyClassRefactoringTest { final List members = new ArrayList(); for (String memberName : membersName) { final PyElement member = findMember(className, memberName); - members.add(new PyMemberInfo(member)); + members.add(MembersManager.findMember(clazz, member)); } new WriteCommandAction.Simple(myFixture.getProject()) { @@ -81,7 +83,7 @@ public class PyExtractSuperclassTest extends PyClassRefactoringTest { final PyClass clazz = findClass(className); final List members = new ArrayList(); final PyElement member = findMember(className, ".foo"); - members.add(new PyMemberInfo(member)); + members.add(MembersManager.findMember(clazz, member)); final VirtualFile base_dir = myFixture.getFile().getVirtualFile().getParent(); new WriteCommandAction.Simple(myFixture.getProject()) { @@ -124,7 +126,7 @@ public class PyExtractSuperclassTest extends PyClassRefactoringTest { final PyClass clazz = findClass(className); final List members = new ArrayList(); final PyElement member = findMember(className, ".foo"); - members.add(new PyMemberInfo(member)); + members.add(MembersManager.findMember(clazz, member)); final VirtualFile base_dir = myFixture.getFile().getVirtualFile().getParent(); new WriteCommandAction.Simple(myFixture.getProject()) { diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/PyPullUpTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/PyPullUpTest.java index 881dac2a9766..1cfc64350182 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/classes/PyPullUpTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/classes/PyPullUpTest.java @@ -17,6 +17,7 @@ package com.jetbrains.python.refactoring.classes; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyElement; +import com.jetbrains.python.refactoring.classes.membersManager.MembersManager; import com.jetbrains.python.refactoring.classes.pullUp.PyPullUpHelper; import java.util.Collections; @@ -49,6 +50,20 @@ public class PyPullUpTest extends PyClassRefactoringTest { doHelperTest("Child", "Spam", "Parent_1"); } + public void testMoveClassAttributesSimple() { + doHelperTest("Child", "#CLASS_VAR", "Parent"); + } + public void testMoveClassAttributesNoPass() { + doHelperTest("Child2", "#CLASS_VAR", "Parent2"); + } + + public void testMoveInstanceAttributesSimple() { + doHelperTest("Child", "#instance_field", "Parent"); + } + public void testMoveInstanceAttributesNoInit() { + doHelperTest("Child", "#instance_field", "Parent"); + } + public void testMultiFile() { // PY-2810 doMultiFileTest(); } @@ -76,6 +91,6 @@ public class PyPullUpTest extends PyClassRefactoringTest { final PyClass clazz = findClass(className); final PyElement member = findMember(className, memberName); final PyClass superClass = findClass(superClassName); - PyPullUpHelper.pullUp(clazz, Collections.singleton(new PyMemberInfo(member)), superClass); + PyPullUpHelper.pullUp(clazz, Collections.singleton(MembersManager.findMember(clazz, member)), superClass); } } diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/PyPushDownTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/PyPushDownTest.java index 72c3bfded44a..480e3a4b4bf7 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/classes/PyPushDownTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/classes/PyPushDownTest.java @@ -18,6 +18,8 @@ package com.jetbrains.python.refactoring.classes; import com.intellij.openapi.command.WriteCommandAction; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyElement; +import com.jetbrains.python.refactoring.classes.membersManager.MembersManager; +import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo; import com.jetbrains.python.refactoring.classes.pushDown.PyPushDownProcessor; import java.util.ArrayList; @@ -55,7 +57,7 @@ public class PyPushDownTest extends PyClassRefactoringTest { final List members = new ArrayList(); for (String memberName : membersName) { final PyElement member = findMember(className, memberName); - members.add(new PyMemberInfo(member)); + members.add(MembersManager.findMember(clazz, member)); } final PyPushDownProcessor processor = new PyPushDownProcessor(myFixture.getProject(), clazz, members); diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterTest.java index 02092d208518..847ac86f2e02 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterTest.java @@ -2,18 +2,18 @@ package com.jetbrains.python.refactoring.classes.pullUp; import com.google.common.base.Function; import com.google.common.collect.Collections2; -import com.intellij.openapi.util.Pair; import com.intellij.refactoring.classMembers.MemberInfoModel; import com.jetbrains.python.fixtures.PyTestCase; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyElement; -import com.jetbrains.python.refactoring.classes.PyMemberInfo; import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage; +import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo; import org.easymock.Capture; import org.easymock.EasyMock; import org.easymock.internal.MocksControl; import org.hamcrest.Matcher; import org.hamcrest.Matchers; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.junit.Assert; @@ -70,12 +70,14 @@ public class PyPullUpPresenterTest extends PyTestCase { public void testNoParents() throws Exception { ensureNoMembers("NoParentsAllowed"); } + /** * Checks that refactoring does not work for classes with out of members */ public void testNoMembers() throws Exception { ensureNoMembers("NoMembers"); } + /** * Checks that refactoring does not work when C3 MRO can't be calculated */ @@ -84,10 +86,10 @@ public class PyPullUpPresenterTest extends PyTestCase { } /** - * Checks that some members are not allowed + * Checks that some members are not allowed, while others are */ - public void testDisabledMembers() throws Exception { - PyPullUpPresenterImpl sut = configureByClass("SomeMembersDisabled"); + public void testMembers() throws Exception { + PyPullUpPresenterImpl sut = configureByClass("HugeChild"); EasyMock.expect(myView.getSelectedParent()).andReturn(getClassByName("SubParent1")).anyTimes(); myMocksControl.replay(); @@ -96,15 +98,22 @@ public class PyPullUpPresenterTest extends PyTestCase { Assert.assertTrue("No members selected", myMemberInfos.hasCaptured()); List members = myMemberInfos.getValue(); Assert.assertFalse("No members selected", members.isEmpty()); - Collection> memberNamesAndStatus = Collections2.transform(members, new NameAndStatusTransformer(sut)); + final Collection memberNamesAndStatus = Collections2.transform(members, new NameAndStatusTransformer(sut)); //Pair will return correct type - @SuppressWarnings("unchecked") Matcher>> matcher = Matchers - .containsInAnyOrder( - Pair.create("date", true), - Pair.create("SubParent1", false), - Pair.create("foo", false), - Pair.create("bar", true)); + final Matcher> matcher = Matchers + .containsInAnyOrder(new Entry("extends date", true, false), + new Entry("CLASS_FIELD", true, true), + new Entry("__init__(self)", true, false), + new Entry("extends SubParent1", false, false), + new Entry("foo(self)", false, false), + new Entry("bar(self)", true, false), + new Entry("static_1(cls)", true, true), + new Entry("static_2()", true, true), + new Entry("self.instance_field_1", true, false), + new Entry("self.instance_field_2", true, false), + new Entry("bad_method()", true, false) + ); Assert.assertThat("Wrong members or their states", memberNamesAndStatus, matcher); @@ -127,7 +136,6 @@ public class PyPullUpPresenterTest extends PyTestCase { } - private PyPullUpPresenterImpl configureByClass(String name) { PyClass childClass = getClassByName(name); PyMemberInfoStorage storage = new PyMemberInfoStorage(childClass); @@ -147,7 +155,7 @@ public class PyPullUpPresenterTest extends PyTestCase { } } - private static class NameAndStatusTransformer implements Function> { + private static class NameAndStatusTransformer implements Function { private final PyPullUpPresenterImpl presenter; private NameAndStatusTransformer(PyPullUpPresenterImpl presenter) { @@ -155,9 +163,52 @@ public class PyPullUpPresenterTest extends PyTestCase { } @Override - public Pair apply(PyMemberInfo input) { - PyElement member = input.getMember(); - return Pair.create(member.getName(), presenter.isMemberEnabled(input)); + public Entry apply(final PyMemberInfo input) { + return new Entry(input.getDisplayName(), presenter.isMemberEnabled(input), input.isStatic()); + } + } + + private static class Entry { + @NonNls @NotNull + private final String myName; + private final boolean myEnabled; + private final boolean myStaticEntry; + + private Entry(@NotNull final String name, final boolean enabled, final boolean staticEntry) { + myName = name; + myEnabled = enabled; + myStaticEntry = staticEntry; + } + + @Override + public String toString() { + return "Entry{" + + "myName='" + myName + '\'' + + ", myEnabled=" + myEnabled + + ", myStaticEntry=" + myStaticEntry + + '}'; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (!(o instanceof Entry)) return false; + + final Entry entry = (Entry)o; + + if (myEnabled != entry.myEnabled) return false; + if (myStaticEntry != entry.myStaticEntry) return false; + if (!myName.equals(entry.myName)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myName.hashCode(); + result = 31 * result + (myEnabled ? 1 : 0); + result = 31 * result + (myStaticEntry ? 1 : 0); + return result; } } } diff --git a/python/testSrc/python-community-tests.iml b/python/testSrc/python-community-tests.iml index b4cc2764d3aa..6511d8860c87 100644 --- a/python/testSrc/python-community-tests.iml +++ b/python/testSrc/python-community-tests.iml @@ -15,6 +15,7 @@ + diff --git a/xml/xml-psi-impl/src/com/intellij/lang/html/HtmlParsing.java b/xml/xml-psi-impl/src/com/intellij/lang/html/HtmlParsing.java index 9d3df3f84536..250d27e9a101 100644 --- a/xml/xml-psi-impl/src/com/intellij/lang/html/HtmlParsing.java +++ b/xml/xml-psi-impl/src/com/intellij/lang/html/HtmlParsing.java @@ -386,14 +386,14 @@ public class HtmlParsing { } private boolean childTerminatesParentInStack(final String childName, final boolean terminateOnNonOptionalTag) { - boolean isTD = TD_TAG.equals(childName); - boolean isTR = TR_TAG.equals(childName); + boolean isCell = TD_TAG.equals(childName) || "th".equals(childName); + boolean isRow = TR_TAG.equals(childName); for (int i = myTagNamesStack.size() - 1; i >= 0; i--) { String parentName = myTagNamesStack.get(i); if (terminateOnNonOptionalTag && !HtmlUtil.isOptionalEndForHtmlTagL(parentName)) return false; - if (isTD && (TR_TAG.equals(parentName) || TABLE_TAG.equals(parentName)) || - isTR && TABLE_TAG.equals(parentName)) { + if (isCell && (TR_TAG.equals(parentName) || TABLE_TAG.equals(parentName)) || + isRow && TABLE_TAG.equals(parentName)) { return false; }