diff options
author | Tor Norbye <tnorbye@google.com> | 2014-08-20 17:01:23 -0700 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2014-08-20 17:01:23 -0700 |
commit | 1aa2e09bdbd413eacb677e9fa4b50630530d0656 (patch) | |
tree | 2f4cc6d69645bd460aa253fdecb606d764fbd25d /plugins | |
parent | 02cf98d65c798d368fcec43ed64a001d513bdd4f (diff) | |
download | idea-1aa2e09bdbd413eacb677e9fa4b50630530d0656.tar.gz |
Snapshot idea/138.1696 from git://git.jetbrains.org/idea/community.git
Change-Id: I50c97b83a815ce635e49a38380ba5b8765e4b16a
Diffstat (limited to 'plugins')
309 files changed, 3877 insertions, 2310 deletions
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml index 5581810b3f2c..c8854d4dbb26 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml @@ -2363,7 +2363,7 @@ implementationClass="com.siyeh.ig.style.UnnecessaryToStringCallInspection"/> <localInspection language="JAVA" suppressId="RedundantNoArgConstructor" shortName="UnnecessaryConstructor" bundle="com.siyeh.InspectionGadgetsBundle" key="unnecessary.constructor.display.name" groupBundle="messages.InspectionsBundle" - groupKey="group.names.code.style.issues" enabledByDefault="false" level="WARNING" cleanupTool="true" + groupKey="group.names.code.style.issues" enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.style.UnnecessaryConstructorInspection"/> <localInspection language="JAVA" shortName="UnnecessaryEnumModifier" bundle="com.siyeh.InspectionGadgetsBundle" key="unnecessary.enum.modifier.display.name" groupBundle="messages.InspectionsBundle" diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties index 715bf898c50a..1dfdfb9eb50a 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1700,7 +1700,7 @@ this.class=this class assertequals.may.be.assertsame.display.name='assertEquals()' may be 'assertSame()' assertequals.may.be.assertsame.problem.descriptor=<code>#ref()</code> may be 'assertSame()' #loc logger.initialized.with.foreign.class.quickfix=Replace with ''{0}.class'' -logger.initialized.with.foreign.class.problem.descriptor=Logger initializer with foreign class <code>#ref</code> #loc +logger.initialized.with.foreign.class.problem.descriptor=Logger initialized with foreign class <code>#ref</code> #loc logger.initialized.with.foreign.class.display.name=Logger initialized with foreign class logger.factory.method.name=Logger factory method name logger.factory.class.name=Logger factory class name @@ -2018,8 +2018,8 @@ string.concatenation.argument.to.log.call.display.name=Non-constant string conca string.concatenation.argument.to.log.call.problem.descriptor=Non-constant string concatenation as argument to <code>#ref()</code> logging call #loc string.concatenation.argument.to.log.call.quickfix=Replace concatenation with parameterized log message placeholder.count.matches.argument.count.display.name=Number of placeholders does not match number of arguments in logging call -placeholder.count.matches.argument.count.more.problem.descriptor=<code>#ref()</code> call has more arguments ({0}) than placeholders ({1}) #loc -placeholder.count.matches.argument.count.fewer.problem.descriptor=<code>#ref()</code> call has fewer arguments ({0}) than placeholders ({1}) #loc +placeholder.count.matches.argument.count.more.problem.descriptor=More arguments provided ({0}) than placeholders specified ({1}) in ''{2}'' #loc +placeholder.count.matches.argument.count.fewer.problem.descriptor=Fewer arguments provided ({0}) than placeholders specified ({1}) in ''{2}'' #loc assignment.to.superclass.field.display.name=Constructor assigns value to field defined in superclass assignment.to.superclass.field.problem.descriptor=Assignment to field ''{0}'' defined in superclass ''{1}'' #loc junit.rule.display.name=Malformed @Rule/@ClassRule field diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java index 80ebfa0ae7d3..00d9f04b8c02 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2010 Bas Leijdekkers + * Copyright 2007-2014 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ package com.siyeh.ig.fixes; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; -import com.intellij.util.IncorrectOperationException; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.psiutils.FinalUtils; @@ -61,8 +60,7 @@ public class MakeFieldFinalFix extends InspectionGadgetsFix { } @Override - protected void doFix(Project project, ProblemDescriptor descriptor) - throws IncorrectOperationException { + protected void doFix(Project project, ProblemDescriptor descriptor) { final PsiElement element = descriptor.getPsiElement(); final PsiField field; if (element instanceof PsiReferenceExpression) { @@ -81,6 +79,7 @@ public class MakeFieldFinalFix extends InspectionGadgetsFix { } field = (PsiField)parent; } + field.normalizeDeclaration(); final PsiModifierList modifierList = field.getModifierList(); if (modifierList == null) { return; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java index a2a3b12bd8de..ef598f5d2216 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java @@ -19,6 +19,7 @@ import com.intellij.psi.*; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.psiutils.TypeUtils; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -143,9 +144,10 @@ public class ImplicitDefaultCharsetUsageInspection extends BaseInspection { } private static boolean hasCharsetType(PsiVariable variable) { - final PsiType lastType = variable.getType(); - return lastType.equalsToText(CommonClassNames.JAVA_LANG_STRING) || - lastType.equalsToText("java.nio.charset.Charset"); + return TypeUtils.variableHasTypeOrSubtype(variable, CommonClassNames.JAVA_LANG_STRING, + "java.nio.charset.Charset", + "java.nio.charset.CharsetEncoder", + "java.nio.charset.CharsetDecoder"); } } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionBase.java index 750b723031d4..08c54abce2a1 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionBase.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. @@ -20,13 +20,13 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import com.siyeh.InspectionGadgetsBundle; 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.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -157,7 +157,10 @@ public class LoggerInitializedWithForeignClassInspectionBase extends BaseInspect if (expressions.length != 1) { return; } - final PsiClass containingClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class); + PsiClass containingClass = ClassUtils.getContainingClass(expression); + while (containingClass instanceof PsiAnonymousClass) { + containingClass = ClassUtils.getContainingClass(containingClass); + } if (containingClass == null) { return; } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspection.java index a2c9307fc80c..711b0edb5c4b 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspection.java @@ -45,13 +45,14 @@ public class PlaceholderCountMatchesArgumentCountInspection extends BaseInspecti protected String buildErrorString(Object... infos) { final Integer argumentCount = (Integer)infos[0]; final Integer placeholderCount = (Integer)infos[1]; + final Object value = infos[2]; if (argumentCount.intValue() > placeholderCount.intValue()) { return InspectionGadgetsBundle.message("placeholder.count.matches.argument.count.more.problem.descriptor", - argumentCount, placeholderCount); + argumentCount, placeholderCount, value); } else { return InspectionGadgetsBundle.message("placeholder.count.matches.argument.count.fewer.problem.descriptor", - argumentCount, placeholderCount); + argumentCount, placeholderCount, value); } } @@ -83,25 +84,24 @@ public class PlaceholderCountMatchesArgumentCountInspection extends BaseInspecti if (arguments.length == 0) { return; } - final PsiExpression firstArgument = arguments[0]; - final int placeholderCount; + PsiExpression logStringArgument = arguments[0]; final int argumentCount; - if (InheritanceUtil.isInheritor(firstArgument.getType(), "org.slf4j.Marker")) { + if (InheritanceUtil.isInheritor(logStringArgument.getType(), "org.slf4j.Marker")) { if (arguments.length < 2) { return; } - final PsiExpression secondArgument = arguments[1]; - placeholderCount = countPlaceholders(secondArgument); + logStringArgument = arguments[1]; argumentCount = countArguments(arguments, 2); } else { - placeholderCount = countPlaceholders(firstArgument); argumentCount = countArguments(arguments, 1); } + final Object value = ExpressionUtils.computeConstantExpression(logStringArgument); + final int placeholderCount = countPlaceholders(value); if (placeholderCount < 0 || argumentCount < 0 || placeholderCount == argumentCount) { return; } - registerMethodCallError(expression, Integer.valueOf(argumentCount), Integer.valueOf(placeholderCount)); + registerError(logStringArgument, Integer.valueOf(argumentCount), Integer.valueOf(placeholderCount), value); } private static boolean hasThrowableType(PsiExpression lastArgument) { @@ -118,8 +118,7 @@ public class PlaceholderCountMatchesArgumentCountInspection extends BaseInspecti return InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_THROWABLE); } - public static int countPlaceholders(PsiExpression argument) { - final Object value = ExpressionUtils.computeConstantExpression(argument); + public static int countPlaceholders(Object value) { if (!(value instanceof String)) { return -1; } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/MethodMayBeStaticInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/MethodMayBeStaticInspectionBase.java new file mode 100644 index 000000000000..2377e4e14c20 --- /dev/null +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/MethodMayBeStaticInspectionBase.java @@ -0,0 +1,181 @@ +/* + * 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.performance; + +import com.intellij.codeInspection.InspectionManager; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.WriteExternalException; +import com.intellij.psi.*; +import com.intellij.psi.search.searches.ClassInheritorsSearch; +import com.intellij.util.Processor; +import com.intellij.util.Query; +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.BaseInspection; +import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.psiutils.ClassUtils; +import com.siyeh.ig.psiutils.MethodUtils; +import com.siyeh.ig.psiutils.SerializationUtils; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.atomic.AtomicInteger; + +public class MethodMayBeStaticInspectionBase extends BaseInspection { + protected static final String IGNORE_DEFAULT_METHODS_ATTR_NAME = "m_ignoreDefaultMethods"; + protected static final String ONLY_PRIVATE_OR_FINAL_ATTR_NAME = "m_onlyPrivateOrFinal"; + protected static final String IGNORE_EMPTY_METHODS_ATTR_NAME = "m_ignoreEmptyMethods"; + protected static final String REPLACE_QUALIFIER_ATTR_NAME = "m_replaceQualifier"; + /** + * @noinspection PublicField + */ + public boolean m_onlyPrivateOrFinal = false; + /** + * @noinspection PublicField + */ + public boolean m_ignoreEmptyMethods = true; + public boolean m_ignoreDefaultMethods = true; + public boolean m_replaceQualifier = true; + + @Override + @NotNull + public String getDisplayName() { + return InspectionGadgetsBundle.message("method.may.be.static.display.name"); + } + + @Override + @NotNull + protected String buildErrorString(Object... infos) { + return InspectionGadgetsBundle.message("method.may.be.static.problem.descriptor"); + } + + @Override + public BaseInspectionVisitor buildVisitor() { + return new MethodCanBeStaticVisitor(); + } + + @Override + public void writeSettings(@NotNull Element node) throws WriteExternalException { + node.addContent(new Element("option").setAttribute("name", ONLY_PRIVATE_OR_FINAL_ATTR_NAME).setAttribute("value", String.valueOf(m_onlyPrivateOrFinal))); + node.addContent(new Element("option").setAttribute("name", IGNORE_EMPTY_METHODS_ATTR_NAME).setAttribute("value", String.valueOf( + m_ignoreEmptyMethods))); + if (!m_ignoreDefaultMethods) { + node.addContent(new Element("option").setAttribute("name", IGNORE_DEFAULT_METHODS_ATTR_NAME).setAttribute("value", "false")); + } + if (!m_replaceQualifier) { + node.addContent(new Element("option").setAttribute("name", REPLACE_QUALIFIER_ATTR_NAME).setAttribute("value", "false")); + } + } + + private class MethodCanBeStaticVisitor extends BaseInspectionVisitor { + + @Override + public void visitMethod(@NotNull PsiMethod method) { + super.visitMethod(method); + if (method.hasModifierProperty(PsiModifier.STATIC) || + method.hasModifierProperty(PsiModifier.ABSTRACT) || + method.hasModifierProperty(PsiModifier.SYNCHRONIZED) || + method.hasModifierProperty(PsiModifier.NATIVE)) { + return; + } + if (method.isConstructor() || method.getNameIdentifier() == null) { + return; + } + if (m_ignoreDefaultMethods && method.hasModifierProperty(PsiModifier.DEFAULT)) { + return; + } + if (m_ignoreEmptyMethods && MethodUtils.isEmpty(method)) { + return; + } + final PsiClass containingClass = ClassUtils.getContainingClass(method); + if (containingClass == null) { + return; + } + final Condition<PsiElement>[] addins = InspectionManager.CANT_BE_STATIC_EXTENSION.getExtensions(); + for (Condition<PsiElement> addin : addins) { + if (addin.value(method)) { + return; + } + } + final PsiElement scope = containingClass.getScope(); + if (!(scope instanceof PsiJavaFile) && !containingClass.hasModifierProperty(PsiModifier.STATIC) && !containingClass.isInterface()) { + return; + } + if (m_onlyPrivateOrFinal && !method.hasModifierProperty(PsiModifier.FINAL) && !method.hasModifierProperty(PsiModifier.PRIVATE)) { + return; + } + if (isExcluded(method) || MethodUtils.hasSuper(method) || MethodUtils.isOverridden(method)) { + return; + } + if (implementsSurprisingInterface(method)) { + return; + } + final MethodReferenceVisitor visitor = new MethodReferenceVisitor(method); + method.accept(visitor); + if (!visitor.areReferencesStaticallyAccessible()) { + return; + } + registerMethodError(method); + } + + private boolean implementsSurprisingInterface(final PsiMethod method) { + final PsiClass containingClass = method.getContainingClass(); + if (containingClass == null) { + return false; + } + final Query<PsiClass> search = ClassInheritorsSearch.search(containingClass, method.getUseScope(), true, true, false); + final boolean[] result = new boolean[1]; + search.forEach(new Processor<PsiClass>() { + AtomicInteger count = new AtomicInteger(0); + + @Override + public boolean process(PsiClass subClass) { + if (count.incrementAndGet() > 5) { + result[0] = true; + return false; + } + final PsiReferenceList list = subClass.getImplementsList(); + if (list == null) { + return true; + } + final PsiJavaCodeReferenceElement[] referenceElements = list.getReferenceElements(); + for (PsiJavaCodeReferenceElement referenceElement : referenceElements) { + final PsiElement target = referenceElement.resolve(); + if (!(target instanceof PsiClass)) { + result[0] = true; + return false; + } + final PsiClass aClass = (PsiClass)target; + if (!aClass.isInterface()) { + result[0] = true; + return false; + } + if (aClass.findMethodBySignature(method, true) != null) { + result[0] = true; + return false; + } + } + return true; + } + }); + return result[0]; + } + + private boolean isExcluded(PsiMethod method) { + return SerializationUtils.isWriteObject(method) || SerializationUtils.isReadObject(method) || + SerializationUtils.isWriteReplace(method) || SerializationUtils.isReadResolve(method); + } + } +} diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentExcludedVisitor.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentExcludedVisitor.java index 69710a084904..f7778e0a89bc 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentExcludedVisitor.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentExcludedVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2012 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. @@ -44,49 +44,35 @@ class VariablePassedAsArgumentExcludedVisitor extends JavaRecursiveElementVisito } @Override - public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) { + public void visitCallExpression(PsiCallExpression callExpression) { if (passed) { return; } - super.visitMethodCallExpression(call); - final PsiExpressionList argumentList = call.getArgumentList(); - final PsiExpression[] arguments = argumentList.getExpressions(); - for (PsiExpression argument : arguments) { - if (!VariableAccessUtils.mayEvaluateToVariable(argument, variable, myBuilderPattern)) { - continue; - } - final PsiMethod method = call.resolveMethod(); - if (method != null) { - final PsiClass aClass = method.getContainingClass(); - if (aClass != null) { - final String name = aClass.getQualifiedName(); - if (excludes.contains(name)) { - continue; - } - } - } - passed = true; - } + super.visitCallExpression(callExpression); + visitCall(callExpression); } @Override - public void visitNewExpression(@NotNull PsiNewExpression newExpression) { + public void visitEnumConstant(PsiEnumConstant enumConstant) { if (passed) { return; } - super.visitNewExpression(newExpression); - final PsiExpressionList argumentList = newExpression.getArgumentList(); + super.visitEnumConstant(enumConstant); + visitCall(enumConstant); + } + + private void visitCall(PsiCall call) { + final PsiExpressionList argumentList = call.getArgumentList(); if (argumentList == null) { return; } - final PsiExpression[] arguments = argumentList.getExpressions(); - for (PsiExpression argument : arguments) { + for (PsiExpression argument : argumentList.getExpressions()) { if (!VariableAccessUtils.mayEvaluateToVariable(argument, variable, myBuilderPattern)) { continue; } - final PsiMethod constructor = newExpression.resolveConstructor(); - if (constructor != null) { - final PsiClass aClass = constructor.getContainingClass(); + final PsiMethod method = call.resolveMethod(); + if (method != null) { + final PsiClass aClass = method.getContainingClass(); if (aClass != null) { final String name = aClass.getQualifiedName(); if (excludes.contains(name)) { diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentVisitor.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentVisitor.java index 7938fbc5c696..92082cea9e27 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentVisitor.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2011 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. @@ -37,33 +37,29 @@ class VariablePassedAsArgumentVisitor extends JavaRecursiveElementVisitor { } @Override - public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) { + public void visitCallExpression(PsiCallExpression callExpression) { + super.visitCallExpression(callExpression); if (passed) { return; } - super.visitMethodCallExpression(call); - final PsiExpressionList argumentList = call.getArgumentList(); - final PsiExpression[] arguments = argumentList.getExpressions(); - for (PsiExpression argument : arguments) { - if (VariableAccessUtils.mayEvaluateToVariable(argument, variable)) { - passed = true; - break; - } - } + visitCall(callExpression); } @Override - public void visitNewExpression(@NotNull PsiNewExpression newExpression) { + public void visitEnumConstant(PsiEnumConstant enumConstant) { if (passed) { return; } - super.visitNewExpression(newExpression); - final PsiExpressionList argumentList = newExpression.getArgumentList(); + super.visitEnumConstant(enumConstant); + visitCall(enumConstant); + } + + private void visitCall(PsiCall call) { + final PsiExpressionList argumentList = call.getArgumentList(); if (argumentList == null) { return; } - final PsiExpression[] arguments = argumentList.getExpressions(); - for (PsiExpression argument : arguments) { + for (PsiExpression argument : argumentList.getExpressions()) { if (VariableAccessUtils.mayEvaluateToVariable(argument, variable)) { passed = true; break; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstructorInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstructorInspection.java index 126f5021a47f..8b7e23fa1547 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstructorInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstructorInspection.java @@ -15,7 +15,6 @@ */ package com.siyeh.ig.style; -import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.openapi.project.Project; @@ -30,7 +29,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; -public class UnnecessaryConstructorInspection extends BaseInspection implements CleanupLocalInspectionTool { +public class UnnecessaryConstructorInspection extends BaseInspection { @NonNls private static final String SUPER_CALL_TEXT = PsiKeyword.SUPER + "();"; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/MethodMayBeStaticInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/MethodMayBeStaticInspection.java index e73b6cc234d7..5936bb5433a3 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/MethodMayBeStaticInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/MethodMayBeStaticInspection.java @@ -15,62 +15,22 @@ */ package com.siyeh.ig.performance; -import com.intellij.codeInspection.InspectionManager; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.WriteExternalException; -import com.intellij.psi.*; -import com.intellij.psi.search.searches.ClassInheritorsSearch; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiModifier; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.makeStatic.MakeMethodStaticProcessor; import com.intellij.refactoring.makeStatic.Settings; -import com.intellij.util.Processor; -import com.intellij.util.Query; import com.siyeh.InspectionGadgetsBundle; -import com.siyeh.ig.BaseInspection; -import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.fixes.ChangeModifierFix; -import com.siyeh.ig.psiutils.ClassUtils; -import com.siyeh.ig.psiutils.MethodUtils; -import com.siyeh.ig.psiutils.SerializationUtils; -import org.jdom.Element; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import java.util.concurrent.atomic.AtomicInteger; - -public class MethodMayBeStaticInspection extends BaseInspection { - - private static final String IGNORE_DEFAULT_METHODS_ATTR_NAME = "m_ignoreDefaultMethods"; - private static final String ONLY_PRIVATE_OR_FINAL_ATTR_NAME = "m_onlyPrivateOrFinal"; - private static final String IGNORE_EMPTY_METHODS_ATTR_NAME = "m_ignoreEmptyMethods"; - private static final String REPLACE_QUALIFIER_ATTR_NAME = "m_replaceQualifier"; - /** - * @noinspection PublicField - */ - public boolean m_onlyPrivateOrFinal = false; - /** - * @noinspection PublicField - */ - public boolean m_ignoreEmptyMethods = true; - public boolean m_ignoreDefaultMethods = true; - public boolean m_replaceQualifier = true; - - @Override - @NotNull - public String getDisplayName() { - return InspectionGadgetsBundle.message("method.may.be.static.display.name"); - } - - @Override - @NotNull - protected String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message("method.may.be.static.problem.descriptor"); - } +public class MethodMayBeStaticInspection extends MethodMayBeStaticInspectionBase { @Override protected InspectionGadgetsFix buildFix(Object... infos) { return new InspectionGadgetsFix() { @@ -103,122 +63,4 @@ public class MethodMayBeStaticInspection extends BaseInspection { optionsPanel.addCheckbox("Replace qualifier by class name", REPLACE_QUALIFIER_ATTR_NAME); return optionsPanel; } - - @Override - public BaseInspectionVisitor buildVisitor() { - return new MethodCanBeStaticVisitor(); - } - - @Override - public void writeSettings(@NotNull Element node) throws WriteExternalException { - node.addContent(new Element("option").setAttribute("name", ONLY_PRIVATE_OR_FINAL_ATTR_NAME).setAttribute("value", String.valueOf(m_onlyPrivateOrFinal))); - node.addContent(new Element("option").setAttribute("name", IGNORE_EMPTY_METHODS_ATTR_NAME).setAttribute("value", String.valueOf( - m_ignoreEmptyMethods))); - if (!m_ignoreDefaultMethods) { - node.addContent(new Element("option").setAttribute("name", IGNORE_DEFAULT_METHODS_ATTR_NAME).setAttribute("value", "false")); - } - if (!m_replaceQualifier) { - node.addContent(new Element("option").setAttribute("name", REPLACE_QUALIFIER_ATTR_NAME).setAttribute("value", "false")); - } - } - - private class MethodCanBeStaticVisitor extends BaseInspectionVisitor { - - @Override - public void visitMethod(@NotNull PsiMethod method) { - super.visitMethod(method); - if (method.hasModifierProperty(PsiModifier.STATIC) || - method.hasModifierProperty(PsiModifier.ABSTRACT) || - method.hasModifierProperty(PsiModifier.SYNCHRONIZED) || - method.hasModifierProperty(PsiModifier.NATIVE)) { - return; - } - if (method.isConstructor() || method.getNameIdentifier() == null) { - return; - } - if (m_ignoreDefaultMethods && method.hasModifierProperty(PsiModifier.DEFAULT)) { - return; - } - if (m_ignoreEmptyMethods && MethodUtils.isEmpty(method)) { - return; - } - final PsiClass containingClass = ClassUtils.getContainingClass(method); - if (containingClass == null) { - return; - } - final Condition<PsiElement>[] addins = InspectionManager.CANT_BE_STATIC_EXTENSION.getExtensions(); - for (Condition<PsiElement> addin : addins) { - if (addin.value(method)) { - return; - } - } - final PsiElement scope = containingClass.getScope(); - if (!(scope instanceof PsiJavaFile) && !containingClass.hasModifierProperty(PsiModifier.STATIC) && !containingClass.isInterface()) { - return; - } - if (m_onlyPrivateOrFinal && !method.hasModifierProperty(PsiModifier.FINAL) && !method.hasModifierProperty(PsiModifier.PRIVATE)) { - return; - } - if (isExcluded(method) || MethodUtils.hasSuper(method) || MethodUtils.isOverridden(method)) { - return; - } - if (implementsSurprisingInterface(method)) { - return; - } - final MethodReferenceVisitor visitor = new MethodReferenceVisitor(method); - method.accept(visitor); - if (!visitor.areReferencesStaticallyAccessible()) { - return; - } - registerMethodError(method); - } - - private boolean implementsSurprisingInterface(final PsiMethod method) { - final PsiClass containingClass = method.getContainingClass(); - if (containingClass == null) { - return false; - } - final Query<PsiClass> search = ClassInheritorsSearch.search(containingClass, method.getUseScope(), true, true, false); - final boolean[] result = new boolean[1]; - search.forEach(new Processor<PsiClass>() { - AtomicInteger count = new AtomicInteger(0); - - @Override - public boolean process(PsiClass subClass) { - if (count.incrementAndGet() > 5) { - result[0] = true; - return false; - } - final PsiReferenceList list = subClass.getImplementsList(); - if (list == null) { - return true; - } - final PsiJavaCodeReferenceElement[] referenceElements = list.getReferenceElements(); - for (PsiJavaCodeReferenceElement referenceElement : referenceElements) { - final PsiElement target = referenceElement.resolve(); - if (!(target instanceof PsiClass)) { - result[0] = true; - return false; - } - final PsiClass aClass = (PsiClass)target; - if (!aClass.isInterface()) { - result[0] = true; - return false; - } - if (aClass.findMethodBySignature(method, true) != null) { - result[0] = true; - return false; - } - } - return true; - } - }); - return result[0]; - } - - private boolean isExcluded(PsiMethod method) { - return SerializationUtils.isWriteObject(method) || SerializationUtils.isReadObject(method) || - SerializationUtils.isWriteReplace(method) || SerializationUtils.isReadResolve(method); - } - } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java index e79f9df5fa7d..25109cc5f26e 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.style; +import com.intellij.codeInsight.javadoc.JavaDocUtil; import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.diagnostic.Logger; @@ -205,11 +206,8 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection impl return; } final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(reference.getProject()); - if (styleSettings.USE_FQ_CLASS_NAMES_IN_JAVADOC) { - final PsiElement containingComment = PsiTreeUtil.getParentOfType(reference, PsiDocComment.class); - if (containingComment != null) { - return; - } + if (acceptFullyQualifiedNamesInJavadoc(reference, styleSettings)) { + return; } final PsiFile containingFile = reference.getContainingFile(); if (!(containingFile instanceof PsiJavaFile)) { @@ -261,4 +259,14 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection impl } } } + + public static boolean acceptFullyQualifiedNamesInJavadoc(PsiJavaCodeReferenceElement reference, CodeStyleSettings styleSettings) { + final PsiDocComment containingComment = PsiTreeUtil.getParentOfType(reference, PsiDocComment.class); + if (containingComment != null) { + if (styleSettings.USE_FQ_CLASS_NAMES_IN_JAVADOC || JavaDocUtil.isInsidePackageInfo(containingComment)) { + return true; + } + } + return false; + } }
\ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_collection_query_update/MismatchedCollectionQueryUpdate.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_collection_query_update/MismatchedCollectionQueryUpdate.java index 5c53674cd15b..5af84ecb21e7 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_collection_query_update/MismatchedCollectionQueryUpdate.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_collection_query_update/MismatchedCollectionQueryUpdate.java @@ -275,4 +275,18 @@ class SimpleAdd { return null; } +} +class EnumConstant { + private static final List<String> CONSTANT_ARRAY = new ArrayList(); + static { + CONSTANT_ARRAY.add("asdf"); + } + + enum SomeEnum { + ITEM(CONSTANT_ARRAY); // passed as argument + private final List<String> myPatterns; + SomeEnum(List<String> patterns) { + myPatterns = patterns; + } + } }
\ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/MismatchedStringBuilderQueryUpdate.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/MismatchedStringBuilderQueryUpdate.java index c8d9fb80cf19..2274472eb2fa 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/MismatchedStringBuilderQueryUpdate.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/MismatchedStringBuilderQueryUpdate.java @@ -31,3 +31,15 @@ interface List<T> { interface Consumer<T> { void accept(T t); } +class EnumConstant { + private static final StringBuilder sb = new StringBuilder(); + static { + sb.append(""); + } + + enum SomeEnum { + ITEM(sb); // passed as argument + + SomeEnum(StringBuilder sb) {} + } +} diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_statement_with_identical_branches/IfStatementWithIdenticalBranches.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_statement_with_identical_branches/IfStatementWithIdenticalBranches.java index 666651d71e21..fef2e0f1f6ff 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_statement_with_identical_branches/IfStatementWithIdenticalBranches.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_statement_with_identical_branches/IfStatementWithIdenticalBranches.java @@ -162,4 +162,15 @@ class NotADup { private static String placeOrder(int i, Object o) { return null; } + + void m() { + int j; + <warning descr="'if' statement with identical branches">if</warning> (true) { + j = 2; + } + else { + j = 2; + } + System.out.println("j = " + j); + } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.after.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.after.java index 032fa0002dea..a161e388ce3b 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.after.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.after.java @@ -117,4 +117,18 @@ class TryIdenticalCatches { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } + + public static void main() { + Throwable causeException; + try { + throw new NullPointerException(); + } catch (final NullPointerException e) { + causeException = e; + } catch (final IllegalArgumentException e) { + causeException = e; + } catch (final IndexOutOfBoundsException e) { + causeException = e; + } + System.out.println("causeException = " + causeException); + } }
\ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.java index 5d33c50de89e..09694491d69d 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.java @@ -120,4 +120,18 @@ class TryIdenticalCatches { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } + + public static void main() { + Throwable causeException; + try { + throw new NullPointerException(); + } catch (final NullPointerException e) { + causeException = e; + } <warning descr="catch branch identical to 'NullPointerException' branch">catch (final IllegalArgumentException e)</warning> { + causeException = e; + } <warning descr="catch branch identical to 'NullPointerException' branch">catch (final IndexOutOfBoundsException e)</warning> { + causeException = e; + } + System.out.println("causeException = " + causeException); + } }
\ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/implicit_default_charset_usage/ImplicitDefaultCharsetUsage.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/implicit_default_charset_usage/ImplicitDefaultCharsetUsage.java index 17dd59eadf7a..151042fa3ed9 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/implicit_default_charset_usage/ImplicitDefaultCharsetUsage.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/implicit_default_charset_usage/ImplicitDefaultCharsetUsage.java @@ -1,6 +1,9 @@ package com.siyeh.igtest.internationalization.implicit_default_charset_usage; import java.io.*; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; import java.util.ArrayList; import java.util.Formatter; import java.util.Locale; @@ -37,4 +40,12 @@ class ImplicitDefaultCharsetUsage { new Scanner("string input"); new ArrayList(10); } + + void charsetEnAndDecoders(InputStream inputStream, OutputStream outputStream) throws IOException { + final Charset cs = Charset.forName("UTF-8"); + CharsetDecoder cd = cs.newDecoder(); + InputStreamReader is = new InputStreamReader(inputStream, cd); + CharsetEncoder ce = cs.newEncoder(); + final OutputStreamWriter ow = new OutputStreamWriter(outputStream, ce); + } }
\ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/logging/logger_initialized_with_foreign_class/LoggerInitializedWithForeignClass.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/logging/logger_initialized_with_foreign_class/LoggerInitializedWithForeignClass.java new file mode 100644 index 000000000000..b252b8af1cd3 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/logging/logger_initialized_with_foreign_class/LoggerInitializedWithForeignClass.java @@ -0,0 +1,13 @@ +import java.util.logging.*; + +class LoggerInitializedWithForeignClass { + + void foo() { + new Object() { + void bar() { + Logger.getLogger(LoggerInitializedWithForeignClass.class.getName()); + Logger.getLogger(<warning descr="Logger initialized with foreign class 'String.class'">String.class</warning>.getName()); + } + }; + } +}
\ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fully_qualified_name/test1/package-info.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fully_qualified_name/test1/package-info.java new file mode 100644 index 000000000000..01825303d455 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fully_qualified_name/test1/package-info.java @@ -0,0 +1,3 @@ +/** + * {@link java.util.Map(java.util.function.BiConsumer)} +*/
\ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspectionTest.java index 78822492b4bc..312e08aebcc3 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspectionTest.java @@ -16,13 +16,22 @@ package com.siyeh.ig.internationalization; import com.intellij.codeInspection.InspectionProfileEntry; +import com.intellij.testFramework.LightProjectDescriptor; import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.NotNull; /** * @author Bas Leijdekkers */ public class ImplicitDefaultCharsetUsageInspectionTest extends LightInspectionTestCase { + + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return JAVA_8; + } + @Override protected InspectionProfileEntry getInspection() { return new ImplicitDefaultCharsetUsageInspection(); diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionTest.java new file mode 100644 index 000000000000..7f0b521fcf4e --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionTest.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.logging; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.Nullable; + +/** + * @author Bas Leijdekkers + */ +public class LoggerInitializedWithForeignClassInspectionTest extends LightInspectionTestCase { + + public void testLoggerInitializedWithForeignClass() { + doTest(); + } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + final LoggerInitializedWithForeignClassInspection inspection = new LoggerInitializedWithForeignClassInspection(); + inspection.loggerFactoryClassNames.add("java.util.logging.Logger"); + inspection.loggerFactoryMethodNames.add("getLogger"); + return inspection; + } + + @Override + protected String[] getEnvironmentClasses() { + return new String[] { + "package java.util.logging;" + + "public class Logger {" + + " public static Logger getLogger(String name) {" + + " return null;" + + " }" + + "}" + }; + } +} diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspectionTest.java index 1bd7feadae45..48d120189740 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspectionTest.java @@ -32,7 +32,7 @@ public class PlaceholderCountMatchesArgumentCountInspectionTest extends LightIns "class X {\n" + " void foo() {\n" + " Logger logger = LoggerFactory.getLogger(X.class);\n" + - " logger./*'info()' call has fewer arguments (1) than placeholders (2)*/info/**/(\"string {}{}\", 1);\n" + + " logger.info(/*Fewer arguments provided (1) than placeholders specified (2) in 'string {}{}'*/\"string {}{}\"/**/, 1);\n" + " }\n" + "}" ); @@ -43,7 +43,7 @@ public class PlaceholderCountMatchesArgumentCountInspectionTest extends LightIns "class X {\n" + " void foo() {\n" + " Logger logger = LoggerFactory.getLogger(X.class);\n" + - " logger./*'info()' call has more arguments (1) than placeholders (0)*/info/**/(\"string\", 1);\n" + + " logger.info(/*More arguments provided (1) than placeholders specified (0) in 'string'*/\"string\"/**/, 1);\n" + " }\n" + "}" ); @@ -107,4 +107,15 @@ public class PlaceholderCountMatchesArgumentCountInspectionTest extends LightIns " }" + "}"); } + + public void testConstant() { + doTest("import org.slf4j.*;" + + "class X {" + + " Logger LOG = LoggerFactory.getLogger(X.class);" + + " private static final String message = \"HELLO {}\";" + + " void m() {" + + " LOG.info(/*Fewer arguments provided (0) than placeholders specified (1) in 'HELLO {}'*/message/**/);" + + " }" + + "}"); + } }
\ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java index 6c5a89009735..2e1b839c85d3 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java @@ -1,11 +1,22 @@ package com.siyeh.ig.style; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.siyeh.ig.IGInspectionTestCase; public class UnnecessaryFullyQualifiedNameInspectionTest extends IGInspectionTestCase { public void test() throws Exception { - doTest("com/siyeh/igtest/style/unnecessary_fully_qualified_name", - new UnnecessaryFullyQualifiedNameInspection()); + final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(getProject()); + + boolean inJavadoc = styleSettings.USE_FQ_CLASS_NAMES_IN_JAVADOC; + try { + styleSettings.USE_FQ_CLASS_NAMES_IN_JAVADOC = false; + doTest("com/siyeh/igtest/style/unnecessary_fully_qualified_name", + new UnnecessaryFullyQualifiedNameInspection()); + } + finally { + styleSettings.USE_FQ_CLASS_NAMES_IN_JAVADOC = inJavadoc; + } } } diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.form b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.form index 9aba68ac9b46..b894b8ced19b 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.form +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.form @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.intellij.plugins.intelliLang.AdvancedSettingsUI"> +<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.intellij.plugins.intelliLang.AdvancedSettingsUI.AdvancedSettingsPanel"> <grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="6" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="5" left="8" bottom="5" right="8"/> <constraints> diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.java index e9083b065605..adb4b51057a8 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.java @@ -44,166 +44,36 @@ import java.util.Arrays; */ public class AdvancedSettingsUI implements SearchableConfigurable { private final Configuration.AdvancedConfiguration myConfiguration; - - @SuppressWarnings({"UnusedDeclaration", "FieldCanBeLocal"}) - private JPanel myRoot; - - private JRadioButton myNoInstrumentation; - private JRadioButton myAssertInstrumentation; - private JRadioButton myExceptionInstrumentation; - private JPanel myLanguageAnnotationPanel; - private JPanel myPatternAnnotationPanel; - private JPanel mySubstAnnotationPanel; - private JRadioButton myDfaOff; - private JRadioButton myAnalyzeReferences; - private JRadioButton myUseDfa; - private JRadioButton myLookForAssignments; - private JCheckBox myIncludeUncomputableOperandsAsCheckBox; - private JCheckBox mySourceModificationAllowedCheckBox; - - private final ReferenceEditorWithBrowseButton myAnnotationField; - private final ReferenceEditorWithBrowseButton myPatternField; - private final ReferenceEditorWithBrowseButton mySubstField; + private AdvancedSettingsPanel myPanel; + private final Project myProject; public AdvancedSettingsUI(@NotNull final Project project, Configuration configuration) { + myProject = project; myConfiguration = configuration.getAdvancedConfiguration(); - - myAnnotationField = new ReferenceEditorWithBrowseButton(null, project, new Function<String, Document>() { - public Document fun(String s) { - return PsiUtilEx.createDocument(s, project); - } - }, myConfiguration.getLanguageAnnotationClass()); - myAnnotationField.addActionListener(new BrowseClassListener(project, myAnnotationField)); - myAnnotationField.setEnabled(!project.isDefault()); - addField(myLanguageAnnotationPanel, myAnnotationField); - - myPatternField = new ReferenceEditorWithBrowseButton(null, project, new Function<String, Document>() { - public Document fun(String s) { - return PsiUtilEx.createDocument(s, project); - } - }, myConfiguration.getPatternAnnotationClass()); - myPatternField.addActionListener(new BrowseClassListener(project, myPatternField)); - myPatternField.setEnabled(!project.isDefault()); - addField(myPatternAnnotationPanel, myPatternField); - - mySubstField = new ReferenceEditorWithBrowseButton(null, project, new Function<String, Document>() { - public Document fun(String s) { - return PsiUtilEx.createDocument(s, project); - } - }, myConfiguration.getPatternAnnotationClass()); - mySubstField.addActionListener(new BrowseClassListener(project, mySubstField)); - mySubstField.setEnabled(!project.isDefault()); - addField(mySubstAnnotationPanel, mySubstField); - } - // - /** - * Adds textfield into placeholder panel and assigns a directly preceding label - */ - private static void addField(JPanel panel, ReferenceEditorWithBrowseButton field) { - panel.add(field, BorderLayout.CENTER); - - final Component[] components = panel.getParent().getComponents(); - final int index = Arrays.asList(components).indexOf(panel); - if (index > 0) { - final Component component = components[index - 1]; - if (component instanceof JLabel) { - ((JLabel)component).setLabelFor(field); - } - } } public JComponent createComponent() { - return myRoot; - } - - @SuppressWarnings({"SimplifiableIfStatement"}) - public boolean isModified() { - if (getInstrumentation() != myConfiguration.getInstrumentation()) { - return true; - } - if (!myAnnotationField.getText().equals(myConfiguration.getLanguageAnnotationClass())) { - return true; - } - if (!myPatternField.getText().equals(myConfiguration.getPatternAnnotationClass())) { - return true; - } - if (!mySubstField.getText().equals(myConfiguration.getSubstAnnotationClass())) { - return true; - } - if (!myConfiguration.getDfaOption().equals(getDfaOption())) { - return true; - } - if (myConfiguration.isIncludeUncomputablesAsLiterals() != myIncludeUncomputableOperandsAsCheckBox.isSelected()) { - return true; - } - if (myConfiguration.isSourceModificationAllowed() != mySourceModificationAllowedCheckBox.isSelected()) { - return true; - } - return false; - } - - @NotNull - private Configuration.InstrumentationType getInstrumentation() { - if (myNoInstrumentation.isSelected()) return Configuration.InstrumentationType.NONE; - if (myAssertInstrumentation.isSelected()) return Configuration.InstrumentationType.ASSERT; - if (myExceptionInstrumentation.isSelected()) return Configuration.InstrumentationType.EXCEPTION; - - assert false; - return null; + myPanel = new AdvancedSettingsPanel(); + return myPanel.myRoot; } + @Override public void apply() throws ConfigurationException { - myConfiguration.setInstrumentationType(getInstrumentation()); - myConfiguration.setLanguageAnnotation(myAnnotationField.getText()); - myConfiguration.setPatternAnnotation(myPatternField.getText()); - myConfiguration.setSubstAnnotation(mySubstField.getText()); - - myConfiguration.setDfaOption(getDfaOption()); - myConfiguration.setIncludeUncomputablesAsLiterals(myIncludeUncomputableOperandsAsCheckBox.isSelected()); - myConfiguration.setSourceModificationAllowed(mySourceModificationAllowedCheckBox.isSelected()); + myPanel.apply(); } - @NotNull - private Configuration.DfaOption getDfaOption() { - if (myDfaOff.isSelected()) return Configuration.DfaOption.OFF; - if (myAnalyzeReferences.isSelected()) return Configuration.DfaOption.RESOLVE; - if (myLookForAssignments.isSelected()) return Configuration.DfaOption.ASSIGNMENTS; - if (myUseDfa.isSelected()) return Configuration.DfaOption.DFA; - return Configuration.DfaOption.OFF; + @Override + public boolean isModified() { + return myPanel.isModified(); } + @Override public void reset() { - myAnnotationField.setText(myConfiguration.getLanguageAnnotationClass()); - myPatternField.setText(myConfiguration.getPatternAnnotationClass()); - mySubstField.setText(myConfiguration.getSubstAnnotationClass()); - - myNoInstrumentation.setSelected(myConfiguration.getInstrumentation() == Configuration.InstrumentationType.NONE); - myAssertInstrumentation.setSelected(myConfiguration.getInstrumentation() == Configuration.InstrumentationType.ASSERT); - myExceptionInstrumentation.setSelected(myConfiguration.getInstrumentation() == Configuration.InstrumentationType.EXCEPTION); - - setDfaOption(myConfiguration.getDfaOption()); - myIncludeUncomputableOperandsAsCheckBox.setSelected(myConfiguration.isIncludeUncomputablesAsLiterals()); - mySourceModificationAllowedCheckBox.setSelected(myConfiguration.isSourceModificationAllowed()); - } - - private void setDfaOption(@NotNull final Configuration.DfaOption dfaOption) { - switch (dfaOption) { - case OFF: - myDfaOff.setSelected(true); - break; - case RESOLVE: - myAnalyzeReferences.setSelected(true); - break; - case ASSIGNMENTS: - myLookForAssignments.setSelected(true); - break; - case DFA: - myUseDfa.setSelected(true); - break; - } + myPanel.reset(); } public void disposeUIResources() { + myPanel = null; } @Nls @@ -255,4 +125,160 @@ public class AdvancedSettingsUI implements SearchableConfigurable { } } } + + public class AdvancedSettingsPanel { + @SuppressWarnings({"UnusedDeclaration", "FieldCanBeLocal"}) + private JPanel myRoot; + + private JRadioButton myNoInstrumentation; + private JRadioButton myAssertInstrumentation; + private JRadioButton myExceptionInstrumentation; + private JPanel myLanguageAnnotationPanel; + private JPanel myPatternAnnotationPanel; + private JPanel mySubstAnnotationPanel; + private JRadioButton myDfaOff; + private JRadioButton myAnalyzeReferences; + private JRadioButton myUseDfa; + private JRadioButton myLookForAssignments; + private JCheckBox myIncludeUncomputableOperandsAsCheckBox; + private JCheckBox mySourceModificationAllowedCheckBox; + + private final ReferenceEditorWithBrowseButton myAnnotationField; + private final ReferenceEditorWithBrowseButton myPatternField; + private final ReferenceEditorWithBrowseButton mySubstField; + + public AdvancedSettingsPanel() { + myAnnotationField = new ReferenceEditorWithBrowseButton(null, myProject, new Function<String, Document>() { + public Document fun(String s) { + return PsiUtilEx.createDocument(s, myProject); + } + }, myConfiguration.getLanguageAnnotationClass()); + myAnnotationField.addActionListener(new BrowseClassListener(myProject, myAnnotationField)); + myAnnotationField.setEnabled(!myProject.isDefault()); + addField(myLanguageAnnotationPanel, myAnnotationField); + + myPatternField = new ReferenceEditorWithBrowseButton(null, myProject, new Function<String, Document>() { + public Document fun(String s) { + return PsiUtilEx.createDocument(s, myProject); + } + }, myConfiguration.getPatternAnnotationClass()); + myPatternField.addActionListener(new BrowseClassListener(myProject, myPatternField)); + myPatternField.setEnabled(!myProject.isDefault()); + addField(myPatternAnnotationPanel, myPatternField); + + mySubstField = new ReferenceEditorWithBrowseButton(null, myProject, new Function<String, Document>() { + public Document fun(String s) { + return PsiUtilEx.createDocument(s, myProject); + } + }, myConfiguration.getPatternAnnotationClass()); + mySubstField.addActionListener(new BrowseClassListener(myProject, mySubstField)); + mySubstField.setEnabled(!myProject.isDefault()); + addField(mySubstAnnotationPanel, mySubstField); + } + // + + /** + * Adds textfield into placeholder panel and assigns a directly preceding label + */ + private void addField(JPanel panel, ReferenceEditorWithBrowseButton field) { + panel.add(field, BorderLayout.CENTER); + + final Component[] components = panel.getParent().getComponents(); + final int index = Arrays.asList(components).indexOf(panel); + if (index > 0) { + final Component component = components[index - 1]; + if (component instanceof JLabel) { + ((JLabel)component).setLabelFor(field); + } + } + } + + + @SuppressWarnings({"SimplifiableIfStatement"}) + public boolean isModified() { + if (getInstrumentation() != myConfiguration.getInstrumentation()) { + return true; + } + if (!myAnnotationField.getText().equals(myConfiguration.getLanguageAnnotationClass())) { + return true; + } + if (!myPatternField.getText().equals(myConfiguration.getPatternAnnotationClass())) { + return true; + } + if (!mySubstField.getText().equals(myConfiguration.getSubstAnnotationClass())) { + return true; + } + if (!myConfiguration.getDfaOption().equals(getDfaOption())) { + return true; + } + if (myConfiguration.isIncludeUncomputablesAsLiterals() != myIncludeUncomputableOperandsAsCheckBox.isSelected()) { + return true; + } + if (myConfiguration.isSourceModificationAllowed() != mySourceModificationAllowedCheckBox.isSelected()) { + return true; + } + return false; + } + + @NotNull + private Configuration.InstrumentationType getInstrumentation() { + if (myNoInstrumentation.isSelected()) return Configuration.InstrumentationType.NONE; + if (myAssertInstrumentation.isSelected()) return Configuration.InstrumentationType.ASSERT; + if (myExceptionInstrumentation.isSelected()) return Configuration.InstrumentationType.EXCEPTION; + + assert false; + return null; + } + + public void apply() throws ConfigurationException { + myConfiguration.setInstrumentationType(getInstrumentation()); + myConfiguration.setLanguageAnnotation(myAnnotationField.getText()); + myConfiguration.setPatternAnnotation(myPatternField.getText()); + myConfiguration.setSubstAnnotation(mySubstField.getText()); + + myConfiguration.setDfaOption(getDfaOption()); + myConfiguration.setIncludeUncomputablesAsLiterals(myIncludeUncomputableOperandsAsCheckBox.isSelected()); + myConfiguration.setSourceModificationAllowed(mySourceModificationAllowedCheckBox.isSelected()); + } + + @NotNull + private Configuration.DfaOption getDfaOption() { + if (myDfaOff.isSelected()) return Configuration.DfaOption.OFF; + if (myAnalyzeReferences.isSelected()) return Configuration.DfaOption.RESOLVE; + if (myLookForAssignments.isSelected()) return Configuration.DfaOption.ASSIGNMENTS; + if (myUseDfa.isSelected()) return Configuration.DfaOption.DFA; + return Configuration.DfaOption.OFF; + } + + public void reset() { + myAnnotationField.setText(myConfiguration.getLanguageAnnotationClass()); + myPatternField.setText(myConfiguration.getPatternAnnotationClass()); + mySubstField.setText(myConfiguration.getSubstAnnotationClass()); + + myNoInstrumentation.setSelected(myConfiguration.getInstrumentation() == Configuration.InstrumentationType.NONE); + myAssertInstrumentation.setSelected(myConfiguration.getInstrumentation() == Configuration.InstrumentationType.ASSERT); + myExceptionInstrumentation.setSelected(myConfiguration.getInstrumentation() == Configuration.InstrumentationType.EXCEPTION); + + setDfaOption(myConfiguration.getDfaOption()); + myIncludeUncomputableOperandsAsCheckBox.setSelected(myConfiguration.isIncludeUncomputablesAsLiterals()); + mySourceModificationAllowedCheckBox.setSelected(myConfiguration.isSourceModificationAllowed()); + } + + private void setDfaOption(@NotNull final Configuration.DfaOption dfaOption) { + switch (dfaOption) { + case OFF: + myDfaOff.setSelected(true); + break; + case RESOLVE: + myAnalyzeReferences.setSelected(true); + break; + case ASSIGNMENTS: + myLookForAssignments.setSelected(true); + break; + case DFA: + myUseDfa.setSelected(true); + break; + } + } + } } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/fqnames/FullyQualifiedNamePredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/fqnames/FullyQualifiedNamePredicate.java index 5342b62db4b9..b09afbb3d776 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/fqnames/FullyQualifiedNamePredicate.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/fqnames/FullyQualifiedNamePredicate.java @@ -21,6 +21,7 @@ import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.util.PsiTreeUtil; import com.siyeh.ig.psiutils.ImportUtils; +import com.siyeh.ig.style.UnnecessaryFullyQualifiedNameInspection; import com.siyeh.ipp.base.PsiElementPredicate; class FullyQualifiedNamePredicate implements PsiElementPredicate { @@ -40,6 +41,11 @@ class FullyQualifiedNamePredicate implements PsiElementPredicate { if (PsiTreeUtil.getParentOfType(element, PsiImportStatementBase.class, PsiPackageStatement.class, JavaCodeFragment.class) != null) { return false; } + final Project project = element.getProject(); + final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project); + if (UnnecessaryFullyQualifiedNameInspection.acceptFullyQualifiedNamesInJavadoc(referenceElement, codeStyleSettings)) { + return false; + } final PsiElement qualifier = referenceElement.getQualifier(); if (!(qualifier instanceof PsiJavaCodeReferenceElement)) { return false; @@ -50,8 +56,6 @@ class FullyQualifiedNamePredicate implements PsiElementPredicate { if (!(resolved instanceof PsiClass)) { return false; } - final Project project = element.getProject(); - final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project); if (!codeStyleSettings.INSERT_INNER_CLASS_IMPORTS) { return false; } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntention.java index 33778f99d931..3bbc7a63bd65 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2011 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. @@ -18,7 +18,7 @@ package com.siyeh.ipp.initialization; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; -import com.intellij.util.IncorrectOperationException; +import com.intellij.refactoring.util.RefactoringUtil; import com.siyeh.IntentionPowerPackBundle; import com.siyeh.ipp.base.Intention; import com.siyeh.ipp.base.PsiElementPredicate; @@ -35,28 +35,14 @@ public class SplitDeclarationAndInitializationIntention extends Intention { } @Override - public void processIntention(@NotNull PsiElement element) - throws IncorrectOperationException { + public void processIntention(@NotNull PsiElement element) { final PsiField field = (PsiField)element.getParent(); field.normalizeDeclaration(); - final PsiExpression initializer = field.getInitializer(); + final PsiExpression initializer = RefactoringUtil.convertInitializerToNormalExpression(field.getInitializer(), field.getType()); if (initializer == null) { return; } - final String initializerText; - if (initializer instanceof PsiArrayInitializerExpression) { - final PsiType type = initializer.getType(); - if (type == null) { - initializerText = initializer.getText(); - } - else { - initializerText = "new " + type.getCanonicalText() + - initializer.getText(); - } - } - else { - initializerText = initializer.getText(); - } + final String initializerText = initializer.getText(); final PsiClass containingClass = field.getContainingClass(); if (containingClass == null) { return; diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/initialization/ArrayInitializer.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/initialization/ArrayInitializer.java new file mode 100644 index 000000000000..54eaa025b8e8 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/initialization/ArrayInitializer.java @@ -0,0 +1,3 @@ +class X { + String s <caret>= {}; +}
\ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/initialization/ArrayInitializer_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/initialization/ArrayInitializer_after.java new file mode 100644 index 000000000000..08ebd41e6f93 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/initialization/ArrayInitializer_after.java @@ -0,0 +1,7 @@ +class X { + String s; + + { + s = {}; + } +}
\ No newline at end of file diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntentionTest.java new file mode 100644 index 000000000000..63ac3c9acf9f --- /dev/null +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntentionTest.java @@ -0,0 +1,38 @@ +/* + * 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.ipp.initialization; + +import com.siyeh.IntentionPowerPackBundle; +import com.siyeh.ipp.IPPTestCase; + +/** + * @see com.siyeh.ipp.initialization.SplitDeclarationAndInitializationIntention + * @author Bas Leijdekkers + */ +public class SplitDeclarationAndInitializationIntentionTest extends IPPTestCase { + + public void testArrayInitializer() { doTest(); } + + @Override + protected String getRelativePath() { + return "initialization"; + } + + @Override + protected String getIntentionName() { + return IntentionPowerPackBundle.message("split.declaration.and.initialization.intention.name"); + } +} diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntToolWindowFactory.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntToolWindowFactory.java index 4aa217f789bc..02d8f0696e7f 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntToolWindowFactory.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntToolWindowFactory.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. @@ -22,13 +22,14 @@ import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowFactory; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentManager; +import org.jetbrains.annotations.NotNull; /** * @author yole */ public class AntToolWindowFactory implements ToolWindowFactory { @Override - public void createToolWindowContent(Project project, ToolWindow toolWindow) { + public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) { AntExplorer explorer = new AntExplorer(project); final ContentManager contentManager = toolWindow.getContentManager(); final Content content = contentManager.getFactory().createContent(explorer, null, false); diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProperty.java b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProperty.java index 2ef2ddb9737b..3e60d22711d2 100644 --- a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProperty.java +++ b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProperty.java @@ -16,11 +16,13 @@ package com.intellij.lang.ant.dom; import com.intellij.lang.properties.IProperty; +import com.intellij.lang.properties.PropertiesImplUtil; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.util.io.FileUtil; import com.intellij.pom.references.PomService; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileSystemItem; import com.intellij.util.PathUtil; import com.intellij.util.containers.HashMap; @@ -131,8 +133,9 @@ public abstract class AntDomProperty extends AntDomClasspathComponent implements } _propertyName = propertyName.substring(prefix.length()); } - if (psiFile instanceof PropertiesFile) { - final IProperty property = ((PropertiesFile)psiFile).findPropertyByKey(_propertyName); + final PropertiesFile pf = toPropertiesFile(psiFile); + if (pf != null) { + final IProperty property = pf.findPropertyByKey(_propertyName); return property != null? property.getPsiElement() : null; } } @@ -185,9 +188,10 @@ public abstract class AntDomProperty extends AntDomClasspathComponent implements else { // name attrib is not specified final PsiFileSystemItem psiFile = getFile().getValue(); if (psiFile != null) { - if (psiFile instanceof PropertiesFile) { + final PropertiesFile file = toPropertiesFile(psiFile); + if (file != null) { result = new HashMap<String, String>(); - for (final IProperty property : ((PropertiesFile)psiFile).getProperties()) { + for (final IProperty property : file.getProperties()) { result.put(property.getUnescapedKey(), property.getUnescapedValue()); } } @@ -212,6 +216,7 @@ public abstract class AntDomProperty extends AntDomClasspathComponent implements final InputStream stream = loader.getResourceAsStream(resource); if (stream != null) { try { + // todo: Remote file can be XmlPropertiesFile final PropertiesFile propFile = (PropertiesFile)CustomAntElementsRegistry.loadContentAsFile(getXmlTag().getProject(), stream, StdFileTypes.PROPERTIES); result = new HashMap<String, String>(); for (final IProperty property : propFile.getProperties()) { @@ -255,4 +260,17 @@ public abstract class AntDomProperty extends AntDomClasspathComponent implements return loader; } + @Nullable + public PropertiesFile getPropertiesFile() { + return toPropertiesFile(getFile().getValue()); + } + + @Nullable + private static PropertiesFile toPropertiesFile(@Nullable final PsiFileSystemItem item) { + if (item instanceof PropertiesFile) { + return (PropertiesFile)item; + } + // Sometimes XmlPropertiesFile is just XmlFile, sao we should ask PropertiesImplUtil about that. + return item instanceof PsiFile? PropertiesImplUtil.getPropertiesFile(((PsiFile)item)) : null; + } } diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/AntResolveInspection.java b/plugins/ant/src/com/intellij/lang/ant/dom/AntResolveInspection.java index b17f29ae11ac..838d69af8027 100644 --- a/plugins/ant/src/com/intellij/lang/ant/dom/AntResolveInspection.java +++ b/plugins/ant/src/com/intellij/lang/ant/dom/AntResolveInspection.java @@ -25,7 +25,6 @@ import com.intellij.lang.ant.quickfix.AntCreateTargetFix; import com.intellij.lang.ant.validation.AntInspection; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiFileSystemItem; import com.intellij.psi.PsiPolyVariantReference; import com.intellij.psi.PsiReference; import com.intellij.psi.xml.XmlElement; @@ -175,9 +174,9 @@ public class AntResolveInspection extends AntInspection { } if (child instanceof AntDomProperty) { final AntDomProperty property = (AntDomProperty)child; - final PsiFileSystemItem file = property.getFile().getValue(); - if (file instanceof PropertiesFile) { - files.add((PropertiesFile)file); + final PropertiesFile file = property.getPropertiesFile(); + if (file != null) { + files.add(file); } } } diff --git a/plugins/ant/src/com/intellij/lang/ant/validation/AntMissingPropertiesFileInspection.java b/plugins/ant/src/com/intellij/lang/ant/validation/AntMissingPropertiesFileInspection.java index b434b1bfc4d4..4e7ac458d6cb 100644 --- a/plugins/ant/src/com/intellij/lang/ant/validation/AntMissingPropertiesFileInspection.java +++ b/plugins/ant/src/com/intellij/lang/ant/validation/AntMissingPropertiesFileInspection.java @@ -18,8 +18,11 @@ package com.intellij.lang.ant.validation; import com.intellij.lang.ant.AntBundle; import com.intellij.lang.ant.dom.AntDomProperty; import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileSystemItem; +import com.intellij.psi.xml.XmlFile; import com.intellij.util.xml.DomElement; +import com.intellij.util.xml.GenericAttributeValue; import com.intellij.util.xml.highlighting.DomElementAnnotationHolder; import com.intellij.util.xml.highlighting.DomHighlightingHelper; import org.jetbrains.annotations.Nls; @@ -45,11 +48,21 @@ public class AntMissingPropertiesFileInspection extends AntInspection { protected void checkDomElement(DomElement element, DomElementAnnotationHolder holder, DomHighlightingHelper helper) { if (element instanceof AntDomProperty) { final AntDomProperty property = (AntDomProperty)element; - final String fileName = property.getFile().getStringValue(); + final GenericAttributeValue<PsiFileSystemItem> fileValue = property.getFile(); + final String fileName = fileValue.getStringValue(); if (fileName != null) { - final PsiFileSystemItem file = property.getFile().getValue(); - if (!(file instanceof PropertiesFile)) { - holder.createProblem(property.getFile(), AntBundle.message("file.doesnt.exist", fileName)); + final PropertiesFile propertiesFile = property.getPropertiesFile(); + if (propertiesFile == null) { + final PsiFileSystemItem file = fileValue.getValue(); + if (file instanceof XmlFile) { + holder.createProblem(fileValue, AntBundle.message("file.type.xml.not.supported", fileName)); + } + else if (file instanceof PsiFile) { + holder.createProblem(fileValue, AntBundle.message("file.type.not.supported", fileName)); + } + else { + holder.createProblem(fileValue, AntBundle.message("file.doesnt.exist", fileName)); + } } } } diff --git a/plugins/commander/src/com/intellij/ide/commander/CommanderToolWindowFactory.java b/plugins/commander/src/com/intellij/ide/commander/CommanderToolWindowFactory.java index 1449ed0d32f1..11c3e596bc4d 100644 --- a/plugins/commander/src/com/intellij/ide/commander/CommanderToolWindowFactory.java +++ b/plugins/commander/src/com/intellij/ide/commander/CommanderToolWindowFactory.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. @@ -19,12 +19,13 @@ import com.intellij.openapi.wm.ToolWindowFactory; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.project.Project; import com.intellij.ui.content.ContentFactory; +import org.jetbrains.annotations.NotNull; /** * @author yole */ public class CommanderToolWindowFactory implements ToolWindowFactory { - public void createToolWindowContent(Project project, ToolWindow toolWindow) { + public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) { Commander commander = Commander.getInstance(project); toolWindow.getContentManager().addContent(ContentFactory.SERVICE.getInstance().createContent(commander, "", false)); } diff --git a/plugins/editorconfig/LICENSE.txt b/plugins/editorconfig/LICENSE.txt new file mode 100644 index 000000000000..fff944099438 --- /dev/null +++ b/plugins/editorconfig/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Kevin Bell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.
\ No newline at end of file diff --git a/plugins/editorconfig/editorconfig.iml b/plugins/editorconfig/editorconfig.iml new file mode 100644 index 000000000000..8d67b1cc8c76 --- /dev/null +++ b/plugins/editorconfig/editorconfig.iml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module relativePaths="true" type="JAVA_MODULE" version="4"> + <component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/META-INF/plugin.xml" /> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="module-library"> + <library> + <CLASSES> + <root url="jar://$MODULE_DIR$/lib/editorconfig-core-java.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES> + <root url="jar://$MODULE_DIR$/lib/editorconfig-core-java.jar!/" /> + </SOURCES> + </library> + </orderEntry> + <orderEntry type="module" module-name="core-api" /> + <orderEntry type="module" module-name="platform-api" /> + <orderEntry type="module" module-name="platform-impl" /> + <orderEntry type="module" module-name="lang-api" /> + </component> +</module> + diff --git a/plugins/editorconfig/lib/editorconfig-core-java.jar b/plugins/editorconfig/lib/editorconfig-core-java.jar Binary files differnew file mode 100644 index 000000000000..f115b7480336 --- /dev/null +++ b/plugins/editorconfig/lib/editorconfig-core-java.jar diff --git a/plugins/editorconfig/src/META-INF/plugin.xml b/plugins/editorconfig/src/META-INF/plugin.xml new file mode 100644 index 000000000000..2be8eb4f5473 --- /dev/null +++ b/plugins/editorconfig/src/META-INF/plugin.xml @@ -0,0 +1,30 @@ +<idea-plugin version="2"> + <id>org.editorconfig.editorconfigjetbrains</id> + <name>EditorConfig</name> + <version>1.0</version> + <vendor url="http://editorconfig.org">Kevin Bell, JetBrains</vendor> + + <description><![CDATA[ + A JetBrains IDE plugin supporting the EditorConfig standard + ]]></description> + + <idea-version since-build="138.1293"/> + + <depends>com.intellij.modules.lang</depends> + + <application-components> + <component> + <implementation-class>org.editorconfig.plugincomponents.SettingsProviderComponent</implementation-class> + </component> + </application-components> + + <project-components> + <component> + <implementation-class>org.editorconfig.plugincomponents.ConfigProjectComponent</implementation-class> + </component> + </project-components> + + <extensions defaultExtensionNs="com.intellij"> + <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/> + </extensions> +</idea-plugin>
\ No newline at end of file diff --git a/plugins/editorconfig/src/org/editorconfig/Utils.java b/plugins/editorconfig/src/org/editorconfig/Utils.java new file mode 100644 index 000000000000..f64d7be34d85 --- /dev/null +++ b/plugins/editorconfig/src/org/editorconfig/Utils.java @@ -0,0 +1,24 @@ +package org.editorconfig; + +import org.editorconfig.core.EditorConfig.OutPair; + +import java.util.List; + +public class Utils { + public static String configValueForKey(List<OutPair> outPairs, String key) { + for (OutPair outPair : outPairs) { + if (outPair.getKey().equals(key)) { + return outPair.getVal(); + } + } + return ""; + } + + public static String invalidConfigMessage(String configValue, String configKey, String filePath) { + return "\"" + configValue + "\" is not a valid value for " + configKey + " for file " + filePath; + } + + public static String appliedConfigMessage(String configValue, String configKey, String filePath) { + return "Applied \"" + configValue + "\" as " + configKey + " for file " + filePath; + } +} diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/CodeStyleManager.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/CodeStyleManager.java new file mode 100644 index 000000000000..406e38456976 --- /dev/null +++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/CodeStyleManager.java @@ -0,0 +1,184 @@ +package org.editorconfig.configmanagement; + +import com.intellij.lang.Language; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileEditor.FileEditorManagerAdapter; +import com.intellij.openapi.fileEditor.FileEditorManagerEvent; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.LanguageFileType; +import com.intellij.openapi.fileTypes.PlainTextLanguage; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import org.editorconfig.Utils; +import org.editorconfig.core.EditorConfig.OutPair; +import org.editorconfig.plugincomponents.SettingsProviderComponent; +import org.jetbrains.annotations.NotNull; + +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.util.List; + +public class CodeStyleManager extends FileEditorManagerAdapter implements WindowFocusListener { + // Handles the following EditorConfig settings: + private static final String indentSizeKey = "indent_size"; + private static final String tabWidthKey = "tab_width"; + private static final String indentStyleKey = "indent_style"; + + private static final Logger LOG = Logger.getInstance("#org.editorconfig.configmanagement.CodeStyleManager"); + private final CodeStyleSettingsManager codeStyleSettingsManager; + private final Project project; + + public CodeStyleManager(Project project) { + codeStyleSettingsManager = CodeStyleSettingsManager.getInstance(project); + this.project = project; + } + + @Override + public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) { + applySettings(file); + } + + @Override + public void selectionChanged(@NotNull FileEditorManagerEvent event) { + final VirtualFile file = event.getNewFile(); + applySettings(file); + } + + @Override + public void windowGainedFocus(WindowEvent e) { + final Editor currentEditor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + if (currentEditor != null) { + final Document currentDocument = currentEditor.getDocument(); + final VirtualFile currentFile = FileDocumentManager.getInstance().getFile(currentDocument); + applySettings(currentFile); + } + } + + @Override + public void windowLostFocus(WindowEvent e) { + } + + private void applySettings(final VirtualFile file) { + if (file != null && file.isInLocalFileSystem()) { + // Always drop any current temporary settings so that the defaults will be applied if + // this is a non-editorconfig-managed file + codeStyleSettingsManager.dropTemporarySettings(); + // Prepare a new settings object, which will maintain the standard settings if no + // editorconfig settings apply + final CodeStyleSettings currentSettings = codeStyleSettingsManager.getCurrentSettings(); + final CodeStyleSettings newSettings = new CodeStyleSettings(); + newSettings.copyFrom(currentSettings); + // Get editorconfig settings + final String filePath = file.getCanonicalPath(); + final SettingsProviderComponent settingsProvider = SettingsProviderComponent.getInstance(); + final List<OutPair> outPairs = settingsProvider.getOutPairs(filePath); + // Apply editorconfig settings for the current editor + applyCodeStyleSettings(outPairs, newSettings, file); + codeStyleSettingsManager.setTemporarySettings(newSettings); + final EditorEx currentEditor = (EditorEx)FileEditorManager.getInstance(project).getSelectedTextEditor(); + if (currentEditor != null) { + currentEditor.reinitSettings(); + } + } + } + + private static void applyCodeStyleSettings(final List<OutPair> outPairs, final CodeStyleSettings codeStyleSettings, + final VirtualFile file) { + // Apply indent options + final String indentSize = Utils.configValueForKey(outPairs, indentSizeKey); + final String tabWidth = Utils.configValueForKey(outPairs, tabWidthKey); + final String indentStyle = Utils.configValueForKey(outPairs, indentStyleKey); + final FileType fileType = file.getFileType(); + final Language language = fileType instanceof LanguageFileType ? ((LanguageFileType)fileType).getLanguage() : + PlainTextLanguage.INSTANCE; + final CommonCodeStyleSettings commonSettings = codeStyleSettings.getCommonSettings(language); + final CommonCodeStyleSettings.IndentOptions indentOptions = commonSettings.getIndentOptions(); + applyIndentOptions(indentOptions, indentSize, tabWidth, indentStyle, file.getCanonicalPath()); + } + + private static void applyIndentOptions(CommonCodeStyleSettings.IndentOptions indentOptions, + String indentSize, String tabWidth, String indentStyle, String filePath) { + final String calculatedIndentSize = calculateIndentSize(tabWidth, indentSize); + final String calculatedTabWidth = calculateTabWidth(tabWidth, indentSize); + if (!calculatedIndentSize.isEmpty()) { + if (applyIndentSize(indentOptions, calculatedIndentSize)) { + LOG.debug(Utils.appliedConfigMessage(calculatedIndentSize, indentSizeKey, filePath)); + } + else { + LOG.warn(Utils.invalidConfigMessage(calculatedIndentSize, indentSizeKey, filePath)); + } + } + if (!calculatedTabWidth.isEmpty()) { + if (applyTabWidth(indentOptions, calculatedTabWidth)) { + LOG.debug(Utils.appliedConfigMessage(calculatedTabWidth, tabWidthKey, filePath)); + } + else { + LOG.warn(Utils.invalidConfigMessage(calculatedTabWidth, tabWidthKey, filePath)); + } + } + if (!indentStyle.isEmpty()) { + if (applyIndentStyle(indentOptions, indentStyle)) { + LOG.debug(Utils.appliedConfigMessage(indentStyle, indentStyleKey, filePath)); + } + else { + LOG.warn(Utils.invalidConfigMessage(indentStyle, indentStyleKey, filePath)); + } + } + } + + private static String calculateIndentSize(final String tabWidth, final String indentSize) { + return indentSize.equals("tab") ? tabWidth : indentSize; + } + + private static String calculateTabWidth(final String tabWidth, final String indentSize) { + if (tabWidth.isEmpty() && indentSize.equals("tab")) { + return ""; + } + else if (tabWidth.isEmpty()) { + return indentSize; + } + else { + return tabWidth; + } + } + + private static boolean applyIndentSize(final CommonCodeStyleSettings.IndentOptions indentOptions, final String indentSize) { + try { + int indent = Integer.parseInt(indentSize); + indentOptions.INDENT_SIZE = indent; + indentOptions.CONTINUATION_INDENT_SIZE = indent; + return true; + } + catch (NumberFormatException e) { + return false; + } + } + + private static boolean applyTabWidth(final CommonCodeStyleSettings.IndentOptions indentOptions, final String tabWidth) { + try { + indentOptions.TAB_SIZE = Integer.parseInt(tabWidth); + return true; + } + catch (NumberFormatException e) { + return false; + } + } + + private static boolean applyIndentStyle(CommonCodeStyleSettings.IndentOptions indentOptions, String indentStyle) { + if (indentStyle.equals("tab") || indentStyle.equals("space")) { + indentOptions.USE_TAB_CHARACTER = indentStyle.equals("tab"); + return true; + } + else { + return false; + } + } +} diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java new file mode 100644 index 000000000000..0a062d4d6e04 --- /dev/null +++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java @@ -0,0 +1,85 @@ +package org.editorconfig.configmanagement; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; +import com.intellij.openapi.editor.impl.TrailingSpacesStripper; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.vfs.VirtualFile; +import org.editorconfig.Utils; +import org.editorconfig.core.EditorConfig; +import org.editorconfig.plugincomponents.SettingsProviderComponent; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class EditorSettingsManager extends FileDocumentManagerAdapter { + // Handles the following EditorConfig settings: + private static final String trimTrailingWhitespaceKey = "trim_trailing_whitespace"; + private static final String insertFinalNewlineKey = "insert_final_newline"; + private static final Map<String, String> trimMap; + + static { + Map<String, String> map = new HashMap<String, String>(); + map.put("true", EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE); + map.put("false", EditorSettingsExternalizable.STRIP_TRAILING_SPACES_NONE); + trimMap = Collections.unmodifiableMap(map); + } + + private static final Map<String, Boolean> newlineMap; + + static { + Map<String, Boolean> map = new HashMap<String, Boolean>(); + map.put("true", Boolean.TRUE); + map.put("false", Boolean.FALSE); + newlineMap = Collections.unmodifiableMap(map); + } + + private static final Logger LOG = Logger.getInstance("#org.editorconfig.configmanagement.EditorSettingsManager"); + + @Override + public void beforeDocumentSaving(@NotNull Document document) { + // This is fired when any document is saved, regardless of whether it is part of a save-all or + // a save-one operation + final VirtualFile file = FileDocumentManager.getInstance().getFile(document); + applySettings(file); + } + + private static void applySettings(VirtualFile file) { + if (file == null || !file.isInLocalFileSystem()) return; + // Get editorconfig settings + final String filePath = file.getCanonicalPath(); + final SettingsProviderComponent settingsProvider = SettingsProviderComponent.getInstance(); + final List<EditorConfig.OutPair> outPairs = settingsProvider.getOutPairs(filePath); + // Apply trailing spaces setting + final String trimTrailingWhitespace = Utils.configValueForKey(outPairs, trimTrailingWhitespaceKey); + applyConfigValueToUserData(file, TrailingSpacesStripper.OVERRIDE_STRIP_TRAILING_SPACES_KEY, + trimTrailingWhitespaceKey, trimTrailingWhitespace, trimMap); + // Apply final newline setting + final String insertFinalNewline = Utils.configValueForKey(outPairs, insertFinalNewlineKey); + applyConfigValueToUserData(file, TrailingSpacesStripper.OVERRIDE_ENSURE_NEWLINE_KEY, + insertFinalNewlineKey, insertFinalNewline, newlineMap); + } + + private static <T> void applyConfigValueToUserData(VirtualFile file, Key<T> userDataKey, String editorConfigKey, + String configValue, Map<String, T> configMap) { + if (configValue.isEmpty()) { + file.putUserData(userDataKey, null); + } + else { + final T data = configMap.get(configValue); + if (data == null) { + LOG.warn(Utils.invalidConfigMessage(configValue, editorConfigKey, file.getCanonicalPath())); + } + else { + file.putUserData(userDataKey, data); + LOG.debug("Applied " + editorConfigKey + " settings for: " + file.getCanonicalPath()); + } + } + } +} diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/EncodingManager.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/EncodingManager.java new file mode 100644 index 000000000000..919f0861055f --- /dev/null +++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/EncodingManager.java @@ -0,0 +1,73 @@ +package org.editorconfig.configmanagement; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.encoding.EncodingProjectManager; +import org.editorconfig.Utils; +import org.editorconfig.core.EditorConfig.OutPair; +import org.editorconfig.plugincomponents.SettingsProviderComponent; +import org.jetbrains.annotations.NotNull; + +import java.nio.charset.Charset; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class EncodingManager extends FileDocumentManagerAdapter { + // Handles the following EditorConfig settings: + private static final String charsetKey = "charset"; + + private final Logger LOG = Logger.getInstance("#org.editorconfig.codestylesettings.EncodingManager"); + private final Project project; + + private static final Map<String, Charset> encodingMap; + + static { + Map<String, Charset> map = new HashMap<String, Charset>(); + map.put("latin1", Charset.forName("ISO-8859-1")); + map.put("utf-8", Charset.forName("UTF-8")); + map.put("utf-16be", Charset.forName("UTF-16BE")); + map.put("utf-16le", Charset.forName("UTF-16LE")); + encodingMap = Collections.unmodifiableMap(map); + } + + private boolean isApplyingSettings; + + public EncodingManager(Project project) { + this.project = project; + isApplyingSettings = false; + } + + @Override + public void beforeDocumentSaving(@NotNull Document document) { + final VirtualFile file = FileDocumentManager.getInstance().getFile(document); + if (!isApplyingSettings) { + applySettings(file); + } + } + + private void applySettings(VirtualFile file) { + if (file == null || !file.isInLocalFileSystem()) return; + // Prevent "setEncoding" calling "saveAll" from causing an endless loop + isApplyingSettings = true; + final String filePath = file.getCanonicalPath(); + final List<OutPair> outPairs = SettingsProviderComponent.getInstance().getOutPairs(filePath); + final EncodingProjectManager encodingProjectManager = EncodingProjectManager.getInstance(project); + final String charset = Utils.configValueForKey(outPairs, charsetKey); + if (!charset.isEmpty()) { + if (encodingMap.containsKey(charset)) { + encodingProjectManager.setEncoding(file, encodingMap.get(charset)); + LOG.debug(Utils.appliedConfigMessage(charset, charsetKey, filePath)); + } + else { + LOG.warn(Utils.invalidConfigMessage(charset, charsetKey, filePath)); + } + } + isApplyingSettings = false; + } +} diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/LineEndingsManager.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/LineEndingsManager.java new file mode 100644 index 000000000000..1291ffd297f0 --- /dev/null +++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/LineEndingsManager.java @@ -0,0 +1,95 @@ +package org.editorconfig.configmanagement; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileEditor.FileEditorManagerEvent; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.IdeFrame; +import com.intellij.openapi.wm.StatusBar; +import com.intellij.openapi.wm.StatusBarWidget; +import com.intellij.openapi.wm.WindowManager; +import com.intellij.openapi.wm.impl.status.LineSeparatorPanel; +import com.intellij.util.LineSeparator; +import org.editorconfig.Utils; +import org.editorconfig.core.EditorConfig; +import org.editorconfig.plugincomponents.SettingsProviderComponent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Locale; + +/** + * @author Dennis.Ushakov + */ +public class LineEndingsManager extends FileDocumentManagerAdapter { + // Handles the following EditorConfig settings: + private static final String lineEndingsKey = "end_of_line"; + + private final Logger LOG = Logger.getInstance("#org.editorconfig.codestylesettings.LineEndingsManager"); + private final Project project; + private boolean statusBarUpdated = false; + + public LineEndingsManager(Project project) { + this.project = project; + } + + @Override + public void beforeAllDocumentsSaving() { + statusBarUpdated = false; + } + + private void updateStatusBar() { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + IdeFrame frame = WindowManager.getInstance().getIdeFrame(project); + StatusBar statusBar = frame.getStatusBar(); + StatusBarWidget widget = statusBar != null ? statusBar.getWidget("LineSeparator") : null; + + if (widget instanceof LineSeparatorPanel) { + FileEditorManagerEvent event = new FileEditorManagerEvent(FileEditorManager.getInstance(project), + null, null, null, null); + ((LineSeparatorPanel)widget).selectionChanged(event); + } + } + }); + } + + @Override + public void beforeDocumentSaving(@NotNull Document document) { + VirtualFile file = FileDocumentManager.getInstance().getFile(document); + applySettings(file); + } + + private void applySettings(VirtualFile file) { + if (file == null || !file.isInLocalFileSystem()) return; + + final String filePath = file.getCanonicalPath(); + final List<EditorConfig.OutPair> outPairs = SettingsProviderComponent.getInstance().getOutPairs(filePath); + final String lineEndings = Utils.configValueForKey(outPairs, lineEndingsKey); + if (!lineEndings.isEmpty()) { + try { + LineSeparator separator = LineSeparator.valueOf(lineEndings.toUpperCase(Locale.US)); + String oldSeparator = file.getDetectedLineSeparator(); + String newSeparator = separator.getSeparatorString(); + if (!StringUtil.equals(oldSeparator, newSeparator)) { + file.setDetectedLineSeparator(newSeparator); + if (!statusBarUpdated) { + statusBarUpdated = true; + updateStatusBar(); + } + LOG.debug(Utils.appliedConfigMessage(lineEndings, lineEndingsKey, filePath)); + } + } + catch (IllegalArgumentException e) { + LOG.warn(Utils.invalidConfigMessage(lineEndings, lineEndingsKey, filePath)); + } + } + } +} diff --git a/plugins/editorconfig/src/org/editorconfig/plugincomponents/ConfigProjectComponent.java b/plugins/editorconfig/src/org/editorconfig/plugincomponents/ConfigProjectComponent.java new file mode 100644 index 000000000000..0d31b2bb8b2c --- /dev/null +++ b/plugins/editorconfig/src/org/editorconfig/plugincomponents/ConfigProjectComponent.java @@ -0,0 +1,61 @@ +package org.editorconfig.plugincomponents; + +import com.intellij.AppTopics; +import com.intellij.openapi.components.ProjectComponent; +import com.intellij.openapi.fileEditor.FileEditorManagerListener; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.IdeFrame; +import com.intellij.openapi.wm.WindowManager; +import com.intellij.util.messages.MessageBus; +import org.editorconfig.configmanagement.CodeStyleManager; +import org.editorconfig.configmanagement.EditorSettingsManager; +import org.editorconfig.configmanagement.EncodingManager; +import org.editorconfig.configmanagement.LineEndingsManager; +import org.jetbrains.annotations.NotNull; + +import java.awt.*; + +public class ConfigProjectComponent implements ProjectComponent { + private final Project project; + private final CodeStyleManager codeStyleManager; + + public ConfigProjectComponent(Project project) { + this.project = project; + + // Register project-level config managers + MessageBus bus = project.getMessageBus(); + codeStyleManager = new CodeStyleManager(project); + EditorSettingsManager editorSettingsManager = new EditorSettingsManager(); + EncodingManager encodingManager = new EncodingManager(project); + LineEndingsManager lineEndingsManager = new LineEndingsManager(project); + bus.connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, codeStyleManager); + bus.connect().subscribe(AppTopics.FILE_DOCUMENT_SYNC, encodingManager); + bus.connect().subscribe(AppTopics.FILE_DOCUMENT_SYNC, editorSettingsManager); + bus.connect().subscribe(AppTopics.FILE_DOCUMENT_SYNC, lineEndingsManager); + } + + public void initComponent() { + } + + public void disposeComponent() { + } + + @NotNull + public String getComponentName() { + return "ConfigProjectComponent"; + } + + public void projectOpened() { + // called when project is opened + IdeFrame frame = WindowManager.getInstance().getIdeFrame(project); + final Window window = (Window)frame; + window.addWindowFocusListener(codeStyleManager); + } + + public void projectClosed() { + // called when project is being closed + IdeFrame frame = WindowManager.getInstance().getIdeFrame(project); + final Window window = (Window)frame; + window.removeWindowFocusListener(codeStyleManager); + } +} diff --git a/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java b/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java new file mode 100644 index 000000000000..edd74ebdb22d --- /dev/null +++ b/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java @@ -0,0 +1,49 @@ +package org.editorconfig.plugincomponents; + +import com.intellij.openapi.components.ApplicationComponent; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.diagnostic.Logger; +import org.editorconfig.core.EditorConfig; +import org.editorconfig.core.EditorConfig.OutPair; +import org.editorconfig.core.EditorConfigException; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class SettingsProviderComponent implements ApplicationComponent { + private static final Logger LOG = Logger.getInstance("#org.editorconfig.plugincomponents.SettingsProviderComponent"); + + private EditorConfig editorConfig; + + public SettingsProviderComponent() { + editorConfig = new EditorConfig(); + } + + public static SettingsProviderComponent getInstance() { + return ServiceManager.getService(SettingsProviderComponent.class); + } + + public List<OutPair> getOutPairs(String filePath) { + final List<OutPair> outPairs; + try { + outPairs = editorConfig.getProperties(filePath); + return outPairs; + } + catch (EditorConfigException error) { + LOG.error(error); + return new ArrayList<OutPair>(); + } + } + + public void initComponent() { + } + + public void disposeComponent() { + } + + @NotNull + public String getComponentName() { + return "SettingsProviderComponent"; + } +} diff --git a/plugins/generate-tostring/src/org/jetbrains/generate/tostring/velocity/VelocityFactory.java b/plugins/generate-tostring/src/org/jetbrains/generate/tostring/velocity/VelocityFactory.java index c362f83afcdd..ff4a5b63c83c 100644 --- a/plugins/generate-tostring/src/org/jetbrains/generate/tostring/velocity/VelocityFactory.java +++ b/plugins/generate-tostring/src/org/jetbrains/generate/tostring/velocity/VelocityFactory.java @@ -17,6 +17,7 @@ package org.jetbrains.generate.tostring.velocity; import org.apache.commons.collections.ExtendedProperties; import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.runtime.RuntimeConstants; import org.apache.velocity.runtime.log.SimpleLog4JLogSystem; /** @@ -25,46 +26,41 @@ import org.apache.velocity.runtime.log.SimpleLog4JLogSystem; * Creating instances of the VelocityEngine. */ public class VelocityFactory { + private static class Holder { + private static final VelocityEngine engine = newVeloictyEngine(); + } - private static VelocityEngine engine; + /** + * Privte constructor. + */ + private VelocityFactory() { + } - /** - * Privte constructor. - */ - private VelocityFactory() { - } - - /** - * Returns a new instance of the VelocityEngine. - * <p/> - * The engine is initialized and outputs its logging to IDEA logging. - * - * @return a new velocity engine that is initialized. - * @throws Exception error creating the VelocityEngine. - */ - public static VelocityEngine newVeloictyEngine() throws Exception { - ExtendedProperties prop = new ExtendedProperties(); - prop.addProperty(VelocityEngine.RUNTIME_LOG_LOGSYSTEM_CLASS, SimpleLog4JLogSystem.class.getName()); - prop.addProperty("runtime.log.logsystem.log4j.category", "GenerateToString"); - VelocityEngine velocity = new VelocityEngine(); - velocity.setExtendedProperties(prop); - velocity.init(); - return velocity; - } - - /** - * Get's a shared instance of the VelocityEngine. - * <p/> - * The engine is initialized and outputs its logging to IDEA logging. - * @return a shared instance of the engine that is initialized. - * @throws Exception error creating the VelocityEngine. - */ - public static VelocityEngine getVelocityEngine() throws Exception { - if (engine == null) { - engine = newVeloictyEngine(); - } - - return engine; - } + /** + * Returns a new instance of the VelocityEngine. + * <p/> + * The engine is initialized and outputs its logging to IDEA logging. + * + * @return a new velocity engine that is initialized. + */ + private static VelocityEngine newVeloictyEngine() { + ExtendedProperties prop = new ExtendedProperties(); + prop.addProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, SimpleLog4JLogSystem.class.getName()); + prop.addProperty("runtime.log.logsystem.log4j.category", "GenerateToString"); + VelocityEngine velocity = new VelocityEngine(); + velocity.setExtendedProperties(prop); + velocity.init(); + return velocity; + } + /** + * Get's a shared instance of the VelocityEngine. + * <p/> + * The engine is initialized and outputs its logging to IDEA logging. + * + * @return a shared instance of the engine that is initialized. + */ + public static VelocityEngine getVelocityEngine() { + return Holder.engine; + } }
\ No newline at end of file diff --git a/plugins/git4idea/git4idea.iml b/plugins/git4idea/git4idea.iml index 1b6091a77419..53ee70f60eca 100644 --- a/plugins/git4idea/git4idea.iml +++ b/plugins/git4idea/git4idea.iml @@ -49,7 +49,7 @@ </library> </orderEntry> <orderEntry type="library" scope="TEST" name="Groovy" level="project" /> - <orderEntry type="module" module-name="dvcs" exported="" /> + <orderEntry type="module" module-name="dvcs-impl" exported="" /> <orderEntry type="library" scope="TEST" name="cucumber-jvm" level="project" /> <orderEntry type="library" scope="TEST" name="cucumber-java" level="project" /> <orderEntry type="library" name="JSch" level="project" /> @@ -58,6 +58,7 @@ <orderEntry type="module" module-name="vcs-log-api" /> <orderEntry type="module" module-name="vcs-log-impl" /> <orderEntry type="module" module-name="vcs-log-graph" /> + <orderEntry type="module" module-name="dvcs-api" exported="" /> </component> </module> diff --git a/plugins/git4idea/remote-servers-git/remote-servers-git.iml b/plugins/git4idea/remote-servers-git/remote-servers-git.iml index a2ae7940093c..754094b7fb98 100644 --- a/plugins/git4idea/remote-servers-git/remote-servers-git.iml +++ b/plugins/git4idea/remote-servers-git/remote-servers-git.iml @@ -18,6 +18,7 @@ <orderEntry type="module" module-name="idea-ui" /> <orderEntry type="module" module-name="openapi" /> <orderEntry type="module" module-name="vcs-impl" /> + <orderEntry type="module" module-name="dvcs-api" /> </component> </module> diff --git a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java index 9846393b99a8..3ac118fe6b7f 100644 --- a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java +++ b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java @@ -15,8 +15,8 @@ import com.intellij.openapi.vcs.changes.ui.CommitChangeListDialog; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.remoteServer.agent.util.CloudAgentLoggingHandler; import com.intellij.remoteServer.agent.util.CloudGitApplication; -import com.intellij.remoteServer.agent.util.CloudLoggingHandler; import com.intellij.remoteServer.configuration.deployment.DeploymentSource; import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager; import com.intellij.remoteServer.runtime.deployment.DeploymentTask; @@ -350,7 +350,7 @@ public class CloudGitDeploymentRuntime extends CloudDeploymentRuntime { } @Override - protected CloudLoggingHandler getLoggingHandler() { + protected CloudAgentLoggingHandler getLoggingHandler() { return super.getLoggingHandler(); } diff --git a/plugins/git4idea/src/git4idea/GitContentRevision.java b/plugins/git4idea/src/git4idea/GitContentRevision.java index 68fcb59febf2..8dd85b167980 100644 --- a/plugins/git4idea/src/git4idea/GitContentRevision.java +++ b/plugins/git4idea/src/git4idea/GitContentRevision.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. @@ -27,6 +27,7 @@ import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vcs.impl.ContentRevisionCache; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.vcsUtil.VcsFilePathUtil; import com.intellij.vcsUtil.VcsFileUtil; import com.intellij.vcsUtil.VcsUtil; import git4idea.util.GitFileUtils; @@ -168,7 +169,7 @@ public class GitContentRevision implements ContentRevision { boolean isDeleted, boolean canBeDeleted, boolean unescapePath) throws VcsException { final String absolutePath = makeAbsolutePath(vcsRoot, path, unescapePath); FilePath file = isDeleted ? VcsUtil.getFilePathForDeletedFile(absolutePath, false) : VcsUtil.getFilePath(absolutePath, false); - if (canBeDeleted && (! SystemInfo.isFileSystemCaseSensitive) && VcsUtil.caseDiffers(file.getPath(), absolutePath)) { + if (canBeDeleted && (! SystemInfo.isFileSystemCaseSensitive) && VcsFilePathUtil.caseDiffers(file.getPath(), absolutePath)) { // as for deleted file file = FilePathImpl.createForDeletedFile(new File(absolutePath), false); } diff --git a/plugins/git4idea/src/git4idea/GitRevisionNumber.java b/plugins/git4idea/src/git4idea/GitRevisionNumber.java index cd6387a4e629..06fba24f015a 100644 --- a/plugins/git4idea/src/git4idea/GitRevisionNumber.java +++ b/plugins/git4idea/src/git4idea/GitRevisionNumber.java @@ -15,6 +15,7 @@ */ package git4idea; +import com.intellij.dvcs.DvcsUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; @@ -103,7 +104,7 @@ public class GitRevisionNumber implements ShortVcsRevisionNumber { */ @NotNull public String getShortRev() { - return GitUtil.getShortHash(myRevisionHash); + return DvcsUtil.getShortHash(myRevisionHash); } /** diff --git a/plugins/git4idea/src/git4idea/GitUtil.java b/plugins/git4idea/src/git4idea/GitUtil.java index 4ff61fb4a68b..e96d52de8ea0 100644 --- a/plugins/git4idea/src/git4idea/GitUtil.java +++ b/plugins/git4idea/src/git4idea/GitUtil.java @@ -102,7 +102,6 @@ public class GitUtil { public static final String DOT_GIT = ".git"; private final static Logger LOG = Logger.getInstance(GitUtil.class); - private static final int SHORT_HASH_LENGTH = 8; public static final Predicate<GitBranchTrackInfo> NOT_NULL_PREDICATE = new Predicate<GitBranchTrackInfo>() { @Override @@ -829,17 +828,6 @@ public class GitUtil { } @NotNull - public static String getShortHash(@NotNull String hash) { - if (hash.length() == 0) return ""; - if (hash.length() == 40) return hash.substring(0, SHORT_HASH_LENGTH); - if (hash.length() > 40) // revision string encoded with date too - { - return hash.substring(hash.indexOf("[") + 1, SHORT_HASH_LENGTH); - } - return hash; - } - - @NotNull public static String fileOrFolder(@NotNull VirtualFile file) { if (file.isDirectory()) { return "Folder"; diff --git a/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java b/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java index f0ad3b7a5e31..8799c0e69651 100644 --- a/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java +++ b/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java @@ -15,6 +15,7 @@ */ package git4idea.actions; +import com.intellij.dvcs.DvcsUtil; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.Presentation; @@ -70,7 +71,7 @@ public class GitCompareWithBranchAction extends DumbAwareAction { String currentRevision = repository.getCurrentRevision(); LOG.assertTrue(currentRevision != null, "Current revision is null for " + repository + ". Compare with branch shouldn't be available for fresh repository"); - head = GitUtil.getShortHash(currentRevision); + head = DvcsUtil.getShortHash(currentRevision); } else { head = currentBranch.getName(); diff --git a/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java b/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java index 46875b9d8c23..5ebdefd74b3a 100644 --- a/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java +++ b/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java @@ -46,45 +46,20 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -/** - * Git annotation provider implementation. - * <p/> - * Based on the JetBrains SVNAnnotationProvider. - */ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAnnotationProvider { - /** - * the context project - */ private final Project myProject; - /** - * The author key for annotations - */ @NonNls private static final String AUTHOR_KEY = "author"; - /** - * The committer time key for annotations - */ @NonNls private static final String COMMITTER_TIME_KEY = "committer-time"; private static final Logger LOG = Logger.getInstance(GitAnnotationProvider.class); - /** - * A constructor - * - * @param project a context project - */ public GitAnnotationProvider(@NotNull Project project) { myProject = project; } - /** - * {@inheritDoc} - */ public FileAnnotation annotate(@NotNull VirtualFile file) throws VcsException { return annotate(file, null); } - /** - * {@inheritDoc} - */ public FileAnnotation annotate(@NotNull final VirtualFile file, final VcsFileRevision revision) throws VcsException { if (file.isDirectory()) { throw new VcsException("Cannot annotate a directory"); @@ -119,8 +94,8 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn } }; if (ApplicationManager.getApplication().isDispatchThread()) { - ProgressManager.getInstance() - .runProcessWithProgressSynchronously(command, GitBundle.getString("annotate.action.name"), false, myProject); + ProgressManager.getInstance().runProcessWithProgressSynchronously(command, GitBundle.getString("annotate.action.name"), false, + myProject); } else { command.run(); @@ -132,16 +107,6 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn return annotation[0]; } - /** - * Calculate annotations - * - * @param repositoryFilePath the file path in the repository - * @param revision the revision to checkout - * @param revisions the revision list from history - * @param file a virtual file for the action - * @return a file annotation object - * @throws VcsException if there is a problem with running git - */ private GitFileAnnotation annotate(final FilePath repositoryFilePath, final VcsFileRevision revision, final List<VcsFileRevision> revisions, @@ -159,7 +124,7 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn h.endOptions(); h.addRelativePaths(repositoryFilePath); String output = h.run(); - GitFileAnnotation annotation = new GitFileAnnotation(myProject, file, revision == null, revision == null ? null : revision.getRevisionNumber()); + GitFileAnnotation annotation = new GitFileAnnotation(myProject, file, revision == null ? null : revision.getRevisionNumber()); class CommitInfo { Date date; String author; @@ -229,7 +194,7 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn String annotatedContent, boolean forCurrentRevision, VcsRevisionNumber revisionNumber) { final GitFileAnnotation gitFileAnnotation = - new GitFileAnnotation(myProject, vcsAnnotation.getFilePath().getVirtualFile(), forCurrentRevision, revisionNumber); + new GitFileAnnotation(myProject, vcsAnnotation.getFilePath().getVirtualFile(), revisionNumber); gitFileAnnotation.addLogEntries(session.getRevisionList()); final VcsLineAnnotationData basicAnnotation = vcsAnnotation.getBasicAnnotation(); final int size = basicAnnotation.getNumLines(); @@ -252,9 +217,6 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn return gitFileAnnotation; } - /** - * {@inheritDoc} - */ public boolean isAnnotationValid(VcsFileRevision rev) { return true; } diff --git a/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java b/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java index 4dfe4da19de0..0c1df6a50a5b 100644 --- a/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java +++ b/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java @@ -15,7 +15,6 @@ */ package git4idea.annotate; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.VcsKey; @@ -23,6 +22,7 @@ import com.intellij.openapi.vcs.annotate.*; import com.intellij.openapi.vcs.history.VcsFileRevision; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.ObjectUtils; import com.intellij.util.text.DateFormatUtil; import git4idea.GitRevisionNumber; import git4idea.GitVcs; @@ -32,45 +32,24 @@ import org.jetbrains.annotations.Nullable; import java.util.*; -/** - * Git file annotation implementation - * <p/> - * Based on the JetBrains SVNAnnotationProvider. - */ public class GitFileAnnotation extends FileAnnotation { - private final static Logger LOG = Logger.getInstance("#git4idea.annotate.GitFileAnnotation"); - - /** - * annotated content - */ - private final StringBuffer myContentBuffer = new StringBuffer(); - /** - * The currently annotated lines - */ - private final ArrayList<LineInfo> myLines = new ArrayList<LineInfo>(); - /** - * The project reference - */ + private final StringBuffer myContentBuffer = new StringBuffer(); // annotated content + private final ArrayList<LineInfo> myLines = new ArrayList<LineInfo>(); // The currently annotated lines private final Project myProject; private final VcsRevisionNumber myBaseRevision; - /** - * Map from revision numbers to revisions - */ - private final Map<VcsRevisionNumber, VcsFileRevision> myRevisionMap = new HashMap<VcsRevisionNumber, VcsFileRevision>(); + @NotNull private final Map<VcsRevisionNumber, VcsFileRevision> myRevisionMap = new HashMap<VcsRevisionNumber, VcsFileRevision>(); + @NotNull private final VirtualFile myFile; + @NotNull private final GitVcs myVcs; - /** - * the virtual file for which annotations are generated - */ - private final VirtualFile myFile; - - private final LineAnnotationAspect DATE_ASPECT = new GitAnnotationAspect(GitAnnotationAspect.DATE, true) { + private final LineAnnotationAspect DATE_ASPECT = new GitAnnotationAspect(LineAnnotationAspect.DATE, true) { + @Override public String doGetValue(LineInfo info) { final Date date = info.getDate(); return date == null ? "" : DateFormatUtil.formatPrettyDate(date); } }; - private final LineAnnotationAspect REVISION_ASPECT = new GitAnnotationAspect(GitAnnotationAspect.REVISION, false) { + private final LineAnnotationAspect REVISION_ASPECT = new GitAnnotationAspect(LineAnnotationAspect.REVISION, false) { @Override protected String doGetValue(LineInfo lineInfo) { final GitRevisionNumber revision = lineInfo.getRevision(); @@ -78,101 +57,78 @@ public class GitFileAnnotation extends FileAnnotation { } }; - private final LineAnnotationAspect AUTHOR_ASPECT = new GitAnnotationAspect(GitAnnotationAspect.AUTHOR, true) { + private final LineAnnotationAspect AUTHOR_ASPECT = new GitAnnotationAspect(LineAnnotationAspect.AUTHOR, true) { @Override protected String doGetValue(LineInfo lineInfo) { final String author = lineInfo.getAuthor(); return author == null ? "" : author; } }; - private final GitVcs myVcs; - /** - * A constructor - * - * @param project the project of annotation provider - * @param file the git root - * @param monitorFlag if false the file system will not be listened for changes (used for annotated files from the repository). - * @param revision - */ - public GitFileAnnotation(@NotNull final Project project, @NotNull VirtualFile file, final boolean monitorFlag, final VcsRevisionNumber revision) { + public GitFileAnnotation(@NotNull final Project project, + @NotNull VirtualFile file, + final VcsRevisionNumber revision) { super(project); myProject = project; - myVcs = GitVcs.getInstance(myProject); + myVcs = ObjectUtils.assertNotNull(GitVcs.getInstance(myProject)); myFile = file; myBaseRevision = revision == null ? (myVcs.getDiffProvider().getCurrentRevision(file)) : revision; } - /** - * Add revisions to the list (from log) - * - * @param revisions revisions to add - */ public void addLogEntries(List<VcsFileRevision> revisions) { for (VcsFileRevision vcsFileRevision : revisions) { myRevisionMap.put(vcsFileRevision.getRevisionNumber(), vcsFileRevision); } } - /** - * {@inheritDoc} - */ + @Override public void dispose() { } - /** - * {@inheritDoc} - */ + @Override public LineAnnotationAspect[] getAspects() { return new LineAnnotationAspect[]{REVISION_ASPECT, DATE_ASPECT, AUTHOR_ASPECT}; } - /** - * {@inheritDoc} - */ + @Override public String getToolTip(final int lineNumber) { if (myLines.size() <= lineNumber || lineNumber < 0) { return ""; } final LineInfo info = myLines.get(lineNumber); - if (info == null) { - return ""; - } VcsFileRevision fileRevision = myRevisionMap.get(info.getRevision()); if (fileRevision != null) { - return GitBundle - .message("annotation.tool.tip", info.getRevision().asString(), info.getAuthor(), info.getDate(), - fileRevision.getCommitMessage()); + return GitBundle.message("annotation.tool.tip", info.getRevision().asString(), info.getAuthor(), info.getDate(), + fileRevision.getCommitMessage()); } else { return ""; } } - /** - * {@inheritDoc} - */ + @Override public String getAnnotatedContent() { return myContentBuffer.toString(); } - /** - * {@inheritDoc} - */ + @Override public List<VcsFileRevision> getRevisions() { final List<VcsFileRevision> result = new ArrayList<VcsFileRevision>(myRevisionMap.values()); Collections.sort(result, new Comparator<VcsFileRevision>() { - public int compare(final VcsFileRevision o1, final VcsFileRevision o2) { + @Override + public int compare(@NotNull VcsFileRevision o1, @NotNull VcsFileRevision o2) { return -1 * o1.getRevisionNumber().compareTo(o2.getRevisionNumber()); } }); return result; } + @Override public boolean revisionsNotEmpty() { return ! myRevisionMap.isEmpty(); } + @Override public AnnotationSourceSwitcher getAnnotationSourceSwitcher() { return null; } @@ -182,19 +138,16 @@ public class GitFileAnnotation extends FileAnnotation { return myLines.size(); } - /** - * {@inheritDoc} - */ + @Override public VcsRevisionNumber getLineRevisionNumber(final int lineNumber) { if (lineNumberCheck(lineNumber)) { return null; } - final LineInfo lineInfo = myLines.get(lineNumber); - return lineInfo == null ? null : lineInfo.getRevision(); + return myLines.get(lineNumber).getRevision(); } private boolean lineNumberCheck(int lineNumber) { - return myLines.size() <= lineNumber || lineNumber < 0 || myLines.get(lineNumber) == null; + return myLines.size() <= lineNumber || lineNumber < 0; } @Override @@ -202,13 +155,13 @@ public class GitFileAnnotation extends FileAnnotation { if (lineNumberCheck(lineNumber)) { return null; } - final LineInfo lineInfo = myLines.get(lineNumber); - return lineInfo == null ? null : lineInfo.getDate(); + return myLines.get(lineNumber).getDate(); } /** * Get revision number for the line. */ + @Override public VcsRevisionNumber originalRevision(int lineNumber) { return getLineRevisionNumber(lineNumber); } @@ -248,6 +201,7 @@ public class GitFileAnnotation extends FileAnnotation { super(id, showByDefault); } + @Override public String getValue(int lineNumber) { if (lineNumberCheck(lineNumber)) { return ""; @@ -262,10 +216,8 @@ public class GitFileAnnotation extends FileAnnotation { @Override protected void showAffectedPaths(int lineNum) { if (lineNum >= 0 && lineNum < myLines.size()) { - final LineInfo info = myLines.get(lineNum); - if (info != null) { - ShowAllAffectedGenericAction.showSubmittedFiles(myProject, info.getRevision(), myFile, GitVcs.getKey()); - } + LineInfo info = myLines.get(lineNum); + ShowAllAffectedGenericAction.showSubmittedFiles(myProject, info.getRevision(), myFile, GitVcs.getKey()); } } } @@ -274,54 +226,31 @@ public class GitFileAnnotation extends FileAnnotation { * Line information */ static class LineInfo { - /** - * date of the change - */ private final Date myDate; - /** - * revision number - */ private final GitRevisionNumber myRevision; - /** - * the author of the change - */ private final String myAuthor; - /** - * A constructor - * - * @param date date of the change - * @param revision revision number - * @param author the author of the change - */ - public LineInfo(final Date date, final GitRevisionNumber revision, final String author) { + public LineInfo(Date date, GitRevisionNumber revision, String author) { myDate = date; myRevision = revision; myAuthor = author; } - /** - * @return the revision date - */ public Date getDate() { return myDate; } - /** - * @return the revision number - */ public GitRevisionNumber getRevision() { return myRevision; } - /** - * @return the author of the change - */ public String getAuthor() { return myAuthor; } } + @NotNull + @Override public VirtualFile getFile() { return myFile; } diff --git a/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java b/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java index a6488d4ce3d0..d0f051c50475 100644 --- a/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java +++ b/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java @@ -15,6 +15,7 @@ */ package git4idea.history; +import com.intellij.dvcs.DvcsUtil; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.impl.SimpleDataContext; import com.intellij.openapi.components.ServiceManager; @@ -116,7 +117,7 @@ public class GitDiffFromHistoryHandler extends BaseDiffFromHistoryHandler<GitFil @NotNull @Override protected String getPresentableName(@NotNull GitFileRevision revision) { - return GitUtil.getShortHash(revision.getHash()); + return DvcsUtil.getShortHash(revision.getHash()); } @NotNull @@ -301,7 +302,7 @@ public class GitDiffFromHistoryHandler extends BaseDiffFromHistoryHandler<GitFil @NotNull private final GitFileRevision myParentRevision; public ShowDiffWithParentAction(@NotNull FilePath filePath, @NotNull GitFileRevision rev, @NotNull GitFileRevision parent) { - super(GitUtil.getShortHash(parent.getHash())); + super(DvcsUtil.getShortHash(parent.getHash())); myFilePath = filePath; myRevision = rev; myParentRevision = parent; diff --git a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties index 03803fbf985c..f89657535f8a 100644 --- a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties +++ b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties @@ -416,20 +416,6 @@ unstash.unstashing=Unstashing... unstash.view.tooltip=View selected stash unstash.view=&View unstashing.title=UnStashing changes... -update.locally.modified.files.tooltip=Locally modified files. -update.locally.modified.files=&Files: -update.locally.modified.git.root=Git Root: -update.locally.modified.message=<html><p>The following files under this root are locally modified. <br/>\ - Possible reasons: uncommitted changes; a problem with crlf conversion; {0} configuration file auto-save.</p>\ - <p><ul>\ - <li>Press <b>Revert Files</b> to discard these local changes and continue the update process.</li>\ - <li>Press <b>Cancel</b> to cancel the update process. <br/> Use Auto-Stash option to stash local changes before update and restore them after it.</li>\ - </ul></p> \ - </html> -update.locally.modified.rescan.tooltip=<html>Rescan the repository to check for locally modified files again.<br/>Use this button if you have resolved the problem manually.</html> -update.locally.modified.rescan=Re&scan -update.locally.modified.revert=Revert Files -update.locally.modified.title=Locally modified files are detected update.options.display.name=Git Update Settings update.options.no.commit=No &Commit update.options.save.before.update=Clean working tree before update diff --git a/plugins/git4idea/src/git4idea/push/GitPushDialog.java b/plugins/git4idea/src/git4idea/push/GitPushDialog.java index 56476078f692..f12b7b407c89 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushDialog.java +++ b/plugins/git4idea/src/git4idea/push/GitPushDialog.java @@ -15,6 +15,7 @@ */ package git4idea.push; +import com.intellij.dvcs.DvcsUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; @@ -219,7 +220,7 @@ public class GitPushDialog extends DialogWrapper { private static String logMessageForCommits(GitCommitsByRepoAndBranch commitsToPush) { StringBuilder logMessage = new StringBuilder(); for (GitCommit commit : commitsToPush.getAllCommits()) { - logMessage.append(GitUtil.getShortHash(commit.getId().toString())); + logMessage.append(DvcsUtil.getShortHash(commit.getId().toString())); } return logMessage.toString(); } diff --git a/plugins/git4idea/src/git4idea/push/GitPushLog.java b/plugins/git4idea/src/git4idea/push/GitPushLog.java index 99d3c1350698..e3659554bdf2 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushLog.java +++ b/plugins/git4idea/src/git4idea/push/GitPushLog.java @@ -29,7 +29,6 @@ import com.intellij.openapi.vcs.changes.ui.ChangesBrowser; import com.intellij.ui.*; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; -import com.intellij.util.text.DateFormatUtil; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; import git4idea.GitBranch; @@ -336,12 +335,12 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider { @NotNull private static String getDateString(@NotNull GitCommit commit) { - return DateFormatUtil.formatPrettyDateTime(commit.getTimestamp()) + " "; + return DvcsUtil.getDateString(commit); } @NotNull private static String getHashString(@NotNull GitCommit commit) { - return GitUtil.getShortHash(commit.getId().toString()); + return DvcsUtil.getShortHash(commit.getId().toString()); } private static class MyTreeCellRenderer extends CheckboxTree.CheckboxTreeCellRenderer { diff --git a/plugins/git4idea/src/git4idea/rebase/GitRebaser.java b/plugins/git4idea/src/git4idea/rebase/GitRebaser.java index aabf913fbf61..d5a0470d1667 100644 --- a/plugins/git4idea/src/git4idea/rebase/GitRebaser.java +++ b/plugins/git4idea/src/git4idea/rebase/GitRebaser.java @@ -30,6 +30,7 @@ import git4idea.commands.*; import git4idea.merge.GitConflictResolver; import git4idea.update.GitUpdateResult; import git4idea.util.GitUIUtil; +import git4idea.util.LocalChangesWouldBeOverwrittenHelper; import git4idea.util.StringScanner; import git4idea.util.UntrackedFilesNotifier; import org.jetbrains.annotations.NotNull; @@ -43,6 +44,8 @@ import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +import static git4idea.commands.GitLocalChangesWouldBeOverwrittenDetector.Operation.CHECKOUT; + /** * @author Kirill Likhodedov */ @@ -77,7 +80,9 @@ public class GitRebaser { final GitRebaseProblemDetector rebaseConflictDetector = new GitRebaseProblemDetector(); rebaseHandler.addLineListener(rebaseConflictDetector); GitUntrackedFilesOverwrittenByOperationDetector untrackedFilesDetector = new GitUntrackedFilesOverwrittenByOperationDetector(root); + GitLocalChangesWouldBeOverwrittenDetector localChangesDetector = new GitLocalChangesWouldBeOverwrittenDetector(root, CHECKOUT); rebaseHandler.addLineListener(untrackedFilesDetector); + rebaseHandler.addLineListener(localChangesDetector); String progressTitle = "Rebasing"; GitTask rebaseTask = new GitTask(myProject, rebaseHandler, progressTitle); @@ -108,7 +113,7 @@ public class GitRebaser { }); if (failure.get()) { - updateResult.set(handleRebaseFailure(rebaseHandler, root, rebaseConflictDetector, untrackedFilesDetector)); + updateResult.set(handleRebaseFailure(rebaseHandler, root, rebaseConflictDetector, untrackedFilesDetector, localChangesDetector)); } } finally { @@ -333,19 +338,27 @@ public class GitRebaser { } @NotNull - public GitUpdateResult handleRebaseFailure(@NotNull GitLineHandler handler, @NotNull VirtualFile root, + public GitUpdateResult handleRebaseFailure(@NotNull GitLineHandler handler, + @NotNull VirtualFile root, @NotNull GitRebaseProblemDetector rebaseConflictDetector, - @NotNull GitMessageWithFilesDetector untrackedWouldBeOverwrittenDetector) { + @NotNull GitMessageWithFilesDetector untrackedWouldBeOverwrittenDetector, + @NotNull GitLocalChangesWouldBeOverwrittenDetector localChangesDetector) { if (rebaseConflictDetector.isMergeConflict()) { LOG.info("handleRebaseFailure merge conflict"); final boolean allMerged = new GitRebaser.ConflictResolver(myProject, myGit, root, this).merge(); return allMerged ? GitUpdateResult.SUCCESS_WITH_RESOLVED_CONFLICTS : GitUpdateResult.INCOMPLETE; - } else if (untrackedWouldBeOverwrittenDetector.wasMessageDetected()) { + } + else if (untrackedWouldBeOverwrittenDetector.wasMessageDetected()) { LOG.info("handleRebaseFailure: untracked files would be overwritten by checkout"); UntrackedFilesNotifier.notifyUntrackedFilesOverwrittenBy(myProject, root, untrackedWouldBeOverwrittenDetector.getRelativeFilePaths(), "rebase", null); return GitUpdateResult.ERROR; - } else { + } + else if (localChangesDetector.wasMessageDetected()) { + LocalChangesWouldBeOverwrittenHelper.showErrorNotification(myProject, root, "rebase", localChangesDetector.getRelativeFilePaths()); + return GitUpdateResult.ERROR; + } + else { LOG.info("handleRebaseFailure error " + handler.errors()); GitUIUtil.notifyImportantError(myProject, "Rebase error", GitUIUtil.stringifyErrors(handler.errors())); return GitUpdateResult.ERROR; diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java index e401334416d6..1444f44c0288 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java @@ -19,11 +19,13 @@ import com.intellij.dvcs.repo.RepositoryImpl; import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import git4idea.GitLocalBranch; import git4idea.GitPlatformFacade; import git4idea.GitUtil; +import git4idea.GitVcs; import git4idea.branch.GitBranchesCollection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -135,6 +137,12 @@ public class GitRepositoryImpl extends RepositoryImpl implements GitRepository { return myInfo.getState(); } + @Nullable + @Override + public AbstractVcs getVcs() { + return GitVcs.getInstance(getProject()); + } + /** * @return local and remote branches in this repository. */ diff --git a/plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java b/plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java index 5e2cb18e7c7e..58363b917992 100644 --- a/plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java +++ b/plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java @@ -15,6 +15,7 @@ */ package git4idea.reset; +import com.intellij.dvcs.DvcsUtil; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; @@ -26,7 +27,6 @@ import com.intellij.util.ui.RadioButtonEnumModel; import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.xml.util.XmlStringUtil; -import git4idea.GitUtil; import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; import org.jetbrains.annotations.NotNull; @@ -117,7 +117,7 @@ public class GitNewResetDialog extends DialogWrapper { @NotNull private static String getTargetText(@NotNull VcsFullCommitDetails commit) { - String commitMessage = StringUtil.shortenTextWithEllipsis(commit.getSubject(), 20, 0); + String commitMessage = StringUtil.escapeXml(StringUtil.shortenTextWithEllipsis(commit.getSubject(), 20, 0)); return String.format("<code><b>%s</b> \"%s\"</code> by <code>%s</code>", commit.getId().toShortString(), commitMessage, commit.getAuthor().getName()); } @@ -127,7 +127,7 @@ public class GitNewResetDialog extends DialogWrapper { String currentRevision = repository.getCurrentRevision(); assert currentRevision != null; String text = repository.getCurrentBranch() == null ? - "HEAD (" + GitUtil.getShortHash(currentRevision) + ")" : + "HEAD (" + DvcsUtil.getShortHash(currentRevision) + ")" : repository.getCurrentBranch().getName(); return "<b>" + text + "</b>"; } diff --git a/plugins/git4idea/src/git4idea/ui/GitCommitListPanel.java b/plugins/git4idea/src/git4idea/ui/GitCommitListPanel.java index dcd1c3182b47..94d01022c83e 100644 --- a/plugins/git4idea/src/git4idea/ui/GitCommitListPanel.java +++ b/plugins/git4idea/src/git4idea/ui/GitCommitListPanel.java @@ -15,6 +15,7 @@ */ package git4idea.ui; +import com.intellij.dvcs.DvcsUtil; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.changes.Change; @@ -28,7 +29,6 @@ import com.intellij.util.ui.ColumnInfo; import com.intellij.util.ui.ListTableModel; import com.intellij.util.ui.UIUtil; import git4idea.GitCommit; -import git4idea.GitUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -198,7 +198,7 @@ public class GitCommitListPanel extends JPanel implements TypeSafeDataProvider { } private static String getHash(GitCommit commit) { - return GitUtil.getShortHash(commit.getId().toString()); + return DvcsUtil.getShortHash(commit.getId().toString()); } private static String getAuthor(GitCommit commit) { diff --git a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java index eccaa446b0ed..44e4f1fab4b9 100644 --- a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java +++ b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java @@ -51,6 +51,7 @@ import git4idea.merge.GitConflictResolver; import git4idea.repo.GitRepository; import git4idea.stash.GitStashUtils; import git4idea.util.GitUIUtil; +import git4idea.util.LocalChangesWouldBeOverwrittenHelper; import git4idea.util.UntrackedFilesNotifier; import git4idea.validators.GitBranchNameValidator; import org.jetbrains.annotations.NotNull; @@ -68,6 +69,8 @@ import java.util.HashSet; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import static git4idea.commands.GitLocalChangesWouldBeOverwrittenDetector.Operation.MERGE; + /** * The unstash dialog */ @@ -349,7 +352,9 @@ public class GitUnstashDialog extends DialogWrapper { } }); GitUntrackedFilesOverwrittenByOperationDetector untrackedFilesDetector = new GitUntrackedFilesOverwrittenByOperationDetector(root); + GitLocalChangesWouldBeOverwrittenDetector localChangesDetector = new GitLocalChangesWouldBeOverwrittenDetector(root, MERGE); h.addLineListener(untrackedFilesDetector); + h.addLineListener(localChangesDetector); GitUtil.workingTreeChangeStarted(myProject); try { @@ -371,6 +376,8 @@ public class GitUnstashDialog extends DialogWrapper { } else if (untrackedFilesDetector.wasMessageDetected()) { UntrackedFilesNotifier.notifyUntrackedFilesOverwrittenBy(myProject, root, untrackedFilesDetector.getRelativeFilePaths(), "unstash", null); + } else if (localChangesDetector.wasMessageDetected()) { + LocalChangesWouldBeOverwrittenHelper.showErrorDialog(myProject, root, "unstash", localChangesDetector.getRelativeFilePaths()); } else if (!res.success()) { GitUIUtil.showOperationErrors(myProject, h.errors(), h.printableCommandLine()); } diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java index bd9c8fb3a1b3..1cb7cf6a66c9 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java @@ -45,14 +45,8 @@ import javax.swing.event.HyperlinkEvent; import java.util.List; /** - * <p> * The popup which allows to quickly switch and control Git branches. - * </p> - * <p> - * Use {@link #asListPopup()} to achieve the {@link ListPopup} itself. - * </p> - * - * @author Kirill Likhodedov + * <p/> */ class GitBranchPopup { @@ -160,32 +154,28 @@ class GitBranchPopup { } private void notifyAboutSyncedBranches() { - VcsNotifier.getInstance(myProject).notifyImportantInfo("Synchronous branch control enabled", - "You have several Git roots in the project and they all are checked out at the same branch. " + - "We've enabled synchronous branch control for the project. <br/>" + - "If you wish to control branches in different roots separately, you may <a href='settings'>disable</a> the setting.", - new NotificationListener() { - @Override - public void hyperlinkUpdate(@NotNull Notification notification, - @NotNull HyperlinkEvent event) { - if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - ShowSettingsUtil.getInstance().showSettingsDialog(myProject, myVcs - .getConfigurable().getDisplayName()); - if (myVcsSettings.getSyncSetting() == GitBranchSyncSetting.DONT) { - notification.expire(); - } - } - } - } - ); + String description = "You have several Git roots in the project and they all are checked out at the same branch. " + + "We've enabled synchronous branch control for the project. <br/>" + + "If you wish to control branches in different roots separately, " + + "you may <a href='settings'>disable</a> the setting."; + NotificationListener listener = new NotificationListener() { + @Override + public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { + if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + ShowSettingsUtil.getInstance().showSettingsDialog(myProject, myVcs.getConfigurable().getDisplayName()); + if (myVcsSettings.getSyncSetting() == GitBranchSyncSetting.DONT) { + notification.expire(); + } + } + } + }; + VcsNotifier.getInstance(myProject).notifyImportantInfo("Synchronous branch control enabled", description, listener); } private ActionGroup createActions() { DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); - GitRepositoryManager repositoryManager = myRepositoryManager; if (repositoryManager.moreThanOneRoot()) { - if (userWantsSyncControl()) { fillWithCommonRepositoryActions(popupGroup, repositoryManager); } @@ -196,7 +186,6 @@ class GitBranchPopup { else { fillPopupWithCurrentRepositoryActions(popupGroup, null); } - popupGroup.addSeparator(); return popupGroup; } diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java index dbd3f8c902e5..b3cba24540de 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java @@ -36,10 +36,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -/** - * - * @author Kirill Likhodedov - */ class GitBranchPopupActions { private final Project myProject; @@ -123,7 +119,7 @@ class GitBranchPopupActions { public void update(AnActionEvent e) { if (myRepository.isFresh()) { e.getPresentation().setEnabled(false); - e.getPresentation().setDescription("Checkout is not possible before the first commit."); + e.getPresentation().setDescription("Checkout is not possible before the first commit"); } } } diff --git a/plugins/git4idea/src/git4idea/update/GitRebaseUpdater.java b/plugins/git4idea/src/git4idea/update/GitRebaseUpdater.java index 04ed3ac845ca..e22c15076170 100644 --- a/plugins/git4idea/src/git4idea/update/GitRebaseUpdater.java +++ b/plugins/git4idea/src/git4idea/update/GitRebaseUpdater.java @@ -18,12 +18,10 @@ package git4idea.update; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Ref; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.VcsNotifier; import com.intellij.openapi.vcs.update.UpdatedFiles; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.ui.UIUtil; import git4idea.GitBranch; import git4idea.GitUtil; import git4idea.branch.GitBranchPair; @@ -78,42 +76,12 @@ public class GitRebaseUpdater extends GitUpdater { return dest.getName(); } - // TODO - //if (!checkLocallyModified(myRoot)) { - // cancel(); - // updateSucceeded.set(false); - //} - - - // TODO: show at any case of update successfullibility, also don't show here but for all roots - //if (mySkippedCommits.size() > 0) { - // GitSkippedCommits.showSkipped(myProject, mySkippedCommits); - //} - public void cancel() { myRebaser.abortRebase(myRoot); myProgressIndicator.setText2("Refreshing files for the root " + myRoot.getPath()); myRoot.refresh(false, true); } - /** - * Check and process locally modified files - * - * @param root the project root - * @param ex the exception holder - */ - protected boolean checkLocallyModified(final VirtualFile root) throws VcsException { - final Ref<Boolean> cancelled = new Ref<Boolean>(false); - UIUtil.invokeAndWaitIfNeeded(new Runnable() { - public void run() { - if (!GitUpdateLocallyModifiedDialog.showIfNeeded(myProject, root)) { - cancelled.set(true); - } - } - }); - return !cancelled.get(); - } - @Override public String toString() { return "Rebase updater"; diff --git a/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.form b/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.form deleted file mode 100644 index a97507f24ec9..000000000000 --- a/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.form +++ /dev/null @@ -1,71 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="git4idea.update.GitUpdateLocallyModifiedDialog"> - <grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> - <margin top="0" left="0" bottom="0" right="0"/> - <constraints> - <xy x="20" y="20" width="514" height="322"/> - </constraints> - <properties/> - <border type="none"/> - <children> - <component id="62c84" class="javax.swing.JLabel"> - <constraints> - <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> - </constraints> - <properties> - <text resource-bundle="git4idea/i18n/GitBundle" key="update.locally.modified.git.root"/> - </properties> - </component> - <component id="24443" class="javax.swing.JLabel" binding="myGitRoot"> - <constraints> - <grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/> - </constraints> - <properties> - <text value=""/> - </properties> - </component> - <component id="e43af" class="javax.swing.JLabel" binding="myDescriptionLabel"> - <constraints> - <grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> - </constraints> - <properties> - <text value=""/> - </properties> - </component> - <scrollpane class="com.intellij.ui.components.JBScrollPane" id="bde6e"> - <constraints> - <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/> - </constraints> - <properties/> - <border type="none"/> - <children> - <component id="5d604" class="com.intellij.ui.components.JBList" binding="myFilesList" default-binding="true"> - <constraints/> - <properties> - <toolTipText resource-bundle="git4idea/i18n/GitBundle" key="update.locally.modified.files.tooltip"/> - </properties> - </component> - </children> - </scrollpane> - <component id="8f763" class="javax.swing.JButton" binding="myRescanButton" default-binding="true"> - <constraints> - <grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="false"/> - </constraints> - <properties> - <text resource-bundle="git4idea/i18n/GitBundle" key="update.locally.modified.rescan"/> - <toolTipText resource-bundle="git4idea/i18n/GitBundle" key="update.locally.modified.rescan.tooltip"/> - </properties> - </component> - <component id="ab434" class="javax.swing.JLabel"> - <constraints> - <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/> - </constraints> - <properties> - <labelFor value="bde6e"/> - <text resource-bundle="git4idea/i18n/GitBundle" key="update.locally.modified.files"/> - <verticalAlignment value="0"/> - </properties> - </component> - </children> - </grid> -</form> diff --git a/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.java b/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.java deleted file mode 100644 index c3384cea20b0..000000000000 --- a/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package git4idea.update; - -import com.intellij.openapi.application.ApplicationNamesInfo; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.ui.UIUtil; -import com.intellij.vcsUtil.VcsUtil; -import git4idea.GitUtil; -import git4idea.commands.GitCommand; -import git4idea.commands.GitSimpleHandler; -import git4idea.util.StringScanner; -import git4idea.i18n.GitBundle; -import git4idea.rollback.GitRollbackEnvironment; -import git4idea.util.GitUIUtil; - -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * The dialog that displays locally modified files during update process - */ -public class GitUpdateLocallyModifiedDialog extends DialogWrapper { - /** - * The rescan button - */ - private JButton myRescanButton; - /** - * The list of files to revert - */ - private JList myFilesList; - - private JLabel myDescriptionLabel; - /** - * The git root label - */ - private JLabel myGitRoot; - /** - * The root panel - */ - private JPanel myRootPanel; - /** - * The collection with locally modified files - */ - private final List<String> myLocallyModifiedFiles; - - /** - * The constructor - * - * @param project the current project - * @param root the vcs root - * @param locallyModifiedFiles the collection of locally modified files to use - */ - protected GitUpdateLocallyModifiedDialog(final Project project, final VirtualFile root, List<String> locallyModifiedFiles) { - super(project, true); - myLocallyModifiedFiles = locallyModifiedFiles; - setTitle(GitBundle.getString("update.locally.modified.title")); - myGitRoot.setText(root.getPresentableUrl()); - myFilesList.setModel(new DefaultListModel()); - setOKButtonText(GitBundle.getString("update.locally.modified.revert")); - syncListModel(); - myRescanButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - myLocallyModifiedFiles.clear(); - try { - scanFiles(project, root, myLocallyModifiedFiles); - } - catch (VcsException ex) { - GitUIUtil.showOperationError(project, ex, "Checking for locally modified files"); - } - } - }); - myDescriptionLabel - .setText(GitBundle.message("update.locally.modified.message", ApplicationNamesInfo.getInstance().getFullProductName())); - init(); - } - - /** - * Refresh list model according to the current content of the collection - */ - private void syncListModel() { - DefaultListModel listModel = (DefaultListModel)myFilesList.getModel(); - listModel.removeAllElements(); - for (String p : myLocallyModifiedFiles) { - listModel.addElement(p); - } - } - - /** - * {@inheritDoc} - */ - @Override - protected JComponent createCenterPanel() { - return myRootPanel; - } - - /** - * {@inheritDoc} - */ - @Override - protected String getDimensionServiceKey() { - return getClass().getName(); - } - - /** - * Scan working tree and detect locally modified files - * - * @param project the project to scan - * @param root the root to scan - * @param files the collection with files - * @throws VcsException if there problem with running git or working tree is dirty in unsupported way - */ - private static void scanFiles(Project project, VirtualFile root, List<String> files) throws VcsException { - String rootPath = root.getPath(); - GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.DIFF); - h.addParameters("--name-status"); - h.setSilent(true); - h.setStdoutSuppressed(true); - StringScanner s = new StringScanner(h.run()); - while (s.hasMoreData()) { - if (s.isEol()) { - s.line(); - continue; - } - if (s.tryConsume("M\t")) { - String path = rootPath + "/" + GitUtil.unescapePath(s.line()); - files.add(path); - } - else { - throw new VcsException("Working tree is dirty in unsupported way: " + s.line()); - } - } - } - - - /** - * Show the dialog if needed - * - * @param project the project - * @param root the vcs root - * @return true if showing is not needed or operation completed successfully - */ - public static boolean showIfNeeded(final Project project, final VirtualFile root) { - final ArrayList<String> files = new ArrayList<String>(); - try { - scanFiles(project, root, files); - final AtomicBoolean rc = new AtomicBoolean(true); - if (!files.isEmpty()) { - UIUtil.invokeAndWaitIfNeeded(new Runnable() { - public void run() { - GitUpdateLocallyModifiedDialog d = new GitUpdateLocallyModifiedDialog(project, root, files); - d.show(); - rc.set(d.isOK()); - } - }); - if (rc.get()) { - if (!files.isEmpty()) { - revertFiles(project, root, files); - } - } - } - return rc.get(); - } - catch (final VcsException e) { - UIUtil.invokeAndWaitIfNeeded(new Runnable() { - public void run() { - GitUIUtil.showOperationError(project, e, "Checking for locally modified files"); - } - }); - return false; - } - } - - /** - * Revert files from the list - * - * @param project the project - * @param root the vcs root - * @param files the files to revert - */ - private static void revertFiles(Project project, VirtualFile root, ArrayList<String> files) throws VcsException { - // TODO consider deleted files - GitRollbackEnvironment rollback = GitRollbackEnvironment.getInstance(project); - ArrayList<FilePath> list = new ArrayList<FilePath>(files.size()); - for (String p : files) { - list.add(VcsUtil.getFilePath(p)); - } - rollback.revert(root, list); - } -} diff --git a/plugins/git4idea/src/git4idea/util/LocalChangesWouldBeOverwrittenHelper.java b/plugins/git4idea/src/git4idea/util/LocalChangesWouldBeOverwrittenHelper.java index 021ce824b9a7..7659c50e362a 100644 --- a/plugins/git4idea/src/git4idea/util/LocalChangesWouldBeOverwrittenHelper.java +++ b/plugins/git4idea/src/git4idea/util/LocalChangesWouldBeOverwrittenHelper.java @@ -35,12 +35,12 @@ import java.util.List; public class LocalChangesWouldBeOverwrittenHelper { @NotNull - public static String getErrorNotificationDescription() { + private static String getErrorNotificationDescription() { return getErrorDescription(true); } @NotNull - public static String getErrorDialogDescription() { + private static String getErrorDialogDescription() { return getErrorDescription(false); } @@ -56,7 +56,7 @@ public class LocalChangesWouldBeOverwrittenHelper { } } - public static void showErrorNotification(@NotNull final Project project, @NotNull VirtualFile root, @NotNull final String operationName, + public static void showErrorNotification(@NotNull final Project project, @NotNull final VirtualFile root, @NotNull final String operationName, @NotNull final Collection<String> relativeFilePaths) { final Collection<String> absolutePaths = GitUtil.toAbsolute(root, relativeFilePaths); final List<Change> changes = GitUtil.findLocalChangesForPaths(project, root, absolutePaths, false); @@ -66,20 +66,33 @@ public class LocalChangesWouldBeOverwrittenHelper { @Override protected void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent e) { - String title = "Local Changes Prevent from " + StringUtil.capitalize(operationName); - String description = getErrorDialogDescription(); - if (changes.isEmpty()) { - GitUtil.showPathsInDialog(project, absolutePaths, title, description); - } - else { - DialogBuilder builder = new DialogBuilder(project); - builder.setNorthPanel(new MultiLineLabel(description)); - builder.setCenterPanel(new ChangesBrowserWithRollback(project, changes)); - builder.addOkAction(); - builder.setTitle(title); - builder.show(); - } + showErrorDialog(project, operationName, changes, absolutePaths); } }); } + + public static void showErrorDialog(@NotNull Project project, @NotNull VirtualFile root, @NotNull String operationName, + @NotNull Collection<String> relativeFilePaths) { + Collection<String> absolutePaths = GitUtil.toAbsolute(root, relativeFilePaths); + List<Change> changes = GitUtil.findLocalChangesForPaths(project, root, absolutePaths, false); + showErrorDialog(project, operationName, changes, absolutePaths); + } + + private static void showErrorDialog(@NotNull Project project, @NotNull String operationName, @NotNull List<Change> changes, + @NotNull Collection<String> absolutePaths) { + String title = "Local Changes Prevent from " + StringUtil.capitalize(operationName); + String description = getErrorDialogDescription(); + if (changes.isEmpty()) { + GitUtil.showPathsInDialog(project, absolutePaths, title, description); + } + else { + DialogBuilder builder = new DialogBuilder(project); + builder.setNorthPanel(new MultiLineLabel(description)); + builder.setCenterPanel(new ChangesBrowserWithRollback(project, changes)); + builder.addOkAction(); + builder.setTitle(title); + builder.show(); + } + } + } diff --git a/plugins/git4idea/tests/git4idea/history/GitHistoryUtilsTest.java b/plugins/git4idea/tests/git4idea/history/GitHistoryUtilsTest.java index 29072ea53940..bdf87b265427 100644 --- a/plugins/git4idea/tests/git4idea/history/GitHistoryUtilsTest.java +++ b/plugins/git4idea/tests/git4idea/history/GitHistoryUtilsTest.java @@ -38,9 +38,9 @@ import java.io.File; import java.io.IOException; import java.util.*; +import static com.intellij.dvcs.DvcsUtil.getShortHash; import static com.intellij.openapi.vcs.Executor.overwrite; import static com.intellij.openapi.vcs.Executor.touch; -import static git4idea.GitUtil.getShortHash; import static git4idea.test.GitExecutor.*; import static git4idea.test.GitTestUtil.USER_EMAIL; import static git4idea.test.GitTestUtil.USER_NAME; diff --git a/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java b/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java index 14d88315c596..2ce560800066 100644 --- a/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java +++ b/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java @@ -3,6 +3,7 @@ package git4idea.log; import com.intellij.mock.MockVirtualFile; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.UsefulTestCase; import com.intellij.util.Function; @@ -285,6 +286,12 @@ public class GitRefManagerTest extends UsefulTestCase { @Nullable @Override + public AbstractVcs getVcs() { + return null; + } + + @Nullable + @Override public String getCurrentRevision() { throw new UnsupportedOperationException(); } diff --git a/plugins/github/github.iml b/plugins/github/github.iml index 54d546aa0886..7866631c1521 100644 --- a/plugins/github/github.iml +++ b/plugins/github/github.iml @@ -18,7 +18,8 @@ <orderEntry type="module" module-name="platform-impl" /> <orderEntry type="module" module-name="util" /> <orderEntry type="library" name="gson" level="project" /> - <orderEntry type="module" module-name="dvcs" /> + <orderEntry type="module" module-name="dvcs-impl" /> + <orderEntry type="module" module-name="dvcs-api" /> <orderEntry type="module" module-name="testFramework" scope="TEST" /> <orderEntry type="module" module-name="xml-openapi" /> <orderEntry type="module" module-name="xml" /> diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java index bfceb0ceec39..719f8b956432 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java @@ -48,6 +48,7 @@ import org.jetbrains.plugins.github.util.*; import java.io.IOException; import java.util.Collections; +import static git4idea.commands.GitLocalChangesWouldBeOverwrittenDetector.Operation.CHECKOUT; import static org.jetbrains.plugins.github.util.GithubUtil.setVisibleEnabled; /** @@ -256,7 +257,9 @@ public class GithubRebaseAction extends DumbAwareAction { final GitUntrackedFilesOverwrittenByOperationDetector untrackedFilesDetector = new GitUntrackedFilesOverwrittenByOperationDetector(root); + final GitLocalChangesWouldBeOverwrittenDetector localChangesDetector = new GitLocalChangesWouldBeOverwrittenDetector(root, CHECKOUT); handler.addLineListener(untrackedFilesDetector); + handler.addLineListener(localChangesDetector); GitTask pullTask = new GitTask(project, handler, "Rebasing from upstream/master"); pullTask.setProgressIndicator(indicator); @@ -271,7 +274,8 @@ public class GithubRebaseAction extends DumbAwareAction { @Override protected void onFailure() { - GitUpdateResult result = rebaser.handleRebaseFailure(handler, root, rebaseConflictDetector, untrackedFilesDetector); + GitUpdateResult result = rebaser.handleRebaseFailure(handler, root, rebaseConflictDetector, + untrackedFilesDetector, localChangesDetector); repositoryManager.updateRepository(root); if (result == GitUpdateResult.NOTHING_TO_UPDATE || result == GitUpdateResult.SUCCESS || diff --git a/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineFacetEditor.java b/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineFacetEditor.java index 6e45480f1156..a01878f1e29d 100644 --- a/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineFacetEditor.java +++ b/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineFacetEditor.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. @@ -60,6 +60,7 @@ public class AppEngineFacetEditor extends FacetEditorTab { myContext = context; mySdkEditor = new AppEngineSdkEditor(myContext.getProject()); validatorsManager.registerValidator(new FacetEditorValidator() { + @NotNull @Override public ValidationResult check() { return AppEngineSdkUtil.checkPath(mySdkEditor.getPath()); diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml index f15f424a10b8..f00346625e81 100644 --- a/plugins/gradle/src/META-INF/plugin.xml +++ b/plugins/gradle/src/META-INF/plugin.xml @@ -106,6 +106,7 @@ <applicationService serviceImplementation="org.jetbrains.plugins.gradle.service.GradleInstallationManager"/> + <applicationService serviceImplementation="org.jetbrains.plugins.gradle.settings.GradleSystemSettings"/> <projectService serviceImplementation="org.jetbrains.plugins.gradle.settings.GradleSettings"/> <projectService serviceImplementation="org.jetbrains.plugins.gradle.settings.GradleLocalSettings"/> <projectService serviceImplementation="org.jetbrains.plugins.gradle.service.project.GradleNotification"/> diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeSuiteEvent.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeSuiteEvent.java index 85e06cdc7dda..c9a69b0987d6 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeSuiteEvent.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeSuiteEvent.java @@ -47,10 +47,10 @@ public class BeforeSuiteEvent extends AbstractTestEvent { getConsoleManager().getTestsMap().put(testId, testProxy); final SMTestProxy parentTestProxy = getConsoleManager().getTestsMap().get(parentTestId); if (parentTestProxy != null) { - parentTestProxy.addChild(testProxy); addToInvokeLater(new Runnable() { @Override public void run() { + parentTestProxy.addChild(testProxy); getResultsViewer().onSuiteStarted(testProxy); } }); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeTestEvent.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeTestEvent.java index bd512bc65b8a..8b7976406e2f 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeTestEvent.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeTestEvent.java @@ -46,12 +46,22 @@ public class BeforeTestEvent extends AbstractTestEvent { getConsoleManager().getTestsMap().put(testId, testProxy); if (StringUtil.isEmpty(parentTestId)) { - getResultsViewer().getTestsRootNode().addChild(testProxy); + addToInvokeLater(new Runnable() { + @Override + public void run() { + getResultsViewer().getTestsRootNode().addChild(testProxy); + } + }); } else { final SMTestProxy parentTestProxy = getConsoleManager().getTestsMap().get(parentTestId); if (parentTestProxy != null) { - parentTestProxy.addChild(testProxy); + addToInvokeLater(new Runnable() { + @Override + public void run() { + parentTestProxy.addChild(testProxy); + } + }); } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java index d85e6cf1a742..db1569965d4a 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java @@ -30,26 +30,24 @@ import java.util.Set; /** * Holds shared project-level gradle-related settings (should be kept at the '*.ipr' or under '.idea'). - * + * * @author peter */ @State( - name = "GradleSettings", - storages = { - @Storage(file = StoragePathMacros.PROJECT_FILE), - @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/gradle.xml", scheme = StorageScheme.DIRECTORY_BASED) - } + name = "GradleSettings", + storages = { + @Storage(file = StoragePathMacros.PROJECT_FILE), + @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/gradle.xml", scheme = StorageScheme.DIRECTORY_BASED) + } ) public class GradleSettings extends AbstractExternalSystemSettings<GradleSettings, GradleProjectSettings, GradleSettingsListener> - implements PersistentStateComponent<GradleSettings.MyState> -{ + implements PersistentStateComponent<GradleSettings.MyState> { - @Nullable private String myServiceDirectoryPath; - @Nullable private String myGradleVmOptions; - private boolean myIsOfflineWork; + private final GradleSystemSettings mySystemSettings; public GradleSettings(@NotNull Project project) { super(GradleSettingsListener.TOPIC, project); + mySystemSettings = GradleSystemSettings.getInstance(); } @NotNull @@ -65,9 +63,6 @@ public class GradleSettings extends AbstractExternalSystemSettings<GradleSetting @Override protected void copyExtraSettingsFrom(@NotNull GradleSettings settings) { - myServiceDirectoryPath = settings.getServiceDirectoryPath(); - myGradleVmOptions = settings.getGradleVmOptions(); - myIsOfflineWork = settings.isOfflineWork(); } @SuppressWarnings("unchecked") @@ -76,58 +71,52 @@ public class GradleSettings extends AbstractExternalSystemSettings<GradleSetting public GradleSettings.MyState getState() { MyState state = new MyState(); fillState(state); - state.serviceDirectoryPath = myServiceDirectoryPath; - state.gradleVmOptions = myGradleVmOptions; - state.offlineWork = myIsOfflineWork; return state; } @Override public void loadState(MyState state) { super.loadState(state); - myServiceDirectoryPath = state.serviceDirectoryPath; - myGradleVmOptions = state.gradleVmOptions; - myIsOfflineWork = state.offlineWork; } /** * @return service directory path (if defined). 'Service directory' is a directory which is used internally by gradle during - * calls to the tooling api. E.g. it holds downloaded binaries (dependency jars). We allow to define it because there - * is a possible situation when a user wants to configure particular directory to be excluded from anti-virus protection - * in order to increase performance + * calls to the tooling api. E.g. it holds downloaded binaries (dependency jars). We allow to define it because there + * is a possible situation when a user wants to configure particular directory to be excluded from anti-virus protection + * in order to increase performance */ @Nullable public String getServiceDirectoryPath() { - return myServiceDirectoryPath; + return mySystemSettings.getServiceDirectoryPath(); } public void setServiceDirectoryPath(@Nullable String newPath) { + String myServiceDirectoryPath = mySystemSettings.getServiceDirectoryPath(); if (!Comparing.equal(myServiceDirectoryPath, newPath)) { - String oldPath = myServiceDirectoryPath; - myServiceDirectoryPath = newPath; - getPublisher().onServiceDirectoryPathChange(oldPath, newPath); - } + mySystemSettings.setServiceDirectoryPath(newPath); + getPublisher().onServiceDirectoryPathChange(myServiceDirectoryPath, newPath); + } } @Nullable public String getGradleVmOptions() { - return myGradleVmOptions; + return mySystemSettings.getGradleVmOptions(); } - + public void setGradleVmOptions(@Nullable String gradleVmOptions) { + String myGradleVmOptions = mySystemSettings.getGradleVmOptions(); if (!Comparing.equal(myGradleVmOptions, gradleVmOptions)) { - String old = myGradleVmOptions; - myGradleVmOptions = gradleVmOptions; - getPublisher().onGradleVmOptionsChange(old, gradleVmOptions); + mySystemSettings.setGradleVmOptions(gradleVmOptions); + getPublisher().onGradleVmOptionsChange(myGradleVmOptions, gradleVmOptions); } } public boolean isOfflineWork() { - return myIsOfflineWork; + return mySystemSettings.isOfflineWork(); } public void setOfflineWork(boolean isOfflineWork) { - myIsOfflineWork = isOfflineWork; + mySystemSettings.setOfflineWork(isOfflineWork); } @Override @@ -143,9 +132,6 @@ public class GradleSettings extends AbstractExternalSystemSettings<GradleSetting public static class MyState implements State<GradleProjectSettings> { private Set<GradleProjectSettings> myProjectSettings = ContainerUtilRt.newTreeSet(); - public String serviceDirectoryPath; - public String gradleVmOptions; - public boolean offlineWork; @AbstractCollection(surroundWithTag = false, elementTypes = {GradleProjectSettings.class}) public Set<GradleProjectSettings> getLinkedExternalProjectsSettings() { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSystemSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSystemSettings.java new file mode 100644 index 000000000000..b24bd24cbf0d --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSystemSettings.java @@ -0,0 +1,92 @@ +/* + * 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 org.jetbrains.plugins.gradle.settings; + +import com.intellij.openapi.components.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Vladislav.Soroka + * @since 14/8/2014 + */ +@State( + name = "GradleSystemSettings", + storages = { + @Storage(file = StoragePathMacros.APP_CONFIG + "/gradle.settings.xml") + } +) +public class GradleSystemSettings implements PersistentStateComponent<GradleSystemSettings.MyState> { + + @Nullable private String myServiceDirectoryPath; + @Nullable private String myGradleVmOptions; + private boolean myIsOfflineWork; + + @NotNull + public static GradleSystemSettings getInstance() { + return ServiceManager.getService(GradleSystemSettings.class); + } + + @SuppressWarnings("unchecked") + @Nullable + @Override + public GradleSystemSettings.MyState getState() { + MyState state = new MyState(); + state.serviceDirectoryPath = myServiceDirectoryPath; + state.gradleVmOptions = myGradleVmOptions; + state.offlineWork = myIsOfflineWork; + return state; + } + + @Override + public void loadState(MyState state) { + myServiceDirectoryPath = state.serviceDirectoryPath; + myGradleVmOptions = state.gradleVmOptions; + myIsOfflineWork = state.offlineWork; + } + + @Nullable + public String getServiceDirectoryPath() { + return myServiceDirectoryPath; + } + + public void setServiceDirectoryPath(@Nullable String newPath) { + myServiceDirectoryPath = newPath; + } + + @Nullable + public String getGradleVmOptions() { + return myGradleVmOptions; + } + + public void setGradleVmOptions(@Nullable String gradleVmOptions) { + myGradleVmOptions = gradleVmOptions; + } + + public boolean isOfflineWork() { + return myIsOfflineWork; + } + + public void setOfflineWork(boolean isOfflineWork) { + myIsOfflineWork = isOfflineWork; + } + + public static class MyState { + public String serviceDirectoryPath; + public String gradleVmOptions; + public boolean offlineWork; + } +}
\ No newline at end of file diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/inspections/GroovySingletonAnnotationInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/inspections/GroovySingletonAnnotationInspection.java index e44ade2d6bd7..f43de1fbb993 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/inspections/GroovySingletonAnnotationInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/inspections/GroovySingletonAnnotationInspection.java @@ -36,6 +36,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; public class GroovySingletonAnnotationInspection extends BaseInspection { public static final String SINGLETON = GroovyCommonClassNames.GROOVY_LANG_SINGLETON; + @NotNull @Override protected BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java index 1d44e8978934..005e5e38a7a0 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java @@ -30,6 +30,7 @@ import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.*; import com.intellij.psi.impl.PsiSubstitutorImpl; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; @@ -67,6 +68,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnState import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrThrowStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrForInClause; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrString; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; @@ -85,6 +87,7 @@ import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParameterEnhan import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParamsEnhancer; import org.jetbrains.plugins.groovy.lang.psi.util.*; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; +import org.jetbrains.plugins.groovy.spock.SpockUtils; import javax.swing.*; import java.util.ArrayList; @@ -768,6 +771,8 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection { private void checkOperator(CallInfo<? extends GrBinaryExpression> info) { if (hasErrorElements(info.getCall())) return; + if (isSpockTimesOperator(info.getCall())) return; + GroovyResolveResult[] results = info.multiResolve(); GroovyResolveResult resolveResult = info.advancedResolve(); @@ -787,6 +792,20 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection { } } + private static boolean isSpockTimesOperator(GrBinaryExpression call) { + if (call.getOperationTokenType() == GroovyTokenTypes.mSTAR && PsiUtil.isExpressionStatement(call)) { + GrExpression operand = call.getLeftOperand(); + if (operand instanceof GrLiteral && TypesUtil.isNumericType(operand.getType())) { + PsiClass aClass = PsiUtil.getContextClass(call); + if (InheritanceUtil.isInheritor(aClass, false, SpockUtils.SPEC_CLASS_NAME)) { + return true; + } + } + } + + return false; + } + private static boolean isOperatorWithSimpleTypes(GrBinaryExpression binary, GroovyResolveResult result) { if (result.getElement() != null && result.isApplicable()) { return false; diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentCanBeOperatorAssignmentInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentCanBeOperatorAssignmentInspection.java index a419af33b55a..2fe54796e192 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentCanBeOperatorAssignmentInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentCanBeOperatorAssignmentInspection.java @@ -102,13 +102,14 @@ public class GroovyAssignmentCanBeOperatorAssignmentInspection return lhs.getText() + ' ' + signText + "= " + rhsRhs.getText(); } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new ReplaceAssignmentWithOperatorAssignmentVisitor(); } @Override - public GroovyFix buildFix(PsiElement location) { + public GroovyFix buildFix(@NotNull PsiElement location) { return new ReplaceAssignmentWithOperatorAssignmentFix( (GrAssignmentExpression) location); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentToForLoopParameterInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentToForLoopParameterInspection.java index 595a653dd63b..a031735e0e36 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentToForLoopParameterInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentToForLoopParameterInspection.java @@ -53,6 +53,7 @@ public class GroovyAssignmentToForLoopParameterInspection extends BaseInspection } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyNestedAssignmentInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyNestedAssignmentInspection.java index e191302f55b1..0a7a3808a959 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyNestedAssignmentInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyNestedAssignmentInspection.java @@ -45,6 +45,7 @@ public class GroovyNestedAssignmentInspection extends BaseInspection { return "Nested assignment expression #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyResultOfAssignmentUsedInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyResultOfAssignmentUsedInspection.java index 8a459b1e2d15..efdd32fb904b 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyResultOfAssignmentUsedInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyResultOfAssignmentUsedInspection.java @@ -45,6 +45,7 @@ public class GroovyResultOfAssignmentUsedInspection extends BaseInspection { return "Result of assignment expression used #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyConstructorNamedArgumentsInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyConstructorNamedArgumentsInspection.java index 6941d89878cc..13ee4c229cc0 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyConstructorNamedArgumentsInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyConstructorNamedArgumentsInspection.java @@ -49,6 +49,7 @@ public class GroovyConstructorNamedArgumentsInspection extends BaseInspection { return true; } + @NotNull @Override protected BaseInspectionVisitor buildVisitor() { return new MyVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDivideByZeroInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDivideByZeroInspection.java index e5db424089fa..02b8f38a9fe8 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDivideByZeroInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDivideByZeroInspection.java @@ -55,6 +55,7 @@ public class GroovyDivideByZeroInspection extends BaseInspection { return true; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDocCheckInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDocCheckInspection.java index 1145def39ff8..a4263ea34798 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDocCheckInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDocCheckInspection.java @@ -59,6 +59,7 @@ public class GroovyDocCheckInspection extends BaseInspection { return true; } + @NotNull @Override protected BaseInspectionVisitor buildVisitor() { return new BaseInspectionVisitor() { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteLoopStatementInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteLoopStatementInspection.java index bd5a2b202ee4..d6dede4fdabf 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteLoopStatementInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteLoopStatementInspection.java @@ -51,6 +51,7 @@ public class GroovyInfiniteLoopStatementInspection extends BaseInspection { return true; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteRecursionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteRecursionInspection.java index 62ad7165a153..7fc52f210c1b 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteRecursionInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteRecursionInspection.java @@ -51,6 +51,7 @@ public class GroovyInfiniteRecursionInspection extends BaseInspection { return true; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyLabeledStatementInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyLabeledStatementInspection.java index 49d173d5584a..4d1856c3d151 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyLabeledStatementInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyLabeledStatementInspection.java @@ -29,6 +29,7 @@ import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; * @author Maxim.Medvedev */ public class GroovyLabeledStatementInspection extends BaseInspection { + @NotNull @Override protected BaseInspectionVisitor buildVisitor() { return new MyVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyNonShortCircuitBooleanInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyNonShortCircuitBooleanInspection.java index c81175e3070b..d3c8de759037 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyNonShortCircuitBooleanInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyNonShortCircuitBooleanInspection.java @@ -60,7 +60,7 @@ public class GroovyNonShortCircuitBooleanInspection extends BaseInspection { } @Override - public GroovyFix buildFix(PsiElement location) { + public GroovyFix buildFix(@NotNull PsiElement location) { return new NonShortCircuitBooleanFix(); } @@ -96,6 +96,7 @@ public class GroovyNonShortCircuitBooleanInspection extends BaseInspection { } } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyResultOfObjectAllocationIgnoredInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyResultOfObjectAllocationIgnoredInspection.java index 19c83142d04c..920878223090 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyResultOfObjectAllocationIgnoredInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyResultOfObjectAllocationIgnoredInspection.java @@ -57,6 +57,7 @@ public class GroovyResultOfObjectAllocationIgnoredInspection extends BaseInspect return true; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/NewInstanceOfSingletonInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/NewInstanceOfSingletonInspection.java index 479f79f74cda..74162fe82c34 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/NewInstanceOfSingletonInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/NewInstanceOfSingletonInspection.java @@ -41,6 +41,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; public class NewInstanceOfSingletonInspection extends BaseInspection { private static final Logger LOG = Logger.getInstance(NewInstanceOfSingletonInspection.class); + @NotNull @Override protected BaseInspectionVisitor buildVisitor() { return new BaseInspectionVisitor() { @@ -67,7 +68,7 @@ public class NewInstanceOfSingletonInspection extends BaseInspection { } @Override - protected GroovyFix buildFix(final PsiElement location) { + protected GroovyFix buildFix(@NotNull final PsiElement location) { final GrCodeReferenceElement refElement = ((GrNewExpression)location).getReferenceElement(); LOG.assertTrue(refElement != null); final GrTypeDefinition singleton = (GrTypeDefinition)refElement.resolve(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspectionBase.java new file mode 100644 index 000000000000..4195dd9a11ae --- /dev/null +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspectionBase.java @@ -0,0 +1,153 @@ +/* + * 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 org.jetbrains.plugins.groovy.codeInspection.confusing; + +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.HierarchicalMethodSignature; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiModifier; +import com.intellij.psi.util.PsiFormatUtil; +import com.intellij.psi.util.PsiFormatUtilBase; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.codeInspection.BaseInspection; +import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor; +import org.jetbrains.plugins.groovy.codeInspection.GroovyFix; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrTraitMethod; +import org.jetbrains.plugins.groovy.lang.psi.util.GrTraitUtil; + +import java.util.Collection; +import java.util.List; + +public abstract class ClashingTraitMethodsInspectionBase extends BaseInspection { + protected static final Logger LOG = Logger.getInstance(ClashingTraitMethodsInspectionBase.class); + + @NotNull + protected static List<ClashingMethod> collectClassingMethods(@NotNull GrTypeDefinition typeDefinition) { + Collection<HierarchicalMethodSignature> visibleSignatures = typeDefinition.getVisibleSignatures(); + + List<ClashingMethod> clashingMethods = ContainerUtil.newArrayList(); + for (HierarchicalMethodSignature signature : visibleSignatures) { + PsiMethod method = signature.getMethod(); + if (method instanceof GrTraitMethod && method.getContainingClass() == typeDefinition) { + List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures(); + if (superSignatures.size() > 1) { + List<GrTypeDefinition> traits = ContainerUtil.newArrayList(); + for (HierarchicalMethodSignature superSignature : superSignatures) { + PsiMethod superMethod = superSignature.getMethod(); + PsiClass superClass = superMethod.getContainingClass(); + if (GrTraitUtil.isTrait(superClass) && + !superMethod.getModifierList().hasExplicitModifier(PsiModifier.ABSTRACT)) { + traits.add((GrTypeDefinition)superClass); + } + } + + if (traits.size() > 1) { + clashingMethods.add(new ClashingMethod(signature, traits)); + } + } + } + } + + return clashingMethods; + } + + @NotNull + private static List<PsiClass> collectImplementedTraits(@NotNull GrTypeDefinition typeDefinition) { + return ContainerUtil.findAll(typeDefinition.getSupers(), new Condition<PsiClass>() { + @Override + public boolean value(PsiClass aClass) { + return GrTraitUtil.isTrait(aClass); + } + }); + } + + @NotNull + @Override + protected BaseInspectionVisitor buildVisitor() { + return new BaseInspectionVisitor() { + @Override + public void visitTypeDefinition(GrTypeDefinition typeDefinition) { + super.visitTypeDefinition(typeDefinition); + + List<PsiClass> superTraits = collectImplementedTraits(typeDefinition); + + if (superTraits.size() < 2) return; + + List<ClashingMethod> clashingMethods = collectClassingMethods(typeDefinition); + + for (ClashingMethod clashing : clashingMethods) { + registerError(typeDefinition.getNameIdentifierGroovy(), buildWarning(clashing), new LocalQuickFix[]{getFix()}, ProblemHighlightType.GENERIC_ERROR_OR_WARNING); + } + } + + @NotNull + private String buildWarning(@NotNull ClashingMethod entry) { + return "Traits " + buildTraitString(entry) + " contain clashing methods with signature " + buildSignatureString(entry); + } + + @NotNull + private String buildSignatureString(@NotNull ClashingMethod entry) { + HierarchicalMethodSignature signature = entry.getSignature(); + return PsiFormatUtil.formatMethod(signature.getMethod(), signature.getSubstitutor(), + PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS, + PsiFormatUtilBase.SHOW_TYPE); + } + + @NotNull + private String buildTraitString(@NotNull ClashingMethod entry) { + return StringUtil.join(entry.getSuperTraits(), new Function<GrTypeDefinition, String>() { + @Override + public String fun(GrTypeDefinition tr) { + return tr.getName(); + } + }, ", "); + } + }; + } + + @NotNull + protected LocalQuickFix getFix(){ + return GroovyFix.EMPTY_FIX; + } + + protected static class ClashingMethod { + private final HierarchicalMethodSignature mySignature; + private final List<GrTypeDefinition> mySuperTraits; + + public ClashingMethod(@NotNull HierarchicalMethodSignature signature, @NotNull List<GrTypeDefinition> superTraits) { + mySignature = signature; + mySuperTraits = superTraits; + } + + @NotNull + public HierarchicalMethodSignature getSignature() { + return mySignature; + } + + @NotNull + public List<GrTypeDefinition> getSuperTraits() { + return mySuperTraits; + } + } +} diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrDeprecatedAPIUsageInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrDeprecatedAPIUsageInspection.java index 916ec5408d90..b8aa7570e08b 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrDeprecatedAPIUsageInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrDeprecatedAPIUsageInspection.java @@ -62,6 +62,7 @@ public class GrDeprecatedAPIUsageInspection extends BaseInspection { return "GrDeprecatedAPIUsage"; } + @NotNull @Override protected BaseInspectionVisitor buildVisitor() { return new BaseInspectionVisitor() { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrPackageInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrPackageInspection.java index 2b561b239112..8a1a6007f314 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrPackageInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrPackageInspection.java @@ -79,6 +79,7 @@ public class GrPackageInspection extends BaseInspection { } + @NotNull @Override protected BaseInspectionVisitor buildVisitor() { return new BaseInspectionVisitor() { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java index b5dc34e2318a..60ad30f642d5 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java @@ -51,6 +51,7 @@ import java.util.List; */ public class GrUnusedIncDecInspection extends BaseInspection { private static final Logger LOG = Logger.getInstance(GrUnusedIncDecInspection.class); + @NotNull @Override protected BaseInspectionVisitor buildVisitor() { return new GrUnusedIncDecInspectionVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyConditionalInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyConditionalInspection.java index 6b532066f1f5..55b314ef6b81 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyConditionalInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyConditionalInspection.java @@ -45,6 +45,7 @@ public class GroovyConditionalInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyDoubleNegationInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyDoubleNegationInspection.java index 7b22f17b289c..b293326196df 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyDoubleNegationInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyDoubleNegationInspection.java @@ -56,7 +56,7 @@ public class GroovyDoubleNegationInspection extends BaseInspection { @Override @Nullable - protected GroovyFix buildFix(PsiElement location) { + protected GroovyFix buildFix(@NotNull PsiElement location) { return new DoubleNegationFix(); } @@ -105,6 +105,7 @@ public class GroovyDoubleNegationInspection extends BaseInspection { } } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new DoubleNegationVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyEmptyStatementBodyInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyEmptyStatementBodyInspection.java index 4dd95e9e3b61..af8f89ad4aed 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyEmptyStatementBodyInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyEmptyStatementBodyInspection.java @@ -53,6 +53,7 @@ public class GroovyEmptyStatementBodyInspection extends BaseInspection { } } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedConditionalInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedConditionalInspection.java index e28e499cfb28..e6611c083e8b 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedConditionalInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedConditionalInspection.java @@ -47,6 +47,7 @@ public class GroovyNegatedConditionalInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedIfInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedIfInspection.java index 471428f83a13..611c292ae6d1 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedIfInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedIfInspection.java @@ -47,6 +47,7 @@ public class GroovyNegatedIfInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedConditionalInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedConditionalInspection.java index 621247d6563c..108c0ebd897b 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedConditionalInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedConditionalInspection.java @@ -46,6 +46,7 @@ public class GroovyNestedConditionalInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedSwitchInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedSwitchInspection.java index 72a16dda7ed6..ad289110f4f2 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedSwitchInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedSwitchInspection.java @@ -46,6 +46,7 @@ public class GroovyNestedSwitchInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOctalIntegerInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOctalIntegerInspection.java index e3bb3025508b..c9e587135a17 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOctalIntegerInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOctalIntegerInspection.java @@ -45,6 +45,7 @@ public class GroovyOctalIntegerInspection extends BaseInspection { return "Octal integer #ref #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new BaseInspectionVisitor() { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexArithmeticExpressionInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexArithmeticExpressionInspectionBase.java index 3d09c275ee3f..24b4d0ebb853 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexArithmeticExpressionInspectionBase.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexArithmeticExpressionInspectionBase.java @@ -60,6 +60,7 @@ public class GroovyOverlyComplexArithmeticExpressionInspectionBase extends BaseI return "Overly complex arithmetic expression #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexBooleanExpressionInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexBooleanExpressionInspectionBase.java index 73c74fb52d1f..6a4d9c0d54da 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexBooleanExpressionInspectionBase.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexBooleanExpressionInspectionBase.java @@ -54,6 +54,7 @@ public class GroovyOverlyComplexBooleanExpressionInspectionBase extends BaseInsp return "Overly complex boolean expression #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyPointlessBooleanInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyPointlessBooleanInspection.java index 8fe93903b567..7d1c46820771 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyPointlessBooleanInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyPointlessBooleanInspection.java @@ -59,6 +59,7 @@ public class GroovyPointlessBooleanInspection extends BaseInspection { return true; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new PointlessBooleanExpressionVisitor(); @@ -162,7 +163,7 @@ public class GroovyPointlessBooleanInspection extends BaseInspection { } @Override - public GroovyFix buildFix(PsiElement location) { + public GroovyFix buildFix(@NotNull PsiElement location) { return new BooleanLiteralComparisonFix(); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyResultOfIncrementOrDecrementUsedInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyResultOfIncrementOrDecrementUsedInspection.java index a750d6cf8f60..92e86425b685 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyResultOfIncrementOrDecrementUsedInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyResultOfIncrementOrDecrementUsedInspection.java @@ -47,6 +47,7 @@ public class GroovyResultOfIncrementOrDecrementUsedInspection extends BaseInspec return "Result of increment or decrement expression used #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyBreakInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyBreakInspection.java index 1ab73ccb92a6..9cb990edbf5c 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyBreakInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyBreakInspection.java @@ -47,6 +47,7 @@ public class GroovyBreakInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalCanBeElvisInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalCanBeElvisInspection.java index 9904a95466ae..a8d1678312ca 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalCanBeElvisInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalCanBeElvisInspection.java @@ -53,7 +53,7 @@ public class GroovyConditionalCanBeElvisInspection extends BaseInspection { } @Override - public GroovyFix buildFix(PsiElement location) { + public GroovyFix buildFix(@NotNull PsiElement location) { return new GroovyFix() { @Override @NotNull @@ -193,6 +193,7 @@ public class GroovyConditionalCanBeElvisInspection extends BaseInspection { return false; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalWithIdenticalBranchesInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalWithIdenticalBranchesInspection.java index 010d92ce95f2..bf26bfcc505e 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalWithIdenticalBranchesInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalWithIdenticalBranchesInspection.java @@ -51,7 +51,7 @@ public class GroovyConditionalWithIdenticalBranchesInspection extends BaseInspec } @Override - public GroovyFix buildFix(PsiElement location) { + public GroovyFix buildFix(@NotNull PsiElement location) { return new CollapseConditionalFix(); } @@ -72,6 +72,7 @@ public class GroovyConditionalWithIdenticalBranchesInspection extends BaseInspec } } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantConditionalInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantConditionalInspection.java index fb722f1e415d..a695bfce2c40 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantConditionalInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantConditionalInspection.java @@ -46,6 +46,7 @@ public class GroovyConstantConditionalInspection extends BaseInspection { return true; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new ConstantConditionalExpressionVisitor(); @@ -72,7 +73,7 @@ public class GroovyConstantConditionalInspection extends BaseInspection { } @Override - public GroovyFix buildFix(PsiElement location) { + public GroovyFix buildFix(@NotNull PsiElement location) { return new ConstantConditionalFix(); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantIfStatementInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantIfStatementInspection.java index d03f36f9f1fa..09dd8abbd7d4 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantIfStatementInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantIfStatementInspection.java @@ -53,13 +53,14 @@ public class GroovyConstantIfStatementInspection extends BaseInspection { return "#ref statement can be simplified #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new ConstantIfStatementVisitor(); } @Override - public GroovyFix buildFix(PsiElement location) { + public GroovyFix buildFix(@NotNull PsiElement location) { return new ConstantIfStatementFix(); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyContinueInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyContinueInspection.java index ddbd809a4fb5..0f582df06bfe 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyContinueInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyContinueInspection.java @@ -45,6 +45,7 @@ public class GroovyContinueInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyFallthroughInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyFallthroughInspection.java index 01871afa1ec8..d203771f827b 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyFallthroughInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyFallthroughInspection.java @@ -59,6 +59,7 @@ public class GroovyFallthroughInspection extends BaseInspection { return true; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithIdenticalBranchesInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithIdenticalBranchesInspection.java index 02d779807d40..62b1371282a8 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithIdenticalBranchesInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithIdenticalBranchesInspection.java @@ -51,7 +51,7 @@ public class GroovyIfStatementWithIdenticalBranchesInspection extends BaseInspec } @Override - public GroovyFix buildFix(PsiElement location) { + public GroovyFix buildFix(@NotNull PsiElement location) { return new CollapseIfFix(); } @@ -73,6 +73,7 @@ public class GroovyIfStatementWithIdenticalBranchesInspection extends BaseInspec } } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new IfStatementWithIdenticalBranchesVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithTooManyBranchesInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithTooManyBranchesInspectionBase.java index 078728b03410..d5f8c3b0e9dc 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithTooManyBranchesInspectionBase.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithTooManyBranchesInspectionBase.java @@ -63,6 +63,7 @@ public class GroovyIfStatementWithTooManyBranchesInspectionBase extends BaseInsp return "'#ref' statement with too many branches (" + branches + ") #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyLoopStatementThatDoesntLoopInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyLoopStatementThatDoesntLoopInspection.java index 38e155dd2d61..fa8fa75f27cd 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyLoopStatementThatDoesntLoopInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyLoopStatementThatDoesntLoopInspection.java @@ -48,6 +48,7 @@ public class GroovyLoopStatementThatDoesntLoopInspection extends BaseInspection } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyReturnFromClosureCanBeImplicitInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyReturnFromClosureCanBeImplicitInspection.java index 24230816d8a8..5f10109a5b14 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyReturnFromClosureCanBeImplicitInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyReturnFromClosureCanBeImplicitInspection.java @@ -55,6 +55,7 @@ public class GroovyReturnFromClosureCanBeImplicitInspection extends BaseInspecti } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); @@ -62,7 +63,7 @@ public class GroovyReturnFromClosureCanBeImplicitInspection extends BaseInspecti @Override @Nullable - protected GroovyFix buildFix(PsiElement location) { + protected GroovyFix buildFix(@NotNull PsiElement location) { return new MakeReturnImplicitFix(); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovySwitchStatementWithNoDefaultInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovySwitchStatementWithNoDefaultInspection.java index f8ea7794d15b..f76d79ab8fcd 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovySwitchStatementWithNoDefaultInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovySwitchStatementWithNoDefaultInspection.java @@ -46,6 +46,7 @@ public class GroovySwitchStatementWithNoDefaultInspection extends BaseInspection } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialConditionalInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialConditionalInspection.java index 277c77316e69..a65f3b6f987a 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialConditionalInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialConditionalInspection.java @@ -49,6 +49,7 @@ public class GroovyTrivialConditionalInspection extends BaseInspection { return true; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new UnnecessaryConditionalExpressionVisitor(); @@ -73,7 +74,7 @@ public class GroovyTrivialConditionalInspection extends BaseInspection { } @Override - public GroovyFix buildFix(PsiElement location) { + public GroovyFix buildFix(@NotNull PsiElement location) { return new TrivialConditionalFix(); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialIfInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialIfInspection.java index 6487e8e97aca..4be923268b10 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialIfInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialIfInspection.java @@ -51,6 +51,7 @@ public class GroovyTrivialIfInspection extends BaseInspection { return CONTROL_FLOW; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new TrivialIfVisitor(); @@ -67,7 +68,7 @@ public class GroovyTrivialIfInspection extends BaseInspection { } @Override - public GroovyFix buildFix(PsiElement location) { + public GroovyFix buildFix(@NotNull PsiElement location) { return new TrivialIfFix(); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryContinueInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryContinueInspection.java index 145f543ad82c..bd90f8c5223e 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryContinueInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryContinueInspection.java @@ -60,6 +60,7 @@ public class GroovyUnnecessaryContinueInspection extends BaseInspection { return true; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); @@ -67,7 +68,7 @@ public class GroovyUnnecessaryContinueInspection extends BaseInspection { @Override @Nullable - protected GroovyFix buildFix(PsiElement location) { + protected GroovyFix buildFix(@NotNull PsiElement location) { return new UnnecessaryContinueFix(); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryReturnInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryReturnInspection.java index 6b2bc77a1503..2f492048abfc 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryReturnInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryReturnInspection.java @@ -59,6 +59,7 @@ public class GroovyUnnecessaryReturnInspection extends BaseInspection { return true; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); @@ -66,7 +67,7 @@ public class GroovyUnnecessaryReturnInspection extends BaseInspection { @Override @Nullable - protected GroovyFix buildFix(PsiElement location) { + protected GroovyFix buildFix(@NotNull PsiElement location) { return new UnnecessaryReturnFix(); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyContinueOrBreakFromFinallyBlockInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyContinueOrBreakFromFinallyBlockInspection.java index 1064f818dfc2..e4b5d0aab68e 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyContinueOrBreakFromFinallyBlockInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyContinueOrBreakFromFinallyBlockInspection.java @@ -48,6 +48,7 @@ public class GroovyContinueOrBreakFromFinallyBlockInspection extends BaseInspect } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyFinallyBlockInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyFinallyBlockInspection.java index ad0d3e2dfa7a..b35d3ff87695 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyFinallyBlockInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyFinallyBlockInspection.java @@ -47,6 +47,7 @@ public class GroovyEmptyFinallyBlockInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyTryBlockInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyTryBlockInspection.java index e2a6baf3bf68..5fc9fc2515c1 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyTryBlockInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyTryBlockInspection.java @@ -47,6 +47,7 @@ public class GroovyEmptyTryBlockInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyReturnFromFinallyBlockInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyReturnFromFinallyBlockInspection.java index 93f70311452c..ae614fd8c508 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyReturnFromFinallyBlockInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyReturnFromFinallyBlockInspection.java @@ -46,6 +46,7 @@ public class GroovyReturnFromFinallyBlockInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyThrowFromFinallyBlockInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyThrowFromFinallyBlockInspection.java index 2d790cf9819f..8c1bcf810a56 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyThrowFromFinallyBlockInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyThrowFromFinallyBlockInspection.java @@ -45,6 +45,7 @@ public class GroovyThrowFromFinallyBlockInspection extends BaseInspection { return "'#ref' inside 'finally' block #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyUnusedCatchParameterInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyUnusedCatchParameterInspection.java index beb4b6d742a8..8fcfd554c4b2 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyUnusedCatchParameterInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyUnusedCatchParameterInspection.java @@ -47,6 +47,7 @@ public class GroovyUnusedCatchParameterInspection extends BaseInspection { return "Unused catch parameter"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListGetCanBeKeyedAccessInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListGetCanBeKeyedAccessInspection.java index 7da69f949c27..875799171d53 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListGetCanBeKeyedAccessInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListGetCanBeKeyedAccessInspection.java @@ -58,13 +58,14 @@ public class GroovyListGetCanBeKeyedAccessInspection extends BaseInspection { return "Call to '#ref' can be keyed access #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); } @Override - public GroovyFix buildFix(PsiElement location) { + public GroovyFix buildFix(@NotNull PsiElement location) { return new ReplaceWithPropertyAccessFix(); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListSetCanBeKeyedAccessInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListSetCanBeKeyedAccessInspection.java index 598212ec0b1d..71840254a02c 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListSetCanBeKeyedAccessInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListSetCanBeKeyedAccessInspection.java @@ -58,13 +58,14 @@ public class GroovyListSetCanBeKeyedAccessInspection extends BaseInspection { return "Call to '#ref' can be keyed access #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); } @Override - public GroovyFix buildFix(PsiElement location) { + public GroovyFix buildFix(@NotNull PsiElement location) { return new ReplaceWithPropertyAccessFix(); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapGetCanBeKeyedAccessInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapGetCanBeKeyedAccessInspection.java index 638d641af234..621dfe82693a 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapGetCanBeKeyedAccessInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapGetCanBeKeyedAccessInspection.java @@ -58,13 +58,14 @@ public class GroovyMapGetCanBeKeyedAccessInspection extends BaseInspection { return "Call to '#ref' can be keyed access #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); } @Override - public GroovyFix buildFix(PsiElement location) { + public GroovyFix buildFix(@NotNull PsiElement location) { return new ReplaceWithPropertyAccessFix(); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapPutCanBeKeyedAccessInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapPutCanBeKeyedAccessInspection.java index 851a7429088b..afaa3ff66548 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapPutCanBeKeyedAccessInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapPutCanBeKeyedAccessInspection.java @@ -59,13 +59,14 @@ public class GroovyMapPutCanBeKeyedAccessInspection extends BaseInspection { return "Call to '#ref' can be keyed access #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); } @Override - public GroovyFix buildFix(PsiElement location) { + public GroovyFix buildFix(@NotNull PsiElement location) { return fix; } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodParameterCountInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodParameterCountInspectionBase.java index 09fc336bb607..fbdedbb6660a 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodParameterCountInspectionBase.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodParameterCountInspectionBase.java @@ -49,6 +49,7 @@ public class GroovyMethodParameterCountInspectionBase extends GroovyMethodMetric return "Method '#ref' contains too many parameters (" + args[0] + '>' + args[1] + ')'; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodWithMoreThanThreeNegationsInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodWithMoreThanThreeNegationsInspection.java index d4c58fa2150a..5dede4ef0da3 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodWithMoreThanThreeNegationsInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodWithMoreThanThreeNegationsInspection.java @@ -40,6 +40,7 @@ public class GroovyMethodWithMoreThanThreeNegationsInspection extends BaseInspec return "Method '#ref' has too many negations (" + args[0] + " > 3)"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMultipleReturnPointsPerMethodInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMultipleReturnPointsPerMethodInspectionBase.java index 3291d2d4d25d..14dcdf0533f4 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMultipleReturnPointsPerMethodInspectionBase.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMultipleReturnPointsPerMethodInspectionBase.java @@ -56,6 +56,7 @@ public class GroovyMultipleReturnPointsPerMethodInspectionBase extends GroovyMet } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new MultipleReturnPointsVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyComplexMethodInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyComplexMethodInspectionBase.java index ffe5997675a1..f6b0f96f89f7 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyComplexMethodInspectionBase.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyComplexMethodInspectionBase.java @@ -48,6 +48,7 @@ public class GroovyOverlyComplexMethodInspectionBase extends GroovyMethodMetricI return "Method '#ref' is overly complex ( cyclomatic complexity =" + args[0] + '>' + args[1] + ')'; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyLongMethodInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyLongMethodInspectionBase.java index 7e04ae727bb6..a437483499ed 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyLongMethodInspectionBase.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyLongMethodInspectionBase.java @@ -48,6 +48,7 @@ public class GroovyOverlyLongMethodInspectionBase extends GroovyMethodMetricInsp return "Method '#ref' is too long ( statement count =" + args[0] + '>' + args[1] + ')'; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyNestedMethodInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyNestedMethodInspectionBase.java index 74aac333b984..7e11ca2d6ac1 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyNestedMethodInspectionBase.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyNestedMethodInspectionBase.java @@ -48,6 +48,7 @@ public class GroovyOverlyNestedMethodInspectionBase extends GroovyMethodMetricIn return "Method '#ref' is overly nested ( nesting depth =" + args[0] + '>' + args[1] + ')'; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyConstantNamingConventionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyConstantNamingConventionInspection.java index 108d7bfedf26..64e6d14d15a2 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyConstantNamingConventionInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyConstantNamingConventionInspection.java @@ -35,7 +35,7 @@ public class GroovyConstantNamingConventionInspection extends ConventionInspecti } @Override - protected GroovyFix buildFix(PsiElement location) { + protected GroovyFix buildFix(@NotNull PsiElement location) { return GroovyQuickFixFactory.getInstance().createRenameFix(); } @@ -71,6 +71,7 @@ public class GroovyConstantNamingConventionInspection extends ConventionInspecti return DEFAULT_MAX_LENGTH; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new NamingConventionsVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceMethodNamingConventionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceMethodNamingConventionInspection.java index c53e1c04eec2..c65afa809b03 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceMethodNamingConventionInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceMethodNamingConventionInspection.java @@ -36,7 +36,7 @@ public class GroovyInstanceMethodNamingConventionInspection extends ConventionIn } @Override - protected GroovyFix buildFix(PsiElement location) { + protected GroovyFix buildFix(@NotNull PsiElement location) { return GroovyQuickFixFactory.getInstance().createRenameFix(); } @@ -72,6 +72,7 @@ public class GroovyInstanceMethodNamingConventionInspection extends ConventionIn return DEFAULT_MAX_LENGTH; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new NamingConventionsVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceVariableNamingConventionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceVariableNamingConventionInspection.java index dc286dec8bc9..297d28129271 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceVariableNamingConventionInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceVariableNamingConventionInspection.java @@ -35,7 +35,7 @@ public class GroovyInstanceVariableNamingConventionInspection extends Convention } @Override - protected GroovyFix buildFix(PsiElement location) { + protected GroovyFix buildFix(@NotNull PsiElement location) { return GroovyQuickFixFactory.getInstance().createRenameFix(); } @@ -71,6 +71,7 @@ public class GroovyInstanceVariableNamingConventionInspection extends Convention return DEFAULT_MAX_LENGTH; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new NamingConventionsVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyLocalVariableNamingConventionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyLocalVariableNamingConventionInspection.java index 6a623d82476c..48dad65f51c4 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyLocalVariableNamingConventionInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyLocalVariableNamingConventionInspection.java @@ -38,7 +38,7 @@ public class GroovyLocalVariableNamingConventionInspection extends ConventionIns } @Override - protected GroovyFix buildFix(PsiElement location) { + protected GroovyFix buildFix(@NotNull PsiElement location) { return GroovyQuickFixFactory.getInstance().createRenameFix(); } @@ -74,6 +74,7 @@ public class GroovyLocalVariableNamingConventionInspection extends ConventionIns return DEFAULT_MAX_LENGTH; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new NamingConventionsVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyParameterNamingConventionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyParameterNamingConventionInspection.java index 5d56f06b3f78..a3e319e2c950 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyParameterNamingConventionInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyParameterNamingConventionInspection.java @@ -36,7 +36,7 @@ public class GroovyParameterNamingConventionInspection extends ConventionInspect } @Override - protected GroovyFix buildFix(PsiElement location) { + protected GroovyFix buildFix(@NotNull PsiElement location) { return GroovyQuickFixFactory.getInstance().createRenameFix(); } @@ -72,6 +72,7 @@ public class GroovyParameterNamingConventionInspection extends ConventionInspect return DEFAULT_MAX_LENGTH; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new NamingConventionsVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticMethodNamingConventionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticMethodNamingConventionInspection.java index 63446a369064..db69c140ba4f 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticMethodNamingConventionInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticMethodNamingConventionInspection.java @@ -35,7 +35,7 @@ public class GroovyStaticMethodNamingConventionInspection extends ConventionInsp } @Override - protected GroovyFix buildFix(PsiElement location) { + protected GroovyFix buildFix(@NotNull PsiElement location) { return GroovyQuickFixFactory.getInstance().createRenameFix(); } @@ -71,6 +71,7 @@ public class GroovyStaticMethodNamingConventionInspection extends ConventionInsp return DEFAULT_MAX_LENGTH; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new NamingConventionsVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticVariableNamingConventionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticVariableNamingConventionInspection.java index 68014a67e61a..4718df33a1fa 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticVariableNamingConventionInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticVariableNamingConventionInspection.java @@ -35,7 +35,7 @@ public class GroovyStaticVariableNamingConventionInspection extends ConventionIn } @Override - protected GroovyFix buildFix(PsiElement location) { + protected GroovyFix buildFix(@NotNull PsiElement location) { return GroovyQuickFixFactory.getInstance().createRenameFix(); } @@ -71,6 +71,7 @@ public class GroovyStaticVariableNamingConventionInspection extends ConventionIn return DEFAULT_MAX_LENGTH; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new NamingConventionsVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyAccessToStaticFieldLockedOnInstanceInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyAccessToStaticFieldLockedOnInstanceInspection.java index f059080470e6..293091e536f8 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyAccessToStaticFieldLockedOnInstanceInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyAccessToStaticFieldLockedOnInstanceInspection.java @@ -56,6 +56,7 @@ public class GroovyAccessToStaticFieldLockedOnInstanceInspection return "Access to static field <code>#ref</code> locked on instance data #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyBusyWaitInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyBusyWaitInspection.java index 890e539350ff..36203c188a76 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyBusyWaitInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyBusyWaitInspection.java @@ -47,6 +47,7 @@ public class GroovyBusyWaitInspection extends BaseInspection { return "Call to <code>Thread.#ref()</code> in a loop, probably busy-waiting #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new BusyWaitVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyDoubleCheckedLockingInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyDoubleCheckedLockingInspection.java index 4721f40c0734..c1b829ecc21d 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyDoubleCheckedLockingInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyDoubleCheckedLockingInspection.java @@ -71,6 +71,7 @@ public class GroovyDoubleCheckedLockingInspection extends BaseInspection { ); } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new DoubleCheckedLockingVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyEmptySyncBlockInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyEmptySyncBlockInspection.java index 121f867b7e37..db421ff40a50 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyEmptySyncBlockInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyEmptySyncBlockInspection.java @@ -47,6 +47,7 @@ public class GroovyEmptySyncBlockInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNestedSynchronizedStatementInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNestedSynchronizedStatementInspection.java index 53080fdb8e4d..646ca65b3998 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNestedSynchronizedStatementInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNestedSynchronizedStatementInspection.java @@ -50,6 +50,7 @@ public class GroovyNestedSynchronizedStatementInspection extends BaseInspection } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNotifyWhileNotSynchronizedInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNotifyWhileNotSynchronizedInspection.java index adb8d6563f57..0589b659c426 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNotifyWhileNotSynchronizedInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNotifyWhileNotSynchronizedInspection.java @@ -55,6 +55,7 @@ public class GroovyNotifyWhileNotSynchronizedInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyPublicFieldAccessedInSynchronizedContextInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyPublicFieldAccessedInSynchronizedContextInspection.java index c46b33ac4a58..ccf799ddd86d 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyPublicFieldAccessedInSynchronizedContextInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyPublicFieldAccessedInSynchronizedContextInspection.java @@ -47,6 +47,7 @@ public class GroovyPublicFieldAccessedInSynchronizedContextInspection return "Non-private field <code>#ref</code> accessed in synchronized context #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new PublicFieldAccessedInSynchronizedContextVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnNonFinalFieldInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnNonFinalFieldInspection.java index f5b9b1f047d6..bacafcdb799d 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnNonFinalFieldInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnNonFinalFieldInspection.java @@ -55,6 +55,7 @@ public class GroovySynchronizationOnNonFinalFieldInspection extends BaseInspecti } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnThisInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnThisInspection.java index ab8dd421098e..e343fa62397d 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnThisInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnThisInspection.java @@ -48,6 +48,7 @@ public class GroovySynchronizationOnThisInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnVariableInitializedWithLiteralInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnVariableInitializedWithLiteralInspection.java index 34b239e4faaa..6464e6654780 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnVariableInitializedWithLiteralInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnVariableInitializedWithLiteralInspection.java @@ -54,6 +54,7 @@ public class GroovySynchronizationOnVariableInitializedWithLiteralInspection ext } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizedMethodInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizedMethodInspection.java index 75767a0fea6b..b8b3e34b1d7c 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizedMethodInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizedMethodInspection.java @@ -46,6 +46,7 @@ public class GroovySynchronizedMethodInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySystemRunFinalizersOnExitInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySystemRunFinalizersOnExitInspection.java index 8acd2d3585b1..8629e23787d9 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySystemRunFinalizersOnExitInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySystemRunFinalizersOnExitInspection.java @@ -48,6 +48,7 @@ public class GroovySystemRunFinalizersOnExitInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyThreadStopSuspendResumeInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyThreadStopSuspendResumeInspection.java index e65e23b1f709..072fb29fbec5 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyThreadStopSuspendResumeInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyThreadStopSuspendResumeInspection.java @@ -60,6 +60,7 @@ public class GroovyThreadStopSuspendResumeInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnconditionalWaitInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnconditionalWaitInspection.java index 445e34da38c4..2e24f21654d2 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnconditionalWaitInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnconditionalWaitInspection.java @@ -53,6 +53,7 @@ public class GroovyUnconditionalWaitInspection extends BaseInspection { return "Unconditional call to <code>#ref()</code> #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new UnconditionalWaitVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnsynchronizedMethodOverridesSynchronizedMethodInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnsynchronizedMethodOverridesSynchronizedMethodInspection.java index 83e822ce663d..9b539bd8185d 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnsynchronizedMethodOverridesSynchronizedMethodInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnsynchronizedMethodOverridesSynchronizedMethodInspection.java @@ -52,6 +52,7 @@ public class GroovyUnsynchronizedMethodOverridesSynchronizedMethodInspection ext } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitCallNotInLoopInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitCallNotInLoopInspection.java index e86a1028e92e..7e0a0080ac68 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitCallNotInLoopInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitCallNotInLoopInspection.java @@ -51,6 +51,7 @@ public class GroovyWaitCallNotInLoopInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitWhileNotSynchronizedInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitWhileNotSynchronizedInspection.java index acacf2954e0a..41c25bc8b51b 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitWhileNotSynchronizedInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitWhileNotSynchronizedInspection.java @@ -56,6 +56,7 @@ public class GroovyWaitWhileNotSynchronizedInspection extends BaseInspection { } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWhileLoopSpinsOnFieldInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWhileLoopSpinsOnFieldInspection.java index 0949348a92da..6ce007026ea0 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWhileLoopSpinsOnFieldInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWhileLoopSpinsOnFieldInspection.java @@ -69,6 +69,7 @@ public class GroovyWhileLoopSpinsOnFieldInspection extends BaseInspection { this, "ignoreNonEmtpyLoops"); } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new WhileLoopSpinsOnFieldVisitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessChecker.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessChecker.java index 2978b652f544..ef9dafc585a5 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessChecker.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessChecker.java @@ -435,10 +435,11 @@ public class GrUnresolvedAccessChecker { PsiClass targetClass = QuickfixUtil.findTargetClass(refExpr, compileStatic); if (targetClass == null) return; + if (!compileStatic) { + addDynamicAnnotation(info, refExpr, key); + } + if (!(targetClass instanceof SyntheticElement) || (targetClass instanceof GroovyScriptClass)) { - if (!compileStatic) { - addDynamicAnnotation(info, refExpr, key); - } QuickFixAction.registerQuickFixAction(info, GroovyQuickFixFactory.getInstance().createCreateFieldFromUsageFix(refExpr), key); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyDuplicateSwitchBranchInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyDuplicateSwitchBranchInspection.java index 7a064ffa8030..bead894b4201 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyDuplicateSwitchBranchInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyDuplicateSwitchBranchInspection.java @@ -56,6 +56,7 @@ public class GroovyDuplicateSwitchBranchInspection extends BaseInspection { return "Duplicate switch case '#ref' #loc"; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyUnreachableStatementInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyUnreachableStatementInspection.java index 83c75cd9f4c8..0c64951c26f4 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyUnreachableStatementInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyUnreachableStatementInspection.java @@ -53,6 +53,7 @@ public class GroovyUnreachableStatementInspection extends BaseInspection { return true; } + @NotNull @Override public BaseInspectionVisitor buildVisitor() { return new Visitor(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java index ae0b7566fe34..cbc6fa29d853 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java @@ -467,7 +467,7 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> { } @Override - public boolean acceptInput(final VirtualFile file) { + public boolean acceptInput(@NotNull final VirtualFile file) { return StringUtil.endsWith(file.getNameSequence(), ".gdsl"); } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrDelegatesToUtil.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrDelegatesToUtil.java index 313065afc5d7..f60256de8397 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrDelegatesToUtil.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrDelegatesToUtil.java @@ -16,6 +16,7 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks; import com.intellij.psi.*; +import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.ArrayUtil; @@ -168,7 +169,7 @@ public class GrDelegatesToUtil { final PsiType baseType = signature.getParameters()[param].getType(); final PsiClass baseClass = PsiUtil.resolveClassInClassTypeOnly(baseType); - if (baseClass != null && psiClass.isInheritor(baseClass, true)) { + if (baseClass != null && InheritanceUtil.isInheritorOrSelf(psiClass, baseClass, true)) { final PsiTypeParameter[] typeParameters = baseClass.getTypeParameters(); if (genericIndex < typeParameters.length) { final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, psiClass, substitutor); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyMarkerTypes.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyMarkerTypes.java index 3dc41bf408f5..38fac33ae3a3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyMarkerTypes.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyMarkerTypes.java @@ -23,6 +23,7 @@ import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator; import com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask; import com.intellij.ide.util.MethodCellRenderer; import com.intellij.ide.util.PsiElementListCellRenderer; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadActionProcessor; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; @@ -159,9 +160,14 @@ public class GroovyMarkerTypes { if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override public void run() { - for (GrAccessorMethod method : GroovyPropertyUtils.getFieldAccessors(field)) { - OverridingMethodsSearch.search(method, true).forEach(collectProcessor); - } + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + for (GrAccessorMethod method : GroovyPropertyUtils.getFieldAccessors(field)) { + OverridingMethodsSearch.search(method, true).forEach(collectProcessor); + } + } + }); } }, "Searching for overriding methods", true, field.getProject(), (JComponent)e.getComponent())) { return; @@ -272,17 +278,22 @@ public class GroovyMarkerTypes { if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override public void run() { - for (GrMethod m : PsiImplUtil.getMethodOrReflectedMethods(method)) { - OverridingMethodsSearch.search(m, true).forEach(new ReadActionProcessor<PsiMethod>() { - @Override - public boolean processInReadAction(PsiMethod psiMethod) { - if (psiMethod instanceof GrReflectedMethod) { - psiMethod = ((GrReflectedMethod)psiMethod).getBaseMethod(); - } - return collectProcessor.execute(psiMethod); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + for (GrMethod m : PsiImplUtil.getMethodOrReflectedMethods(method)) { + OverridingMethodsSearch.search(m, true).forEach(new ReadActionProcessor<PsiMethod>() { + @Override + public boolean processInReadAction(PsiMethod psiMethod) { + if (psiMethod instanceof GrReflectedMethod) { + psiMethod = ((GrReflectedMethod)psiMethod).getBaseMethod(); + } + return collectProcessor.execute(psiMethod); + } + }); } - }); - } + } + }); } }, MarkerType.SEARCHING_FOR_OVERRIDING_METHODS, true, method.getProject(), (JComponent)e.getComponent())) { return; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyQuickFixFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyQuickFixFactoryImpl.java index 1be4df43ba72..8bb41490a3b4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyQuickFixFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyQuickFixFactoryImpl.java @@ -26,6 +26,7 @@ import org.jetbrains.plugins.groovy.codeInspection.bugs.AddClassToExtendsFix; import org.jetbrains.plugins.groovy.codeInspection.bugs.AddMethodFix; import org.jetbrains.plugins.groovy.codeInspection.confusing.ReplaceWithImportFix; import org.jetbrains.plugins.groovy.codeInspection.local.RemoveUnusedGrParameterFix; +import org.jetbrains.plugins.groovy.codeInspection.naming.RenameFix; import org.jetbrains.plugins.groovy.dsl.InvestigateFix; import org.jetbrains.plugins.groovy.lang.GrCreateClassKind; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; @@ -101,7 +102,7 @@ public class GroovyQuickFixFactoryImpl extends GroovyQuickFixFactory { @Override public GroovyFix createRenameFix() { - return GroovyQuickFixFactory.getInstance().createRenameFix(); + return new RenameFix(); } @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspection.java index b5579e186613..60be41f0309b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspection.java @@ -1,168 +1,47 @@ +/* + * 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 org.jetbrains.plugins.groovy.codeInspection.confusing; import com.intellij.codeInsight.generation.OverrideImplementUtil; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.*; -import com.intellij.psi.util.PsiFormatUtil; -import com.intellij.psi.util.PsiFormatUtilBase; -import com.intellij.util.Function; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.codeInspection.BaseInspection; -import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor; import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrTraitMethod; -import org.jetbrains.plugins.groovy.lang.psi.util.GrTraitUtil; -import java.util.Collection; import java.util.List; /** * Created by Max Medvedev on 03/06/14 */ -public class ClashingTraitMethodsInspection extends BaseInspection { - private static final Logger LOG = Logger.getInstance(ClashingTraitMethodsInspection.class); +public class ClashingTraitMethodsInspection extends ClashingTraitMethodsInspectionBase { @NotNull @Override - protected BaseInspectionVisitor buildVisitor() { - return new BaseInspectionVisitor() { - @Override - public void visitTypeDefinition(GrTypeDefinition typeDefinition) { - super.visitTypeDefinition(typeDefinition); - - List<PsiClass> superTraits = collectImplementedTraits(typeDefinition); - - if (superTraits.size() < 2) return; - - List<ClashingMethod> clashingMethods = collectClassingMethods(typeDefinition); - - for (ClashingMethod clashing : clashingMethods) { - registerError(typeDefinition.getNameIdentifierGroovy(), buildWarning(clashing), new LocalQuickFix[]{new MyQuickFix()}, ProblemHighlightType.GENERIC_ERROR_OR_WARNING); - } - } - - @NotNull - private String buildWarning(@NotNull ClashingMethod entry) { - return "Traits " + buildTraitString(entry) + " contain clashing methods with signature " + buildSignatureString(entry); - } - - @NotNull - private String buildSignatureString(@NotNull ClashingMethod entry) { - HierarchicalMethodSignature signature = entry.getSignature(); - return PsiFormatUtil.formatMethod(signature.getMethod(), signature.getSubstitutor(), - PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS, - PsiFormatUtilBase.SHOW_TYPE); - } - - @NotNull - private String buildTraitString(@NotNull ClashingMethod entry) { - return StringUtil.join(entry.getSuperTraits(), new Function<GrTypeDefinition, String>() { - public String fun(GrTypeDefinition tr) { - return tr.getName(); - } - }, ", "); - } - }; - } - - @NotNull - private static List<ClashingMethod> collectClassingMethods(@NotNull GrTypeDefinition typeDefinition) { - Collection<HierarchicalMethodSignature> visibleSignatures = typeDefinition.getVisibleSignatures(); - - List<ClashingMethod> clashingMethods = ContainerUtil.newArrayList(); - for (HierarchicalMethodSignature signature : visibleSignatures) { - PsiMethod method = signature.getMethod(); - if (method instanceof GrTraitMethod && method.getContainingClass() == typeDefinition) { - List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures(); - if (superSignatures.size() > 1) { - List<GrTypeDefinition> traits = ContainerUtil.newArrayList(); - for (HierarchicalMethodSignature superSignature : superSignatures) { - PsiMethod superMethod = superSignature.getMethod(); - PsiClass superClass = superMethod.getContainingClass(); - if (GrTraitUtil.isTrait(superClass) && - !superMethod.getModifierList().hasExplicitModifier(PsiModifier.ABSTRACT)) { - traits.add((GrTypeDefinition)superClass); - } - } - - if (traits.size() > 1) { - clashingMethods.add(new ClashingMethod(signature, traits)); - } - } - } - } - - return clashingMethods; - } - - @NotNull - private static List<PsiClass> collectImplementedTraits(@NotNull GrTypeDefinition typeDefinition) { - return ContainerUtil.findAll(typeDefinition.getSupers(), new Condition<PsiClass>() { - @Override - public boolean value(PsiClass aClass) { - return GrTraitUtil.isTrait(aClass); - } - }); - } - - private static class ClashingMethod { - private final HierarchicalMethodSignature mySignature; - private final List<GrTypeDefinition> mySuperTraits; - - public ClashingMethod(@NotNull HierarchicalMethodSignature signature, @NotNull List<GrTypeDefinition> superTraits) { - mySignature = signature; - mySuperTraits = superTraits; - } - - @NotNull - public HierarchicalMethodSignature getSignature() { - return mySignature; - } - - @NotNull - public List<GrTypeDefinition> getSuperTraits() { - return mySuperTraits; - } + protected LocalQuickFix getFix(){ + return new MyQuickFix(); } private static class MyQuickFix implements LocalQuickFix { - private static final int MAX_SIGNATURE_LENGTH = 50; - - private static String buildSignature(HierarchicalMethodSignature signature, int maxLength) { - StringBuilder result = new StringBuilder(); - result.append(signature.getName()); - - PsiType[] params = signature.getParameterTypes(); - - if (params.length == 0) { - result.append("()"); - return result.toString(); - } - - result.append("("); - - for (PsiType param : params) { - if (result.length() >= maxLength - "...)".length()) { - result.append("...)"); - return result.toString(); - } - result.append(param.getPresentableText()); - result.append(", "); - } - result.replace(result.length() - ", ".length(), result.length(), ")"); - return result.toString(); - } - @NotNull @Override public String getName() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyLanguageCodeStyleSettingsProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyLanguageCodeStyleSettingsProvider.java index 1e28d0c8935e..4ce07a3d3fff 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyLanguageCodeStyleSettingsProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyLanguageCodeStyleSettingsProvider.java @@ -49,6 +49,7 @@ public class GroovyLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSe @NotNull SettingsType settingsType) { if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) { consumer.showStandardOptions( + "RIGHT_MARGIN", "KEEP_LINE_BREAKS", "KEEP_FIRST_COLUMN_COMMENT", "KEEP_CONTROL_STATEMENT_IN_ONE_LINE", diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonDebuggerRunner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonDebuggerRunner.java index 898f429659f3..2d424b2f58d9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonDebuggerRunner.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonDebuggerRunner.java @@ -22,7 +22,6 @@ import com.intellij.execution.configurations.*; import com.intellij.execution.executors.DefaultDebugExecutor; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.ui.RunContentDescriptor; -import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; /** @@ -42,10 +41,7 @@ public class GriffonDebuggerRunner extends GenericDebuggerRunner { @Override - protected RunContentDescriptor createContentDescriptor(Project project, - RunProfileState state, - RunContentDescriptor contentToReuse, - ExecutionEnvironment env) throws ExecutionException { + protected RunContentDescriptor createContentDescriptor(@NotNull RunProfileState state, @NotNull ExecutionEnvironment environment) throws ExecutionException { final JavaCommandLine javaCommandLine = (JavaCommandLine)state; final JavaParameters params = javaCommandLine.getJavaParameters(); @@ -68,11 +64,8 @@ public class GriffonDebuggerRunner extends GenericDebuggerRunner { } if (address == null) { - return super.createContentDescriptor(project, state, contentToReuse, env); + return super.createContentDescriptor(state, environment); } - - RemoteConnection connection = new RemoteConnection(true, "127.0.0.1", address, false); - return attachVirtualMachine(project, state, contentToReuse, env, connection, true); + return attachVirtualMachine(state, environment, new RemoteConnection(true, "127.0.0.1", address, false), true); } - -} +}
\ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java index 4b5459ff432e..55ab68f7f822 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java @@ -415,9 +415,13 @@ public class GroovySmartCompletionContributor extends CompletionContributor { } } - final LookupItem item = PsiTypeLookupItem.createLookupItem(GenericsUtil.eliminateWildcards(type), place, isDiamond, ChooseTypeExpression.IMPORT_FIXER); - if (item.getObject() instanceof PsiClass) { + final PsiTypeLookupItem item = PsiTypeLookupItem.createLookupItem(GenericsUtil.eliminateWildcards(type), place, isDiamond, ChooseTypeExpression.IMPORT_FIXER); + Object object = item.getObject(); + if (object instanceof PsiClass) { JavaCompletionUtil.setShowFQN(item); + if (((PsiClass)object).hasModifierProperty(PsiModifier.ABSTRACT)) { + item.setIndicateAnonymous(true); + } } item.setInsertHandler(new AfterNewClassInsertHandler((PsiClassType)type, true)); return item; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcProjectViewPane.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcProjectViewPane.java index 32db531b212e..f32d77131d82 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcProjectViewPane.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcProjectViewPane.java @@ -352,6 +352,7 @@ public class MvcProjectViewPane extends AbstractProjectViewPSIPane implements Id } } + @NotNull @Override public PsiDirectory[] getDirectories() { return getSelectedDirectories(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcToolWindowDescriptor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcToolWindowDescriptor.java index 945bb9c8f24b..35171ccda212 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcToolWindowDescriptor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcToolWindowDescriptor.java @@ -51,7 +51,7 @@ public abstract class MvcToolWindowDescriptor implements ToolWindowFactory, Cond } @Override - public void createToolWindowContent(Project project, ToolWindow toolWindow) { + public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) { toolWindow.setAvailable(true, null); toolWindow.setToHideOnEmptyContent(true); toolWindow.setTitle(myFramework.getDisplayName()); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/memberPullUp/GrPullUpHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/memberPullUp/GrPullUpHandler.java index 83d2a4088645..19480e0d80e8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/memberPullUp/GrPullUpHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/memberPullUp/GrPullUpHandler.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.refactoring.memberPullUp; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; @@ -170,9 +171,16 @@ public class GrPullUpHandler implements RefactoringActionHandler, GrPullUpDialog if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override public void run() { - final PsiDirectory targetDirectory = superClass.getContainingFile().getContainingDirectory(); - final PsiPackage targetPackage = targetDirectory != null ? JavaDirectoryService.getInstance().getPackage(targetDirectory) : null; - conflicts.putAllValues(GrPullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, targetPackage, targetDirectory, dialog.getContainmentVerifier())); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + final PsiDirectory targetDirectory = superClass.getContainingFile().getContainingDirectory(); + final PsiPackage targetPackage = + targetDirectory != null ? JavaDirectoryService.getInstance().getPackage(targetDirectory) : null; + conflicts.putAllValues(GrPullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, targetPackage, targetDirectory, + dialog.getContainmentVerifier())); + } + }); } }, RefactoringBundle.message("detecting.possible.conflicts"), true, myProject)) { return false; diff --git a/plugins/groovy/structuralsearch-groovy/testSrc/com/intellij/structuralsearch/GroovyStructuralSearchTest.java b/plugins/groovy/structuralsearch-groovy/testSrc/com/intellij/structuralsearch/GroovyStructuralSearchTest.java index 8990fba2716e..18505d018747 100644 --- a/plugins/groovy/structuralsearch-groovy/testSrc/com/intellij/structuralsearch/GroovyStructuralSearchTest.java +++ b/plugins/groovy/structuralsearch-groovy/testSrc/com/intellij/structuralsearch/GroovyStructuralSearchTest.java @@ -25,7 +25,6 @@ import java.util.List; /** * @author Eugene.Kudelevsky */ -@Bombed(day = 14, month = Calendar.JULY) public class GroovyStructuralSearchTest extends StructuralSearchTestCase { public void test1() throws Exception { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java index 28b2e26949ad..e227a1b34663 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java @@ -25,6 +25,7 @@ import com.intellij.execution.executors.DefaultRunExecutor; import com.intellij.execution.impl.DefaultJavaProgramRunner; import com.intellij.execution.process.*; import com.intellij.execution.runners.ExecutionEnvironment; +import com.intellij.execution.runners.ExecutionEnvironmentBuilder; import com.intellij.execution.runners.ProgramRunner; import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.openapi.Disposable; @@ -234,7 +235,7 @@ public abstract class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestC ProgramRunner runner, RunProfile configuration) throws ExecutionException { final Executor executor = Executor.EXECUTOR_EXTENSION_NAME.findExtension(executorClass); - final ExecutionEnvironment environment = new ExecutionEnvironment(configuration, executor, getProject(), null); + final ExecutionEnvironment environment = new ExecutionEnvironmentBuilder(getProject(), executor).runProfile(configuration).build(); final Semaphore semaphore = new Semaphore(); semaphore.down(); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/WrappingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/WrappingTest.groovy index 79d79edc42de..4d585dbf7f6f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/WrappingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/WrappingTest.groovy @@ -16,6 +16,7 @@ package org.jetbrains.plugins.groovy.lang.formatter import com.intellij.psi.codeStyle.CommonCodeStyleSettings +import org.jetbrains.plugins.groovy.GroovyLanguage /** * @author Max Medvedev @@ -24,7 +25,7 @@ class WrappingTest extends GroovyFormatterTestCase { @Override protected void setUp() throws Exception { super.setUp() - myTempSettings.RIGHT_MARGIN = 10 + myTempSettings.setRightMargin(GroovyLanguage.INSTANCE, 10); } void testWrapChainedMethodCalls() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy index 9762f6772016..96be1fe5be02 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy @@ -681,6 +681,24 @@ def staticOnWrapper() { ''', 'List') } + void testClassTest() { + assertScript(''' +class DelegatesToTest { + void create(@DelegatesTo.Target Class type, @DelegatesTo(genericTypeIndex = 0, strategy = Closure.OWNER_FIRST) Closure closure) {} + + + void doit() { + create(Person) { + a<caret>ge = 30 // IDEA 12.1.6 can resolve this property, 13.1.3 can't + } + } +} + +class Person { + int age +} +''', 'Person') + } void assertScript(String text, String resolvedClass) { myFixture.configureByText('_a.groovy', text) diff --git a/plugins/hg4idea/hg4idea.iml b/plugins/hg4idea/hg4idea.iml index 7f5074895e4f..93b5a5109bde 100644 --- a/plugins/hg4idea/hg4idea.iml +++ b/plugins/hg4idea/hg4idea.iml @@ -16,9 +16,10 @@ <orderEntry type="module" module-name="vcs-impl" /> <orderEntry type="module" module-name="platform-impl" /> <orderEntry type="library" name="Guava" level="project" /> - <orderEntry type="module" module-name="dvcs" /> + <orderEntry type="module" module-name="dvcs-impl" /> <orderEntry type="module" module-name="vcs-log-api" /> <orderEntry type="module" module-name="vcs-log-impl" /> + <orderEntry type="module" module-name="dvcs-api" /> </component> </module> diff --git a/plugins/hg4idea/src/META-INF/plugin.xml b/plugins/hg4idea/src/META-INF/plugin.xml index 9ccc175803f5..26b69326a703 100644 --- a/plugins/hg4idea/src/META-INF/plugin.xml +++ b/plugins/hg4idea/src/META-INF/plugin.xml @@ -21,6 +21,7 @@ <vcs name="hg4idea" vcsClass="org.zmlx.hg4idea.HgVcs" displayName="Mercurial" administrativeAreaName=".hg"/> <checkoutProvider implementation="org.zmlx.hg4idea.provider.HgCheckoutProvider"/> <vcsRootChecker implementation="org.zmlx.hg4idea.roots.HgRootChecker"/> + <pushSupport implementation="org.zmlx.hg4idea.push.HgPushSupport"/> <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/> <vcsPopupProvider implementation="org.zmlx.hg4idea.provider.HgQuickListProvider"/> <logProvider implementation="org.zmlx.hg4idea.log.HgLogProvider"/> diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java index d38bc7bfc6a7..d6282ebe8786 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java @@ -29,7 +29,9 @@ import org.zmlx.hg4idea.util.HgUtil; import javax.swing.*; import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; abstract class HgAbstractGlobalAction extends AnAction { @@ -48,12 +50,17 @@ abstract class HgAbstractGlobalAction extends AnAction { if (project == null) { return; } - VirtualFile file = event.getData(CommonDataKeys.VIRTUAL_FILE); - HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(project); - HgRepository repo = file != null ? repositoryManager.getRepositoryForFile(file): HgUtil.getCurrentRepository(project); + VirtualFile[] files = event.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY); + final HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(project); List<HgRepository> repositories = repositoryManager.getRepositories(); if (!repositories.isEmpty()) { - execute(project, repositories, repo); + List<HgRepository> selectedRepositories = (files == null || files.length == 0) + ? + Collections.singletonList(HgUtil.getCurrentRepository(project)) + : HgActionUtil.collectRepositoriesFromFiles(repositoryManager, + Arrays.asList(files)); + + execute(project, repositories, selectedRepositories); } } @@ -66,7 +73,7 @@ abstract class HgAbstractGlobalAction extends AnAction { protected abstract void execute(@NotNull Project project, @NotNull Collection<HgRepository> repositories, - @Nullable HgRepository selectedRepo); + @NotNull List<HgRepository> selectedRepositories); public static void handleException(@Nullable Project project, @NotNull Exception e) { handleException(project, "Error", e); @@ -102,16 +109,4 @@ abstract class HgAbstractGlobalAction extends AnAction { return true; } - @Nullable - public static HgRepository getSelectedRepositoryFromEvent(AnActionEvent e) { - final DataContext dataContext = e.getDataContext(); - final Project project = CommonDataKeys.PROJECT.getData(dataContext); - if (project == null) { - return null; - } - VirtualFile file = e.getData(CommonDataKeys.VIRTUAL_FILE); - HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(project); - return file != null ? repositoryManager.getRepositoryForFile(file) : HgUtil.getCurrentRepository(project); - } - } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalSingleRepoAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalSingleRepoAction.java new file mode 100644 index 000000000000..bfb2d7715e68 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalSingleRepoAction.java @@ -0,0 +1,47 @@ +/* + * 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 org.zmlx.hg4idea.action; + +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.repo.HgRepository; + +import javax.swing.*; +import java.util.Collection; +import java.util.List; + +public abstract class HgAbstractGlobalSingleRepoAction extends HgAbstractGlobalAction { + + public HgAbstractGlobalSingleRepoAction(Icon icon) { + super(icon); + } + + public HgAbstractGlobalSingleRepoAction() { + super(); + } + + @Override + protected void execute(@NotNull Project project, + @NotNull Collection<HgRepository> repositories, + @NotNull List<HgRepository> selectedRepositories) { + execute(project, repositories, selectedRepositories.isEmpty() ? null : selectedRepositories.get(0)); + } + + protected abstract void execute(@NotNull Project project, + @NotNull Collection<HgRepository> repositories, + @Nullable HgRepository selectedRepo); +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgActionUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgActionUtil.java new file mode 100644 index 000000000000..6abebd587787 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgActionUtil.java @@ -0,0 +1,58 @@ +/* + * 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 org.zmlx.hg4idea.action; + +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import com.sun.istack.internal.NotNull; +import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.repo.HgRepositoryManager; +import org.zmlx.hg4idea.util.HgUtil; + +import java.util.Collection; +import java.util.List; + +public class HgActionUtil { + + @NotNull + public static List<HgRepository> collectRepositoriesFromFiles(@NotNull final HgRepositoryManager repositoryManager, + @NotNull Collection<VirtualFile> files) { + return ContainerUtil.mapNotNull(files, new Function<VirtualFile, HgRepository>() { + @Override + public HgRepository fun(VirtualFile file) { + return repositoryManager.getRepositoryForFile(file); + } + }); + } + + @Nullable + public static HgRepository getSelectedRepositoryFromEvent(AnActionEvent e) { + final DataContext dataContext = e.getDataContext(); + final Project project = CommonDataKeys.PROJECT.getData(dataContext); + if (project == null) { + return null; + } + VirtualFile file = e.getData(CommonDataKeys.VIRTUAL_FILE); + HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(project); + return file != null ? repositoryManager.getRepositoryForFile(file) : HgUtil.getCurrentRepository(project); + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java index b8a10ed92116..d799cde1705c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java @@ -22,7 +22,7 @@ import org.zmlx.hg4idea.repo.HgRepository; import java.util.Collection; -public class HgBranchesAction extends HgAbstractGlobalAction { +public class HgBranchesAction extends HgAbstractGlobalSingleRepoAction { @Override protected void execute(@NotNull Project project, @NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java index 5c97e3ca9f39..c8734e8109f4 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java @@ -25,7 +25,7 @@ import org.zmlx.hg4idea.util.HgErrorUtil; import java.util.Collection; -public class HgCreateTagAction extends HgAbstractGlobalAction { +public class HgCreateTagAction extends HgAbstractGlobalSingleRepoAction { public void execute(@NotNull final Project project, @NotNull Collection<HgRepository> repositories, diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java index 1743e7e5b56e..45ff24e382ce 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java @@ -33,7 +33,7 @@ import org.zmlx.hg4idea.ui.HgMergeDialog; import java.util.Collection; -public class HgMerge extends HgAbstractGlobalAction { +public class HgMerge extends HgAbstractGlobalSingleRepoAction { @Override public void execute(@NotNull final Project project, diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgProcessRebaseAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgProcessRebaseAction.java index 342369f0a9bb..84e9d5b1beaf 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgProcessRebaseAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgProcessRebaseAction.java @@ -18,10 +18,10 @@ package org.zmlx.hg4idea.action; import com.intellij.openapi.actionSystem.AnActionEvent; import org.zmlx.hg4idea.repo.HgRepository; -public abstract class HgProcessRebaseAction extends HgAbstractGlobalAction { +public abstract class HgProcessRebaseAction extends HgAbstractGlobalSingleRepoAction { protected static boolean isRebasing(AnActionEvent e) { - HgRepository repository = HgAbstractGlobalAction.getSelectedRepositoryFromEvent(e); + HgRepository repository = HgActionUtil.getSelectedRepositoryFromEvent(e); return repository != null && repository.getState() == HgRepository.State.REBASING; } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java index d5a934e1d86d..74beff13eb81 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java @@ -24,7 +24,7 @@ import org.zmlx.hg4idea.ui.HgPullDialog; import java.util.Collection; -public class HgPullAction extends HgAbstractGlobalAction { +public class HgPullAction extends HgAbstractGlobalSingleRepoAction { public HgPullAction() { super(AllIcons.Actions.CheckOut); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java index 1b5704f1d0f4..232b2ef7fa73 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java @@ -12,14 +12,14 @@ // limitations under the License. package org.zmlx.hg4idea.action; +import com.intellij.dvcs.push.ui.VcsPushDialog; import com.intellij.icons.AllIcons; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.zmlx.hg4idea.HgPusher; import org.zmlx.hg4idea.repo.HgRepository; import java.util.Collection; +import java.util.List; public class HgPushAction extends HgAbstractGlobalAction { public HgPushAction() { @@ -29,7 +29,7 @@ public class HgPushAction extends HgAbstractGlobalAction { @Override public void execute(@NotNull final Project project, @NotNull Collection<HgRepository> repositories, - @Nullable final HgRepository selectedRepo) { - new HgPusher(project).showDialogAndPush(repositories, selectedRepo); + @NotNull final List<HgRepository> selectedRepositories) { + new VcsPushDialog(project, selectedRepositories).show(); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java index 938413e95356..279747c5278b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java @@ -25,7 +25,7 @@ import org.zmlx.hg4idea.ui.HgRunConflictResolverDialog; import java.util.Collection; -public class HgRunConflictResolverAction extends HgAbstractGlobalAction { +public class HgRunConflictResolverAction extends HgAbstractGlobalSingleRepoAction { @Override public void execute(@NotNull final Project project, @NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java index 7e1025921234..415cd223bd1f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java @@ -29,7 +29,7 @@ import org.zmlx.hg4idea.util.HgErrorUtil; import java.util.Collection; -public class HgUpdateToAction extends HgAbstractGlobalAction { +public class HgUpdateToAction extends HgAbstractGlobalSingleRepoAction { @Override protected void execute(@NotNull Project project, @NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java index c719d9174d39..4acbc1f72370 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java @@ -31,7 +31,7 @@ public class HgIdentifyCommand { public HgCommandResult execute(@NotNull ModalityState state) { final List<String> arguments = new LinkedList<String>(); arguments.add(source); - final HgRemoteCommandExecutor executor = new HgRemoteCommandExecutor(project, source, state); + final HgRemoteCommandExecutor executor = new HgRemoteCommandExecutor(project, source, state, false); executor.setSilent(true); return executor.executeInCurrentThread(null, "identify", arguments); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgOutgoingCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgOutgoingCommand.java index 64f155064ead..578af65a6b56 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgOutgoingCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgOutgoingCommand.java @@ -12,11 +12,19 @@ // limitations under the License. package org.zmlx.hg4idea.command; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.execution.HgCommandResult; +import org.zmlx.hg4idea.execution.HgRemoteCommandExecutor; +import org.zmlx.hg4idea.log.HgHistoryUtil; import org.zmlx.hg4idea.util.HgUtil; +import java.util.LinkedList; +import java.util.List; + public class HgOutgoingCommand extends HgRemoteChangesetsCommand { public HgOutgoingCommand(Project project) { @@ -27,4 +35,23 @@ public class HgOutgoingCommand extends HgRemoteChangesetsCommand { protected String getRepositoryUrl(VirtualFile root) { return HgUtil.getRepositoryDefaultPushPath(project, root); } + + @Nullable + public HgCommandResult execute(@NotNull VirtualFile repo, + @NotNull String template, + @NotNull String source, + @NotNull String destination, + boolean doNotShowAuthorizationRequest) { + + List<String> arguments = new LinkedList<String>(); + arguments.add("-n"); + arguments.add("--template"); + arguments.add(template); + arguments.add(HgHistoryUtil.prepareParameter("rev", source)); + arguments.add(destination); + HgRemoteCommandExecutor commandExecutor = + new HgRemoteCommandExecutor(project, destination, ModalityState.any(), doNotShowAuthorizationRequest); + commandExecutor.setOutputAlwaysSuppressed(true); + return commandExecutor.executeInCurrentThread(repo, "outgoing", arguments); + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java index 14f6c981777b..01f9083da808 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java @@ -39,10 +39,13 @@ class HgCommandAuthenticator { private GetPasswordRunnable myGetPassword; private final Project myProject; private boolean myForceAuthorization; + //todo replace silent mode and/or force authorization + private boolean mySilentMode; - public HgCommandAuthenticator(Project project, boolean forceAuthorization) { + public HgCommandAuthenticator(Project project, boolean forceAuthorization, boolean silent) { myProject = project; myForceAuthorization = forceAuthorization; + mySilentMode = silent; } public void saveCredentials() { @@ -71,7 +74,7 @@ class HgCommandAuthenticator { } public boolean promptForAuthentication(Project project, String proposedLogin, String uri, String path, @Nullable ModalityState state) { - GetPasswordRunnable runnable = new GetPasswordRunnable(project, proposedLogin, uri, path, myForceAuthorization); + GetPasswordRunnable runnable = new GetPasswordRunnable(project, proposedLogin, uri, path, myForceAuthorization, mySilentMode); ApplicationManager.getApplication().invokeAndWait(runnable, state == null ? ModalityState.defaultModalityState() : state); myGetPassword = runnable; return runnable.isOk(); @@ -96,19 +99,27 @@ class HgCommandAuthenticator { @Nullable private String myURL; private boolean myRememberPassword; private boolean myForceAuthorization; + private final boolean mySilent; - public GetPasswordRunnable(Project project, String proposedLogin, String uri, String path, boolean forceAuthorization) { + public GetPasswordRunnable(Project project, + String proposedLogin, + String uri, + String path, + boolean forceAuthorization, boolean silent) { this.myProject = project; this.myProposedLogin = proposedLogin; this.myURL = uri + path; this.myForceAuthorization = forceAuthorization; + mySilent = silent; } - + public void run() { // find if we've already been here final HgVcs vcs = HgVcs.getInstance(myProject); - if (vcs == null) { return; } + if (vcs == null) { + return; + } @NotNull final HgGlobalSettings hgGlobalSettings = vcs.getGlobalSettings(); @Nullable String rememberedLoginsForUrl = null; @@ -128,11 +139,14 @@ class HgCommandAuthenticator { final String key = keyForUrlAndLogin(myURL, login); try { final PasswordSafeImpl passwordSafe = (PasswordSafeImpl)PasswordSafe.getInstance(); - password = passwordSafe.getMemoryProvider().getPassword(myProject, HgCommandAuthenticator.class, key); - if (password == null) { + if (mySilent) { + password = passwordSafe.getMemoryProvider().getPassword(myProject, HgCommandAuthenticator.class, key); + } + else { password = passwordSafe.getPassword(myProject, HgCommandAuthenticator.class, key); } - } catch (PasswordSafeException e) { + } + catch (PasswordSafeException e) { LOG.info("Couldn't get password for key [" + key + "]", e); } } @@ -146,7 +160,13 @@ class HgCommandAuthenticator { return; } - final AuthDialog dialog = new AuthDialog(myProject, HgVcsMessages.message("hg4idea.dialog.login.password.required"), HgVcsMessages.message("hg4idea.dialog.login.description", myURL), + if (mySilent) { + ok = false; + return; + } + + final AuthDialog dialog = new AuthDialog(myProject, HgVcsMessages.message("hg4idea.dialog.login.password.required"), + HgVcsMessages.message("hg4idea.dialog.login.description", myURL), login, password, true); dialog.show(); if (dialog.isOK()) { @@ -182,5 +202,4 @@ class HgCommandAuthenticator { private static String keyForUrlAndLogin(String stringUrl, String login) { return login + ":" + stringUrl; } - } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgRemoteCommandExecutor.java b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgRemoteCommandExecutor.java index fdab67fbed6f..ce139cb16d9e 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgRemoteCommandExecutor.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgRemoteCommandExecutor.java @@ -30,16 +30,22 @@ import java.util.List; public class HgRemoteCommandExecutor extends HgCommandExecutor { @Nullable private ModalityState myState; + final boolean myIgnoreAuthorizationRequest; public HgRemoteCommandExecutor(@NotNull Project project, @Nullable String destination) { - this(project, destination, null); + this(project, destination, null, false); + } + + public HgRemoteCommandExecutor(@NotNull Project project, @Nullable String destination, boolean ignoreAuthorizationRequest) { + this(project, destination, null, ignoreAuthorizationRequest); } public HgRemoteCommandExecutor(@NotNull Project project, @Nullable String destination, - @Nullable ModalityState state) { + @Nullable ModalityState state, boolean ignoreAuthorizationRequest) { super(project, destination); myState = state; + myIgnoreAuthorizationRequest = ignoreAuthorizationRequest; } @Nullable @@ -48,7 +54,7 @@ public class HgRemoteCommandExecutor extends HgCommandExecutor { HgCommandResult result = executeInCurrentThread(repo, operation, arguments, false); - if (HgErrorUtil.isAuthorizationError(result)) { + if (!myIgnoreAuthorizationRequest && HgErrorUtil.isAuthorizationError(result)) { if (HgErrorUtil.hasAuthorizationInDestinationPath(myDestination)) { new HgCommandResultNotifier(myProject) .notifyError(result, "Authorization failed", "Your hgrc file settings have wrong username or password in [paths].\n" + @@ -62,11 +68,11 @@ public class HgRemoteCommandExecutor extends HgCommandExecutor { @Nullable private HgCommandResult executeInCurrentThread(@Nullable final VirtualFile repo, - @NotNull final String operation, - @Nullable final List<String> arguments, - boolean forceAuthorization) { + @NotNull final String operation, + @Nullable final List<String> arguments, + boolean forceAuthorization) { - PassReceiver passReceiver = new PassReceiver(myProject, forceAuthorization, myState); + PassReceiver passReceiver = new PassReceiver(myProject, forceAuthorization, myIgnoreAuthorizationRequest, myState); SocketServer passServer = new SocketServer(passReceiver); try { int passPort = passServer.start(); @@ -109,11 +115,13 @@ public class HgRemoteCommandExecutor extends HgCommandExecutor { private final Project myProject; private HgCommandAuthenticator myAuthenticator; private boolean myForceAuthorization; + private boolean mySilentMode; @Nullable private ModalityState myState; - private PassReceiver(Project project, boolean forceAuthorization, @Nullable ModalityState state) { + private PassReceiver(Project project, boolean forceAuthorization, boolean silent, @Nullable ModalityState state) { myProject = project; myForceAuthorization = forceAuthorization; + mySilentMode = silent; myState = state; } @@ -129,7 +137,7 @@ public class HgRemoteCommandExecutor extends HgCommandExecutor { String path = new String(readDataBlock(dataInputStream)); String proposedLogin = new String(readDataBlock(dataInputStream)); - HgCommandAuthenticator authenticator = new HgCommandAuthenticator(myProject, myForceAuthorization); + HgCommandAuthenticator authenticator = new HgCommandAuthenticator(myProject, myForceAuthorization, mySilentMode); boolean ok = authenticator.promptForAuthentication(myProject, proposedLogin, uri, path, myState); if (ok) { myAuthenticator = authenticator; diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java index dfb576f98ab3..de565484e2d5 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java @@ -94,25 +94,35 @@ public class HgHistoryUtil { } /** - * <p>Get & parse hg log detailed output with commits, their parents and their changes.</p> + * <p>Get & parse hg log detailed output with commits, their parents and their changes. + * For null destination return log command result</p> * <p/> * <p>Warning: this is method is efficient by speed, but don't query too much, because the whole log output is retrieved at once, * and it can occupy too much memory. The estimate is ~600Kb for 1000 commits.</p> */ @NotNull - public static List<? extends VcsFullCommitDetails> history(@NotNull final Project project, @NotNull final VirtualFile root, int limit, + public static List<? extends VcsFullCommitDetails> history(@NotNull final Project project, + @NotNull final VirtualFile root, + int limit, @NotNull List<String> parameters) throws VcsException { - final VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project); - if (factory == null) { - return Collections.emptyList(); - } HgVcs hgvcs = HgVcs.getInstance(project); assert hgvcs != null; final HgVersion version = hgvcs.getVersion(); String[] templates = HgBaseLogParser.constructFullTemplateArgument(true, version); HgCommandResult result = getLogResult(project, root, version, limit, parameters, HgChangesetUtil.makeTemplate(templates)); + return createFullCommitsFromResult(project, root, result, version, false); + } + + public static List<? extends VcsFullCommitDetails> createFullCommitsFromResult(@NotNull Project project, + @NotNull VirtualFile root, + @Nullable HgCommandResult result, + @NotNull HgVersion version, boolean silent) { + final VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project); + if (factory == null) { + return Collections.emptyList(); + } List<HgFileRevision> hgRevisions = - getCommitRecords(project, result, new HgFileRevisionLogParser(project, getOriginalHgFile(project, root), version)); + getCommitRecords(project, result, new HgFileRevisionLogParser(project, getOriginalHgFile(project, root), version), silent); List<VcsFullCommitDetails> vcsFullCommitDetailsList = new ArrayList<VcsFullCommitDetails>(); for (HgFileRevision revision : hgRevisions) { @@ -184,6 +194,13 @@ public class HgHistoryUtil { public static <CommitInfo> List<CommitInfo> getCommitRecords(@NotNull Project project, @Nullable HgCommandResult result, @NotNull Function<String, CommitInfo> converter) { + return getCommitRecords(project, result, converter, false); + } + + @NotNull + public static <CommitInfo> List<CommitInfo> getCommitRecords(@NotNull Project project, + @Nullable HgCommandResult result, + @NotNull Function<String, CommitInfo> converter, boolean silent) { final List<CommitInfo> revisions = new LinkedList<CommitInfo>(); if (result == null) { return revisions; @@ -192,7 +209,12 @@ public class HgHistoryUtil { List<String> errors = result.getErrorLines(); if (errors != null && !errors.isEmpty()) { if (result.getExitValue() != 0) { - VcsNotifier.getInstance(project).notifyError(HgVcsMessages.message("hg4idea.error.log.command.execution"), errors.toString()); + if (silent) { + LOG.warn(errors.toString()); + } + else { + VcsNotifier.getInstance(project).notifyError(HgVcsMessages.message("hg4idea.error.log.command.execution"), errors.toString()); + } return Collections.emptyList(); } LOG.warn(errors.toString()); @@ -331,4 +353,8 @@ public class HgHistoryUtil { } return branchHeads; } + + public static String prepareParameter(String paramName, String value) { + return "--" + paramName + "=" + value; // no value escaping needed, because the parameter itself will be quoted by GeneralCommandLine + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java index 4adec9dff515..3b989e448b61 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java @@ -180,11 +180,11 @@ public class HgLogProvider implements VcsLogProvider { boolean atLeastOneBranchExists = false; for (String branchName : filterCollection.getBranchFilter().getBranchNames()) { if (branchName.equals(TIP_REFERENCE) || branchExists(repository, branchName)) { - filterParameters.add(prepareParameter("branch", branchName)); + filterParameters.add(HgHistoryUtil.prepareParameter("branch", branchName)); atLeastOneBranchExists = true; } else if (branchName.equals(HEAD_REFERENCE)) { - filterParameters.add(prepareParameter("branch", ".")); + filterParameters.add(HgHistoryUtil.prepareParameter("branch", ".")); filterParameters.add("-r"); filterParameters.add("::."); //all ancestors for current revision; atLeastOneBranchExists = true; @@ -197,7 +197,7 @@ public class HgLogProvider implements VcsLogProvider { if (filterCollection.getUserFilter() != null) { for (String authorName : filterCollection.getUserFilter().getUserNames(root)) { - filterParameters.add(prepareParameter("user", authorName)); + filterParameters.add(HgHistoryUtil.prepareParameter("user", authorName)); } } @@ -223,7 +223,7 @@ public class HgLogProvider implements VcsLogProvider { if (filterCollection.getTextFilter() != null) { String textFilter = filterCollection.getTextFilter().getText(); - filterParameters.add(prepareParameter("keyword", textFilter)); + filterParameters.add(HgHistoryUtil.prepareParameter("keyword", textFilter)); } if (filterCollection.getStructureFilter() != null) { @@ -262,10 +262,6 @@ public class HgLogProvider implements VcsLogProvider { return HgHistoryUtil.getDescendingHeadsOfBranches(myProject, root, commitHash); } - private static String prepareParameter(String paramName, String value) { - return "--" + paramName + "=" + value; // no value escaping needed, because the parameter itself will be quoted by GeneralCommandLine - } - private static boolean branchExists(@NotNull HgRepository repository, @NotNull String branchName) { return repository.getBranches().keySet().contains(branchName) || HgUtil.getNamesWithoutHashes(repository.getBookmarks()).contains(branchName); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java index c60e46c63ced..06b74148156e 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java @@ -13,6 +13,7 @@ package org.zmlx.hg4idea.provider.commit; import com.intellij.dvcs.DvcsCommitAdditionalComponent; +import com.intellij.dvcs.push.ui.VcsPushDialog; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.progress.ProgressIndicator; @@ -37,6 +38,7 @@ import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.action.HgActionUtil; import org.zmlx.hg4idea.command.*; import org.zmlx.hg4idea.execution.HgCommandException; import org.zmlx.hg4idea.execution.HgCommandExecutor; @@ -132,13 +134,12 @@ public class HgCheckinEnvironment implements CheckinEnvironment { // push if needed if (myNextCommitIsPushed && exceptions.isEmpty()) { - final VirtualFile preselectedRepo = repositoriesMap.size() == 1 ? repositoriesMap.keySet().iterator().next() : null; + final Set<VirtualFile> preselectedFiles = repositoriesMap.keySet(); HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(myProject); - final HgRepository repo = preselectedRepo != null ? repositoryManager.getRepositoryForFile(preselectedRepo) : null; - final Collection<HgRepository> repositories = repositoryManager.getRepositories(); + final List<HgRepository> preselectedRepositories = HgActionUtil.collectRepositoriesFromFiles(repositoryManager, preselectedFiles); UIUtil.invokeLaterIfNeeded(new Runnable() { public void run() { - new HgPusher(myProject).showDialogAndPush(repositories, repo); + new VcsPushDialog(myProject, preselectedRepositories).show(); } }); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java new file mode 100644 index 000000000000..70055cafe1a1 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java @@ -0,0 +1,90 @@ +/* + * 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 org.zmlx.hg4idea.push; + +import com.intellij.dvcs.push.*; +import com.intellij.dvcs.repo.Repository; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.vcs.log.VcsFullCommitDetails; +import org.jetbrains.annotations.NotNull; +import org.zmlx.hg4idea.HgVcs; +import org.zmlx.hg4idea.command.HgOutgoingCommand; +import org.zmlx.hg4idea.execution.HgCommandResult; +import org.zmlx.hg4idea.log.HgBaseLogParser; +import org.zmlx.hg4idea.log.HgHistoryUtil; +import org.zmlx.hg4idea.util.HgChangesetUtil; +import org.zmlx.hg4idea.util.HgErrorUtil; +import org.zmlx.hg4idea.util.HgVersion; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class HgOutgoingCommitsProvider extends OutgoingCommitsProvider { + + + private static final Logger LOG = Logger.getInstance(HgOutgoingCommitsProvider.class); + private static final String LOGIN_AND_REFRESH_LINK = "Enter Password & Refresh"; + + @NotNull + @Override + public OutgoingResult getOutgoingCommits(@NotNull final Repository repository, + @NotNull final PushSpec pushSpec, + boolean initial) { + final Project project = repository.getProject(); + HgVcs hgvcs = HgVcs.getInstance(project); + assert hgvcs != null; + final HgVersion version = hgvcs.getVersion(); + String[] templates = HgBaseLogParser.constructFullTemplateArgument(true, version); + HgOutgoingCommand hgOutgoingCommand = new HgOutgoingCommand(project); + HgTarget hgTarget = (HgTarget)pushSpec.getTarget(); + List<VcsError> errors = new ArrayList<VcsError>(); + if (hgTarget == null || StringUtil.isEmptyOrSpaces(hgTarget.myTarget)) { + errors.add(new VcsError("Hg push path could not be empty.")); + return new OutgoingResult(Collections.<VcsFullCommitDetails>emptyList(), errors); + } + HgCommandResult result = hgOutgoingCommand + .execute(repository.getRoot(), HgChangesetUtil.makeTemplate(templates), pushSpec.getSource().getPresentation(), + hgTarget.myTarget, initial); + if (result == null) { + errors.add(new VcsError("Couldn't execute hg outgoing command for " + repository)); + return new OutgoingResult(Collections.<VcsFullCommitDetails>emptyList(), errors); + } + List<String> resultErrors = result.getErrorLines(); + if (resultErrors != null && !resultErrors.isEmpty() && result.getExitValue() != 0) { + for (String error : resultErrors) { + if (HgErrorUtil.isAbortLine(error)) { + if (HgErrorUtil.isAuthorizationError(error)) { + VcsError authorizationError = + new VcsError(error + "<a href='authenticate'>" + LOGIN_AND_REFRESH_LINK + "</a>", new VcsErrorHandler() { + public void handleError(@NotNull CommitLoader commitLoader) { + commitLoader.reloadCommits(); + } + }); + errors.add(authorizationError); + } + else { + errors.add(new VcsError(error)); + } + } + } + LOG.warn(resultErrors.toString()); + } + return new OutgoingResult(HgHistoryUtil.createFullCommitsFromResult(project, repository.getRoot(), result, version, true), errors); + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushOptionsPanel.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushOptionsPanel.java new file mode 100644 index 000000000000..336f8ff1aa4c --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushOptionsPanel.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 org.zmlx.hg4idea.push; + +import com.intellij.dvcs.push.VcsPushOptionsPanel; +import com.intellij.openapi.ui.ComboBox; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionListener; + +public class HgPushOptionsPanel extends VcsPushOptionsPanel { + + private final ComboBox myReferenceStrategyCombobox; + + public HgPushOptionsPanel() { + setLayout(new BorderLayout()); + myReferenceStrategyCombobox = new ComboBox(); + HgVcsPushOptionValue[] values = HgVcsPushOptionValue.values(); + DefaultComboBoxModel comboModel = new DefaultComboBoxModel(values); + myReferenceStrategyCombobox.setModel(comboModel); + JLabel referenceStrategyLabel = new JLabel("Export Bookmarks: "); + add(referenceStrategyLabel, BorderLayout.WEST); + add(myReferenceStrategyCombobox, BorderLayout.CENTER); + } + + @Override + @NotNull + public HgVcsPushOptionValue getValue() { + return (HgVcsPushOptionValue)myReferenceStrategyCombobox.getSelectedItem(); + } + + @Override + public void addValueChangeListener(ActionListener listener) { + myReferenceStrategyCombobox.addActionListener(listener); + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSource.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSource.java new file mode 100644 index 000000000000..babd49c9b31d --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSource.java @@ -0,0 +1,38 @@ +/* + * 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 org.zmlx.hg4idea.push; + +import com.intellij.dvcs.push.PushSource; +import org.jetbrains.annotations.NotNull; + +public class HgPushSource implements PushSource { + @NotNull private String myBranch; + + public HgPushSource(@NotNull String branch) { + myBranch = branch; + } + + @NotNull + @Override + public String getPresentation() { + return myBranch; + } + + @NotNull + public String getBranch() { + return myBranch; // presentation may differ from branch + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java new file mode 100644 index 000000000000..4bfa134a5e26 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java @@ -0,0 +1,109 @@ +/* + * 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 org.zmlx.hg4idea.push; + +import com.intellij.dvcs.push.*; +import com.intellij.dvcs.repo.Repository; +import com.intellij.dvcs.repo.RepositoryManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vcs.AbstractVcs; +import com.intellij.util.Function; +import com.intellij.util.ObjectUtils; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.HgVcs; +import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.util.HgUtil; + +import java.util.Collection; + +public class HgPushSupport extends PushSupport<HgRepository> { + + @NotNull private final Project myProject; + @NotNull private final HgVcs myVcs; + + public HgPushSupport(@NotNull Project project) { + myProject = project; + myVcs = ObjectUtils.assertNotNull(HgVcs.getInstance(myProject)); + } + + @NotNull + @Override + public AbstractVcs getVcs() { + return myVcs; + } + + @NotNull + @Override + public Pusher getPusher() { + return new HgPusher(); + } + + @NotNull + @Override + public OutgoingCommitsProvider getOutgoingCommitsProvider() { + return new HgOutgoingCommitsProvider(); + } + + @Nullable + @Override + public HgTarget getDefaultTarget(@NotNull HgRepository repository) { + String defaultPushPath = repository.getRepositoryConfig().getDefaultPushPath(); + return defaultPushPath == null ? null : new HgTarget(defaultPushPath); + } + + @NotNull + @Override + public Collection<String> getTargetNames(@NotNull HgRepository repository) { + return ContainerUtil.map(repository.getRepositoryConfig().getPaths(), new Function<String, String>() { + @Override + public String fun(String s) { + return HgUtil.removePasswordIfNeeded(s); + } + }); + } + + @NotNull + @Override + public HgPushSource getSource(@NotNull HgRepository repository) { + String localBranch = HgUtil.getActiveBranchName(repository); + return new HgPushSource(localBranch); + } + + @Override + public HgTarget createTarget(@NotNull HgRepository repository, @NotNull String targetName) { + return new HgTarget(targetName); + } + + @NotNull + @Override + public RepositoryManager<HgRepository> getRepositoryManager() { + return HgUtil.getRepositoryManager(myProject); + } + + @Nullable + public VcsPushOptionsPanel getVcsPushOptionsPanel() { + return new HgPushOptionsPanel(); + } + + @Override + @Nullable + public VcsError validate(@NotNull Repository repository, @Nullable String targetToValidate) { + return StringUtil.isEmptyOrSpaces(targetToValidate) ? new VcsError("Please, specify remote push path for repository!") : null; + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgPusher.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPusher.java index 2b6108dddbbc..f019035a373f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgPusher.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPusher.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,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.zmlx.hg4idea; +package org.zmlx.hg4idea.push; +import com.intellij.dvcs.push.PushSpec; +import com.intellij.dvcs.push.Pusher; +import com.intellij.dvcs.push.VcsPushOptionValue; +import com.intellij.dvcs.repo.Repository; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsNotifier; -import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,52 +31,54 @@ import org.zmlx.hg4idea.command.HgPushCommand; import org.zmlx.hg4idea.execution.HgCommandResult; import org.zmlx.hg4idea.execution.HgCommandResultHandler; import org.zmlx.hg4idea.repo.HgRepository; -import org.zmlx.hg4idea.ui.HgPushDialog; -import java.util.Collection; import java.util.List; -import java.util.concurrent.atomic.AtomicReference; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class HgPusher { +public class HgPusher extends Pusher { private static final Logger LOG = Logger.getInstance(HgPusher.class); - private static Pattern PUSH_COMMITS_PATTERN = Pattern.compile(".*added (\\d+) changesets.*"); + private static final String ONE = "one"; + private static Pattern PUSH_COMMITS_PATTERN = Pattern.compile(".*(?:added|pushed) (\\d+|" + ONE + ") changeset.*"); // hg push command has definite exit values for some cases: // mercurial returns 0 if push was successful, 1 if nothing to push. see hg push --help private static int PUSH_SUCCEEDED_EXIT_VALUE = 0; private static int NOTHING_TO_PUSH_EXIT_VALUE = 1; - private final Project myProject; - - public HgPusher(Project project) { - myProject = project; - } - - public void showDialogAndPush (@NotNull Collection<HgRepository> repositories,@Nullable final HgRepository selectedRepo) { - - if (repositories.isEmpty()) { - VcsBalloonProblemNotifier.showOverChangesView(myProject, "No Mercurial repositories in the project", MessageType.ERROR); - return; - } - final AtomicReference<HgPushCommand> pushCommand = new AtomicReference<HgPushCommand>(); - final HgPushDialog dialog = new HgPushDialog(myProject, repositories, selectedRepo); - dialog.show(); - if (dialog.isOK()) { - pushCommand.set(preparePushCommand(myProject, dialog)); - new Task.Backgroundable(myProject, "Pushing...", false) { - @Override - public void run(@NotNull ProgressIndicator indicator) { - if (pushCommand.get() != null) { - push(myProject, pushCommand.get()); - } + @Override + public void push(@NotNull Map<Repository, PushSpec> pushSpecs, @Nullable VcsPushOptionValue vcsPushOptionValue, boolean force) { + for (Map.Entry<Repository, PushSpec> entry : pushSpecs.entrySet()) { + Repository repository = entry.getKey(); + HgRepository hgRepository = (HgRepository)repository; + PushSpec hgSpec = entry.getValue(); + HgTarget destination = (HgTarget)hgSpec.getTarget(); + if (destination == null) { + continue; + } + HgPushSource source = (HgPushSource)hgSpec.getSource(); + Project project = repository.getProject(); + final HgPushCommand pushCommand = new HgPushCommand(project, repository.getRoot(), destination.myTarget); + pushCommand.setIsNewBranch(true); // set always true, because it just allow mercurial to create a new one if needed + pushCommand.setForce(force); + String branchName = source.getBranch(); + if (branchName.equals(hgRepository.getCurrentBookmark())) { + if (vcsPushOptionValue == HgVcsPushOptionValue.Current) { + pushCommand.setBookmarkName(branchName); + } + else { + pushCommand.setRevision(branchName); } - }.queue(); + } + else { + pushCommand.setBranchName(branchName); + } + push(project, pushCommand); } } - private static void push(final Project project, HgPushCommand command) { + public static void push(@NotNull final Project project, @NotNull HgPushCommand command) { final VirtualFile repo = command.getRepo(); command.execute(new HgCommandResultHandler() { @Override @@ -91,9 +93,11 @@ public class HgPusher { String successDescription = String.format("Pushed %d %s [%s]", commitsNum, StringUtil.pluralize("commit", commitsNum), repo.getPresentableName()); VcsNotifier.getInstance(project).notifySuccess(successTitle, successDescription); - } else if (result.getExitValue() == NOTHING_TO_PUSH_EXIT_VALUE) { + } + else if (result.getExitValue() == NOTHING_TO_PUSH_EXIT_VALUE) { VcsNotifier.getInstance(project).notifySuccess("Nothing to push"); - } else { + } + else { new HgCommandResultNotifier(project).notifyError(result, "Push failed", "Failed to push to [" + repo.getPresentableName() + "]"); } @@ -101,17 +105,7 @@ public class HgPusher { }); } - private static HgPushCommand preparePushCommand(Project project, HgPushDialog dialog) { - final HgPushCommand command = new HgPushCommand(project, dialog.getRepository().getRoot(), dialog.getTarget()); - command.setRevision(dialog.getRevision()); - command.setForce(dialog.isForce()); - command.setBranchName(dialog.getBranch()); - command.setBookmarkName(dialog.getBookmarkName()); - command.setIsNewBranch(dialog.isNewBranch()); - return command; - } - - private static int getNumberOfPushedCommits(HgCommandResult result) { + private static int getNumberOfPushedCommits(@NotNull HgCommandResult result) { int numberOfCommitsInAllSubrepos = 0; final List<String> outputLines = result.getOutputLines(); for (String outputLine : outputLines) { @@ -119,7 +113,8 @@ public class HgPusher { final Matcher matcher = PUSH_COMMITS_PATTERN.matcher(outputLine); if (matcher.matches()) { try { - numberOfCommitsInAllSubrepos += Integer.parseInt(matcher.group(1)); + String numberOfCommits = matcher.group(1); + numberOfCommitsInAllSubrepos += ONE.equals(numberOfCommits) ? 1 : Integer.parseInt(numberOfCommits); } catch (NumberFormatException e) { LOG.error("getNumberOfPushedCommits ", e); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgTarget.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgTarget.java new file mode 100644 index 000000000000..8f5aca3838ca --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgTarget.java @@ -0,0 +1,34 @@ +/* + * 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 org.zmlx.hg4idea.push; + +import com.intellij.dvcs.push.PushTarget; +import org.jetbrains.annotations.NotNull; +import org.zmlx.hg4idea.util.HgUtil; + +public class HgTarget implements PushTarget { + @NotNull String myTarget; + + public HgTarget(@NotNull String name) { + myTarget = name; + } + + @Override + @NotNull + public String getPresentation() { + return HgUtil.removePasswordIfNeeded(myTarget); + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgVcsPushOptionValue.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgVcsPushOptionValue.java new file mode 100644 index 000000000000..5b35e7f5e6e0 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgVcsPushOptionValue.java @@ -0,0 +1,22 @@ +/* + * 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 org.zmlx.hg4idea.push; + +import com.intellij.dvcs.push.VcsPushOptionValue; + +public enum HgVcsPushOptionValue implements VcsPushOptionValue { + None, Current +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java index 77c81ee80993..b670fb056c0c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java @@ -21,6 +21,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcs.log.Hash; @@ -96,6 +97,12 @@ public class HgRepositoryImpl extends RepositoryImpl implements HgRepository { return myInfo.getState(); } + @Nullable + @Override + public AbstractVcs getVcs() { + return HgVcs.getInstance(getProject()); + } + @Override @NotNull public String getCurrentBranch() { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java index 1810370588b7..7592f5830ee5 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java @@ -43,7 +43,7 @@ public final class HgErrorUtil { } final List<String> errorLines = result.getErrorLines(); for (String line : errorLines) { - if (!StringUtil.isEmptyOrSpaces(line) && line.trim().startsWith("abort:")) { + if (isAbortLine(line)) { return true; } } @@ -55,8 +55,7 @@ public final class HgErrorUtil { return false; } String line = getLastErrorLine(result); - return !StringUtil.isEmptyOrSpaces(line) && (line.contains("authorization required") || line.contains("authorization failed") - ); + return isAuthorizationError(line); } @Nullable @@ -119,4 +118,12 @@ public final class HgErrorUtil { Matcher matcher = UNCOMMITTED_PATTERN.matcher(result.getRawError()); return matcher.matches(); } + + public static boolean isAuthorizationError(String line) { + return !StringUtil.isEmptyOrSpaces(line) && (line.contains("authorization required") || line.contains("authorization failed")); + } + + public static boolean isAbortLine(String line) { + return !StringUtil.isEmptyOrSpaces(line) && line.trim().startsWith("abort:"); + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java index 1cc100efb029..3bb14721f0a8 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java @@ -32,6 +32,7 @@ import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vcs.history.FileHistoryPanelImpl; import com.intellij.openapi.vcs.history.VcsFileRevisionEx; +import com.intellij.openapi.vcs.vfs.AbstractVcsVirtualFile; import com.intellij.openapi.vcs.vfs.VcsVirtualFile; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.LocalFileSystem; @@ -474,7 +475,7 @@ public abstract class HgUtil { */ @Nullable public static VirtualFile convertToLocalVirtualFile(@Nullable VirtualFile file) { - if (!(file instanceof VcsVirtualFile)) { + if (!(file instanceof AbstractVcsVirtualFile)) { return file; } LocalFileSystem lfs = LocalFileSystem.getInstance(); @@ -583,11 +584,16 @@ public abstract class HgUtil { if (state != HgRepository.State.NORMAL) { branchText += state.toString() + " "; } + return branchText + getActiveBranchName(repository); + } + + @NotNull + public static String getActiveBranchName(@NotNull HgRepository repository) { String branchOrBookMarkName = repository.getCurrentBookmark(); if (StringUtil.isEmptyOrSpaces(branchOrBookMarkName)) { branchOrBookMarkName = repository.getCurrentBranch(); } - return branchText + branchOrBookMarkName; + return branchOrBookMarkName; } @NotNull diff --git a/plugins/java-i18n/src/META-INF/plugin.xml b/plugins/java-i18n/src/META-INF/plugin.xml index b352a2f78e08..dca09990aeac 100644 --- a/plugins/java-i18n/src/META-INF/plugin.xml +++ b/plugins/java-i18n/src/META-INF/plugin.xml @@ -26,6 +26,7 @@ <psi.referenceContributor implementation="com.intellij.lang.properties.PropertiesReferenceContributor"/> <lang.foldingBuilder language="JAVA" implementationClass="com.intellij.codeInspection.i18n.folding.PropertyFoldingBuilder" order="FIRST"/> <gotoDeclarationHandler implementation="com.intellij.codeInspection.i18n.folding.I18nMessageGotoDeclarationHandler" order="FIRST"/> + <inlineActionHandler implementation="com.intellij.refactoring.inline.InlinePropertyHandler"/> <localInspection shortName="HardCodedStringLiteral" bundle="messages.CodeInsightBundle" key="inspection.i18n.display.name" groupBundle="messages.InspectionsBundle" groupKey="group.names.internationalization.issues" enabledByDefault="false" level="WARNING" diff --git a/plugins/java-i18n/src/com/intellij/refactoring/inline/InlinePropertyHandler.java b/plugins/java-i18n/src/com/intellij/refactoring/inline/InlinePropertyHandler.java new file mode 100644 index 000000000000..151b8e605f8c --- /dev/null +++ b/plugins/java-i18n/src/com/intellij/refactoring/inline/InlinePropertyHandler.java @@ -0,0 +1,120 @@ +/* + * 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.refactoring.inline; + +import com.intellij.lang.properties.IProperty; +import com.intellij.lang.properties.PropertiesBundle; +import com.intellij.lang.properties.references.PropertyReference; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.refactoring.HelpID; +import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.listeners.RefactoringEventData; +import com.intellij.refactoring.listeners.RefactoringEventListener; +import com.intellij.refactoring.util.CommonRefactoringUtil; +import com.intellij.refactoring.util.RefactoringMessageDialog; +import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.FilteringIterator; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; + +/** + * @author gregsh + */ +public class InlinePropertyHandler extends JavaInlineActionHandler { + public static final String REFACTORING_NAME = PropertiesBundle.message("inline.property.refactoring"); + public static final String REFACTORING_ID = "refactoring.inline.property"; + + public boolean canInlineElement(PsiElement element) { + if (element instanceof PsiJavaToken && ((PsiJavaToken)element).getTokenType() == JavaTokenType.STRING_LITERAL) { + PsiReference[] references = element.getParent().getReferences(); + return ContainerUtil.find(references, FilteringIterator.instanceOf(PropertyReference.class)) != null; + } + return element instanceof IProperty; + } + + public void inlineElement(final Project project, Editor editor, PsiElement psiElement) { + if (!(psiElement instanceof IProperty)) return; + + IProperty property = (IProperty)psiElement; + final String propertyValue = property.getValue(); + if (propertyValue == null) return; + + final List<PsiElement> occurrences = Collections.synchronizedList(ContainerUtil.<PsiElement>newArrayList()); + final Collection<PsiFile> containingFiles = Collections.synchronizedSet(new HashSet<PsiFile>()); + containingFiles.add(psiElement.getContainingFile()); + boolean result = ReferencesSearch.search(psiElement).forEach( + new Processor<PsiReference>() { + public boolean process(final PsiReference psiReference) { + PsiElement element = psiReference.getElement(); + PsiElement parent = element.getParent(); + if (parent instanceof PsiExpressionList && parent.getParent() instanceof PsiMethodCallExpression) { + if (((PsiExpressionList)parent).getExpressions().length == 1) { + occurrences.add(parent.getParent()); + containingFiles.add(element.getContainingFile()); + return true; + } + } + return false; + } + } + ); + + if (!result) { + CommonRefactoringUtil.showErrorHint(project, editor, "Property has non-method usages", REFACTORING_NAME, null); + } + if (occurrences.isEmpty()) { + CommonRefactoringUtil.showErrorHint(project, editor, "Property has no usages", REFACTORING_NAME, null); + return; + } + + if (!ApplicationManager.getApplication().isUnitTestMode()) { + String occurrencesString = RefactoringBundle.message("occurrences.string", occurrences.size()); + String question = PropertiesBundle.message("inline.property.confirmation", property.getName(), propertyValue) + " " + occurrencesString; + RefactoringMessageDialog dialog = new RefactoringMessageDialog(REFACTORING_NAME, question, HelpID.INLINE_VARIABLE, + "OptionPane.questionIcon", true, project); + dialog.show(); + if (!dialog.isOK()) { + return; + } + } + + final RefactoringEventData data = new RefactoringEventData(); + data.addElement(psiElement.copy()); + + new WriteCommandAction.Simple(project, REFACTORING_NAME, containingFiles.toArray(new PsiFile[containingFiles.size()])) { + @Override + protected void run() throws Throwable { + project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(REFACTORING_ID, data); + PsiLiteral stringLiteral = (PsiLiteral)JavaPsiFacade.getInstance(getProject()).getElementFactory(). + createExpressionFromText("\"" + StringUtil.escapeStringCharacters(propertyValue) + "\"", null); + for (PsiElement occurrence : occurrences) { + occurrence.replace(stringLiteral.copy()); + } + project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringDone(REFACTORING_ID, null); + } + }.execute(); + } +} diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java index f0c1eccd86f1..a0a90efe9c74 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java @@ -11,11 +11,13 @@ import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.fileEditor.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.ui.VerticalFlowLayout; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.vfs.ReadonlyStatusHandler; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.HyperlinkLabel; +import com.intellij.ui.ScrollPaneFactory; +import com.intellij.util.ExceptionUtil; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -42,8 +44,10 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor private final CardLayout myLayout = new CardLayout(); private final JPanel myPanel = new JPanel(myLayout); - private final JPanel myErrorPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 10, 5, true, false)); + //private final JPanel myErrorPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 10, 5, true, false)); + private final JPanel myErrorPanel = new JPanel(new BorderLayout()); private final HyperlinkLabel myErrorLabel = new HyperlinkLabel(); + private JTextArea myErrorStack; private final Document myDocument; private final ExternalChangeListener myChangeListener; @@ -72,11 +76,19 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor } }); - myErrorPanel.add(myErrorLabel); + myErrorStack = new JTextArea(50, 20); + myErrorStack.setEditable(false); + + myErrorPanel.add(myErrorLabel, BorderLayout.NORTH); + myErrorPanel.add(ScrollPaneFactory.createScrollPane(myErrorStack), BorderLayout.CENTER); myPanel.add(myErrorPanel); } private void showErrorPage(State state, Throwable e) { + if (e != null) { + LOG.info(e); + } + removeSceneBuilder(); if (e == null) { @@ -93,12 +105,21 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor } myErrorLabel.setIcon(Messages.getWarningIcon()); } + + myErrorStack.setText(null); + myErrorStack.setVisible(false); } else { - myErrorLabel.setHyperlinkText("Error: " + e.getMessage(), "", ""); + String message = e.getMessage(); + if (message == null) { + message = e.getClass().getName(); + } + + myErrorLabel.setHyperlinkText("Error: " + message, "", ""); myErrorLabel.setIcon(Messages.getErrorIcon()); - LOG.info(e); + myErrorStack.setText(ExceptionUtil.getThrowableText(e)); + myErrorStack.setVisible(true); } myLayout.show(myPanel, ERROR_CARD); } @@ -139,8 +160,12 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor } @Override - public void handleError(Throwable e) { - showErrorPage(null, e); + public void handleError(final Throwable e) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + public void run() { + showErrorPage(null, e); + } + }); } private void initSceneBuilder(boolean choosePathIfEmpty) { diff --git a/plugins/junit/src/com/intellij/execution/junit/TestPackage.java b/plugins/junit/src/com/intellij/execution/junit/TestPackage.java index 558b2e88dbda..3d3c2da89143 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestPackage.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestPackage.java @@ -27,7 +27,7 @@ import com.intellij.execution.process.ProcessAdapter; import com.intellij.execution.process.ProcessEvent; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ExecutionEnvironmentBuilder; -import com.intellij.execution.runners.ProgramRunner; +import com.intellij.execution.runners.ExecutionUtil; import com.intellij.execution.testframework.SourceScope; import com.intellij.execution.testframework.TestSearchScope; import com.intellij.openapi.application.ApplicationManager; @@ -43,7 +43,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.openapi.wm.ToolWindowManager; @@ -438,12 +437,10 @@ public class TestPackage extends TestObject { if (moduleByName != null) { myConfiguration.getConfigurationModule().setModule(moduleByName); try { - final Executor executor = myConsoleProperties.isDebug() ? DefaultDebugExecutor.getDebugExecutorInstance() - : DefaultRunExecutor.getRunExecutorInstance(); - final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(executor.getId(), myConfiguration); - assert runner != null; - runner.execute(new ExecutionEnvironmentBuilder(myEnvironment).setContentToReuse(null).build()); - final Balloon balloon = myToolWindowManager.getToolWindowBalloon(myTestRunDebugId); + Executor executor = myConsoleProperties.isDebug() ? DefaultDebugExecutor.getDebugExecutorInstance() + : DefaultRunExecutor.getRunExecutorInstance(); + ExecutionEnvironmentBuilder.create(myProject, executor, myConfiguration).contentToReuse(null).buildAndExecute(); + Balloon balloon = myToolWindowManager.getToolWindowBalloon(myTestRunDebugId); if (balloon != null) { balloon.hide(); } diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java index a1201c65a4d5..3fba1a3d9b7a 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java @@ -92,7 +92,13 @@ public class JUnit4IdeaTestRunner implements IdeaTestRunner { } private static Description getFilteredDescription(Request request, Description description) throws NoSuchFieldException, IllegalAccessException { - final Field field = FilterRequest.class.getDeclaredField("fFilter"); + Field field; + try { + field = FilterRequest.class.getDeclaredField("fFilter"); + } + catch (NoSuchFieldException e) { + field = FilterRequest.class.getDeclaredField("filter"); + } field.setAccessible(true); final Filter filter = (Filter)field.get(request); final String filterDescription = filter.describe(); @@ -125,7 +131,13 @@ public class JUnit4IdeaTestRunner implements IdeaTestRunner { } private static Description getSuiteMethodDescription(Request request, Description description) throws NoSuchFieldException, IllegalAccessException { - final Field field = ClassRequest.class.getDeclaredField("fTestClass"); + Field field; + try { + field = ClassRequest.class.getDeclaredField("fTestClass"); + } + catch (NoSuchFieldException e) { + field = ClassRequest.class.getDeclaredField("testClass"); + } field.setAccessible(true); final Description methodDescription = Description.createSuiteDescription((Class)field.get(request)); for (Iterator iterator = description.getChildren().iterator(); iterator.hasNext();) { diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java index d22ea44f2d8f..1bab2d69e1c5 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java @@ -352,12 +352,18 @@ public class JUnit4TestRunnerUtil { for (Iterator iterator = children.iterator(); iterator.hasNext(); ) { Object child = iterator.next(); try { + Class aClass = child.getClass(); Field f; try { - f = child.getClass().getDeclaredField("fName"); + f = aClass.getDeclaredField("fName"); } catch (NoSuchFieldException e) { - continue; + try { + f = aClass.getDeclaredField("name"); + } + catch (NoSuchFieldException e1) { + continue; + } } f.setAccessible(true); String fName = (String)f.get(child); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenResumeAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenResumeAction.java index 927b087a9fce..6d58aa895f6a 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenResumeAction.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenResumeAction.java @@ -301,7 +301,7 @@ public class MavenResumeAction extends AnAction { runConfiguration.getRunnerParameters().setGoals(goals); - myRunner.execute(new ExecutionEnvironmentBuilder(myEnvironment).setContentToReuse(null).setRunProfile(runConfiguration).build()); + myRunner.execute(new ExecutionEnvironmentBuilder(myEnvironment).contentToReuse(null).runProfile(runConfiguration).build()); } catch (RunCanceledByUserException ignore) { } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfigurationType.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfigurationType.java index 3747107fb223..bada6c044354 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfigurationType.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfigurationType.java @@ -59,10 +59,12 @@ public class MavenRunConfigurationType implements ConfigurationType { */ MavenRunConfigurationType() { myFactory = new ConfigurationFactory(this) { + @Override public RunConfiguration createTemplateConfiguration(Project project) { return new MavenRunConfiguration(project, this, ""); } + @Override public RunConfiguration createTemplateConfiguration(Project project, RunManager runManager) { return new MavenRunConfiguration(project, this, ""); } @@ -99,22 +101,27 @@ public class MavenRunConfigurationType implements ConfigurationType { }; } + @Override public String getDisplayName() { return RunnerBundle.message("maven.run.configuration.name"); } + @Override public String getConfigurationTypeDescription() { return RunnerBundle.message("maven.run.configuration.description"); } + @Override public Icon getIcon() { return MavenIcons.Phase; } + @Override public ConfigurationFactory[] getConfigurationFactories() { return new ConfigurationFactory[]{myFactory}; } + @Override @NonNls @NotNull public String getId() { @@ -187,29 +194,26 @@ public class MavenRunConfigurationType implements ConfigurationType { ProgramRunner runner = DefaultJavaProgramRunner.getInstance(); Executor executor = DefaultRunExecutor.getRunExecutorInstance(); - ExecutionEnvironment env = new ExecutionEnvironment(executor, runner, configSettings, project); - try { - runner.execute(env, callback); + runner.execute(new ExecutionEnvironment(executor, runner, configSettings, project), callback); } catch (ExecutionException e) { MavenUtil.showError(project, "Failed to execute Maven goal", e); } } + @NotNull public static RunnerAndConfigurationSettings createRunnerAndConfigurationSettings(@Nullable MavenGeneralSettings generalSettings, - @Nullable MavenRunnerSettings runnerSettings, - MavenRunnerParameters params, - Project project) { + @Nullable MavenRunnerSettings runnerSettings, + MavenRunnerParameters params, + Project project) { MavenRunConfigurationType type = ConfigurationTypeUtil.findConfigurationType(MavenRunConfigurationType.class); - final RunnerAndConfigurationSettings settings = RunManagerEx.getInstanceEx(project) - .createConfiguration(generateName(project, params), type.myFactory); + RunnerAndConfigurationSettings settings = RunManager.getInstance(project).createRunConfiguration(generateName(project, params), type.myFactory); MavenRunConfiguration runConfiguration = (MavenRunConfiguration)settings.getConfiguration(); runConfiguration.setRunnerParameters(params); runConfiguration.setGeneralSettings(generalSettings); runConfiguration.setRunnerSettings(runnerSettings); - return settings; } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenRunConfigurationMenu.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenRunConfigurationMenu.java index 4566689ed55e..7cbccc6b4a7a 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenRunConfigurationMenu.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenRunConfigurationMenu.java @@ -29,9 +29,7 @@ public class MavenRunConfigurationMenu extends DefaultActionGroup implements Dum Executor[] executors = ExecutorRegistry.getInstance().getRegisteredExecutors(); for (int i = executors.length; --i >= 0; ) { final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(executors[i].getId(), settings.getConfiguration()); - AnAction action = new ExecuteMavenRunConfigurationAction(executors[i], runner != null, project, settings); - addAction(action, Constraints.FIRST); } @@ -57,9 +55,9 @@ public class MavenRunConfigurationMenu extends DefaultActionGroup implements Dum @Override public void actionPerformed(AnActionEvent event) { - if (!myEnabled) return; - - ProgramRunnerUtil.executeConfiguration(myProject, mySettings, myExecutor); + if (myEnabled) { + ProgramRunnerUtil.executeConfiguration(myProject, mySettings, myExecutor); + } } @Override diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectImportProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectImportProvider.java index b54da50c1396..f74a98a3476b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectImportProvider.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectImportProvider.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. @@ -43,8 +43,11 @@ public class MavenProjectImportProvider extends ProjectImportProvider { public ModuleWizardStep[] createSteps(final WizardContext wizardContext) { final ProjectWizardStepFactory stepFactory = ProjectWizardStepFactory.getInstance(); - return new ModuleWizardStep[]{new MavenProjectImportStep(wizardContext), new SelectProfilesStep(wizardContext), + return new ModuleWizardStep[]{ + new MavenProjectImportStep(wizardContext), + new SelectProfilesStep(wizardContext), new SelectImportedProjectsStep<MavenProject>(wizardContext) { + @Override protected String getElementText(final MavenProject project) { final StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(project.getMavenId()); @@ -71,15 +74,20 @@ public class MavenProjectImportProvider extends ProjectImportProvider { return !MavenProjectsManager.getInstance(project).isIgnored(mavenProject); } + @Override public void updateDataModel() { super.updateDataModel(); getWizardContext().setProjectName(((MavenProjectBuilder)getBuilder()).getSuggestedProjectName()); } + @Override public String getHelpId() { return "reference.dialogs.new.project.import.maven.page3"; } - }, stepFactory.createProjectJdkStep(wizardContext), stepFactory.createNameAndLocationStep(wizardContext)}; + }, + stepFactory.createProjectJdkStep(wizardContext), + stepFactory.createNameAndLocationStep(wizardContext) + }; } @Override diff --git a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties index 06e0c2e3ae03..61b69161c5e3 100644 --- a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties +++ b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties @@ -50,4 +50,7 @@ new.property.dialog.name.prompt.text=Enter new property key name resource.bundle.renamer=Rename resource bundle properties files resource.bundle.renamer.dialog.description=Rename resource bundle properties files with the following names to: resource.bundle.renamer.entity.name=Resource bundle -resource.bundle.renamer.option=Rename bound &resource bundle
\ No newline at end of file +resource.bundle.renamer.option=Rename bound &resource bundle + +inline.property.refactoring=Inline Property +inline.property.confirmation=Inline property ''{0}'' with value ''{1}''? diff --git a/plugins/properties/properties-psi-impl/properties-psi-impl.iml b/plugins/properties/properties-psi-impl/properties-psi-impl.iml index 76596cc333fe..d297116cb114 100644 --- a/plugins/properties/properties-psi-impl/properties-psi-impl.iml +++ b/plugins/properties/properties-psi-impl/properties-psi-impl.iml @@ -14,8 +14,8 @@ <orderEntry type="module" module-name="xml-psi-api" /> <orderEntry type="module" module-name="xml-psi-impl" /> <orderEntry type="module" module-name="indexing-impl" /> - <orderEntry type="module" module-name="lang-impl" /> <orderEntry type="module" module-name="structure-view-impl" /> + <orderEntry type="module" module-name="analysis-impl" /> </component> </module> diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java index 8f5084b87391..f667b1a93da0 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java @@ -61,7 +61,13 @@ public class PropertiesImplUtil extends PropertiesUtil { @Nullable private static ResourceBundle getResourceBundle(@NotNull final String baseName, @NotNull final PsiDirectory baseDirectory) { PropertiesFile defaultPropertiesFile = null; - for (final PsiFile psiFile : baseDirectory.getFiles()) { + final PsiFile[] files = ApplicationManager.getApplication().runReadAction(new Computable<PsiFile[]>() { + @Override + public PsiFile[] compute() { + return baseDirectory.getFiles(); + } + }); + for (final PsiFile psiFile : files) { if (baseName.equals(getBaseName(psiFile))) { final PropertiesFile propertiesFile = getPropertiesFile(psiFile); if (propertiesFile != null) { diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleEditorViewElement.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleEditorViewElement.java index 58932d1fd4c5..8a8d3b0390d4 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleEditorViewElement.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleEditorViewElement.java @@ -16,9 +16,7 @@ package com.intellij.lang.properties.editor; -import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; /** * @author Dmitry Batkovich diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java index ed660536d052..724a794ca3bb 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java @@ -24,6 +24,7 @@ import com.intellij.lang.properties.IProperty; import com.intellij.lang.properties.PropertiesHighlighter; import com.intellij.lang.properties.PropertiesUtil; import com.intellij.lang.properties.ResourceBundle; +import com.intellij.lang.properties.psi.Property; import com.intellij.navigation.ColoredItemPresentation; import com.intellij.navigation.ItemPresentation; import com.intellij.openapi.editor.colors.EditorColorsManager; @@ -69,8 +70,8 @@ public class ResourceBundlePropertyStructureViewElement implements StructureView } @Override - public String getValue() { - return myProperty.getName(); + public Property getValue() { + return (Property)myProperty.getPsiElement(); } @Override diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/GroupByWordPrefixes.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/GroupByWordPrefixes.java index b67f6bfbea3f..efdbeaf3e863 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/GroupByWordPrefixes.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/GroupByWordPrefixes.java @@ -16,6 +16,7 @@ package com.intellij.lang.properties.structureView; import com.intellij.icons.AllIcons; +import com.intellij.ide.structureView.StructureViewTreeElement; import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.ide.util.treeView.smartTree.*; import com.intellij.lang.properties.IProperty; @@ -65,14 +66,14 @@ public class GroupByWordPrefixes implements Grouper, Sorter { parentPrefixLength = 0; } for (TreeElement element : children) { - String text = null; - if (element instanceof PropertiesStructureViewElement) { - IProperty property = ((PropertiesStructureViewElement)element).getValue(); - text = property.getUnescapedKey(); + if (!(element instanceof StructureViewTreeElement)) { + continue; } - else if (element instanceof ResourceBundlePropertyStructureViewElement) { - text = ((ResourceBundlePropertyStructureViewElement)element).getValue(); + final Object value = ((StructureViewTreeElement)element).getValue(); + if (!(value instanceof IProperty)) { + continue; } + final String text = ((IProperty) value).getUnescapedKey(); if (text == null) continue; LOG.assertTrue(text.startsWith(parentPrefix) || text.startsWith(mySeparator)); List<String> words = StringUtil.split(text, mySeparator); diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesPrefixGroup.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesPrefixGroup.java index 61b3c0202619..c4958502c25a 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesPrefixGroup.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesPrefixGroup.java @@ -16,11 +16,13 @@ package com.intellij.lang.properties.structureView; import com.intellij.icons.AllIcons; +import com.intellij.ide.structureView.StructureViewTreeElement; import com.intellij.ide.util.treeView.smartTree.Group; import com.intellij.ide.util.treeView.smartTree.TreeElement; import com.intellij.lang.properties.IProperty; import com.intellij.lang.properties.editor.ResourceBundleEditorViewElement; import com.intellij.lang.properties.editor.ResourceBundlePropertyStructureViewElement; +import com.intellij.lang.properties.psi.Property; import com.intellij.navigation.ItemPresentation; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; @@ -90,20 +92,14 @@ public class PropertiesPrefixGroup implements Group, ResourceBundleEditorViewEle Collection<TreeElement> result = new ArrayList<TreeElement>(); List<String> prefixWords = StringUtil.split(myPrefix, mySeparator); for (TreeElement treeElement : myProperties) { - String key; - if (treeElement instanceof PropertiesStructureViewElement) { - PropertiesStructureViewElement propertiesElement = (PropertiesStructureViewElement)treeElement; - IProperty property = propertiesElement.getValue(); - - key = property.getUnescapedKey(); - } - else if (treeElement instanceof ResourceBundlePropertyStructureViewElement) { - key = ((ResourceBundlePropertyStructureViewElement)treeElement).getValue(); + if (!(treeElement instanceof StructureViewTreeElement)) { + continue; } - else { + final Object value = ((StructureViewTreeElement)treeElement).getValue(); + if (!(value instanceof IProperty)) { continue; } - + final String key = ((IProperty) value).getUnescapedKey(); if (key == null || key.equals(myPrefix)) { continue; } diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/NewPropertyAction.java b/plugins/properties/src/com/intellij/lang/properties/editor/NewPropertyAction.java index d25b780bd769..2218b7598884 100644 --- a/plugins/properties/src/com/intellij/lang/properties/editor/NewPropertyAction.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/NewPropertyAction.java @@ -60,7 +60,7 @@ class NewPropertyAction extends AnAction { prefix = null; separator = null; } else { - final ResourceBundleEditorViewElement selectedElement = resourceBundleEditor.getSelectedElement(); + final ResourceBundleEditorViewElement selectedElement = resourceBundleEditor.getSelectedElementIfOnlyOne(); if (selectedElement == null) { return; } diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java index 36915e7e6962..36915e7e6962 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java index e9eb9e9f72d2..39e9ed67e7b2 100644 --- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java @@ -57,7 +57,10 @@ import com.intellij.ui.JBColor; import com.intellij.ui.JBSplitter; import com.intellij.ui.components.JBScrollPane; import com.intellij.util.Alarm; +import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.NullableFunction; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.containers.Stack; import com.intellij.util.ui.UIUtil; @@ -129,7 +132,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit @Override public void valueChanged(TreeSelectionEvent e) { // filter out temp unselect/select events - if (getSelectedProperty() == null) return; + if (Comparing.equal(e.getNewLeadSelectionPath(), e.getOldLeadSelectionPath()) || getSelectedProperty() == null) return; if (!arePropertiesEquivalent(selectedProperty, getSelectedProperty()) || !Comparing.equal(selectedPropertiesFile, getSelectedPropertiesFile())) { @@ -167,7 +170,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit TreeElement[] children = myStructureViewComponent.getTreeModel().getRoot().getChildren(); if (children.length != 0) { TreeElement child = children[0]; - String propName = ((ResourceBundlePropertyStructureViewElement)child).getValue(); + String propName = ((ResourceBundlePropertyStructureViewElement)child).getValue().getUnescapedKey(); setState(new ResourceBundleEditorState(propName)); } myDataProviderPanel = new DataProviderPanel(splitPanel); @@ -245,7 +248,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit DefaultMutableTreeNode node = toCheck.pop(); final ResourceBundleEditorViewElement element = getSelectedElement(node); String value = element instanceof ResourceBundlePropertyStructureViewElement - ? ((ResourceBundlePropertyStructureViewElement)element).getValue() + ? ((ResourceBundlePropertyStructureViewElement)element).getValue().getUnescapedKey() : null; if (propertyName.equals(value)) { nodeToSelect = node; @@ -570,13 +573,21 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit document.replaceString(0, document.getTextLength(), text); } - @Nullable - private DefaultMutableTreeNode getSelectedNode() { + @NotNull + private Collection<DefaultMutableTreeNode> getSelectedNodes() { + if (!isValid()) { + return Collections.emptyList(); + } JTree tree = myStructureViewComponent.getTree(); - if (tree == null) return null; - TreePath selected = tree.getSelectionModel().getSelectionPath(); - if (selected == null) return null; - return (DefaultMutableTreeNode)selected.getLastPathComponent(); + if (tree == null) return Collections.emptyList(); + TreePath[] selected = tree.getSelectionModel().getSelectionPaths(); + if (selected == null || selected.length == 0) return Collections.emptyList(); + return ContainerUtil.map(selected, new Function<TreePath, DefaultMutableTreeNode>() { + @Override + public DefaultMutableTreeNode fun(TreePath treePath) { + return (DefaultMutableTreeNode)treePath.getLastPathComponent(); + } + }); } @Nullable @@ -587,25 +598,34 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit @Nullable private IProperty getSelectedProperty() { - final DefaultMutableTreeNode selectedNode = getSelectedNode(); - if (selectedNode == null) { + final Collection<DefaultMutableTreeNode> selectedNode = getSelectedNodes(); + if (selectedNode.isEmpty()) { return null; } - final ResourceBundleEditorViewElement element = getSelectedElement(selectedNode); + final ResourceBundleEditorViewElement element = getSelectedElement(ContainerUtil.getFirstItem(selectedNode)); return element instanceof ResourceBundlePropertyStructureViewElement ? ((ResourceBundlePropertyStructureViewElement)element).getProperty() : null; } + @NotNull + public Collection<ResourceBundleEditorViewElement> getSelectedElements() { + final Collection<DefaultMutableTreeNode> selectedNodes = getSelectedNodes(); + return ContainerUtil.mapNotNull(selectedNodes, new NullableFunction<DefaultMutableTreeNode, ResourceBundleEditorViewElement>() { + @Nullable + @Override + public ResourceBundleEditorViewElement fun(DefaultMutableTreeNode selectedNode) { + Object userObject = selectedNode.getUserObject(); + if (!(userObject instanceof AbstractTreeNode)) return null; + Object value = ((AbstractTreeNode)userObject).getValue(); + return value instanceof ResourceBundleEditorViewElement ? (ResourceBundleEditorViewElement) value : null; + } + }); + } + @Nullable - public ResourceBundleEditorViewElement getSelectedElement() { - final DefaultMutableTreeNode selectedNode = getSelectedNode(); - if (selectedNode == null) { - return null; - } - Object userObject = selectedNode.getUserObject(); - if (!(userObject instanceof AbstractTreeNode)) return null; - Object value = ((AbstractTreeNode)userObject).getValue(); - return value instanceof ResourceBundleEditorViewElement ? (ResourceBundleEditorViewElement) value : null; + public ResourceBundleEditorViewElement getSelectedElementIfOnlyOne() { + final Collection<ResourceBundleEditorViewElement> selectedElements = getSelectedElements(); + return selectedElements.size() == 1 ? ContainerUtil.getFirstItem(selectedElements) : null; } @Override diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleStructureViewComponent.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleStructureViewComponent.java index 0985f35a5e12..da376abe05b2 100644 --- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleStructureViewComponent.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleStructureViewComponent.java @@ -25,7 +25,6 @@ import com.intellij.lang.properties.psi.Property; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.ide.CopyPasteManager; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNamedElement; @@ -34,10 +33,13 @@ import com.intellij.refactoring.safeDelete.SafeDeleteHandler; import com.intellij.ui.PopupHandler; import com.intellij.usages.UsageTarget; import com.intellij.usages.UsageView; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.awt.datatransfer.StringSelection; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -74,9 +76,17 @@ class ResourceBundleStructureViewComponent extends PropertiesGroupingStructureVi } else if (PlatformDataKeys.FILE_EDITOR.is(dataId)) { return getFileEditor(); } else if (LangDataKeys.PSI_ELEMENT_ARRAY.is(dataId)) { - final ResourceBundleEditorViewElement selectedElement = ((ResourceBundleEditor)getFileEditor()).getSelectedElement(); - if (selectedElement != null) { - return selectedElement.getPsiElements(); + final Collection<ResourceBundleEditorViewElement> selectedElements = ((ResourceBundleEditor)getFileEditor()).getSelectedElements(); + if (selectedElements.isEmpty()) { + return null; + } else if (selectedElements.size() == 1) { + return ContainerUtil.getFirstItem(selectedElements).getPsiElements(); + } else { + final List<PsiElement> psiElements = new ArrayList<PsiElement>(); + for (ResourceBundleEditorViewElement selectedElement : selectedElements) { + Collections.addAll(psiElements, selectedElement.getPsiElements()); + } + return psiElements.toArray(new PsiElement[psiElements.size()]); } } else if (PlatformDataKeys.DELETE_ELEMENT_PROVIDER.is(dataId)) { final PsiElement[] psiElements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(this); diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java index e4a35e7e677c..e4a35e7e677c 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java diff --git a/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java b/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java index 0c04bec80620..e105195cb9b3 100644 --- a/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java +++ b/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java @@ -74,7 +74,7 @@ public class ResourceBundleFromEditorRenameHandler implements RenameHandler { public void invoke(final @NotNull Project project, Editor editor, final PsiFile file, DataContext dataContext) { final ResourceBundleEditor resourceBundleEditor = (ResourceBundleEditor)PlatformDataKeys.FILE_EDITOR.getData(dataContext); assert resourceBundleEditor != null; - final ResourceBundleEditorViewElement selectedElement = resourceBundleEditor.getSelectedElement(); + final ResourceBundleEditorViewElement selectedElement = resourceBundleEditor.getSelectedElementIfOnlyOne(); if (selectedElement != null) { CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { @Override diff --git a/plugins/svn4idea/src/META-INF/plugin.xml b/plugins/svn4idea/src/META-INF/plugin.xml index e831d0550a80..5a441dc89565 100644 --- a/plugins/svn4idea/src/META-INF/plugin.xml +++ b/plugins/svn4idea/src/META-INF/plugin.xml @@ -76,7 +76,7 @@ <reference id="Vcs.ShowTabbedFileHistory"/> <reference id="Vcs.ShowHistoryForBlock"/> <reference id="Annotate"/> - <action id="Subversion.Copy" class="org.jetbrains.idea.svn.actions.CreateBranchOrTagAction"/> + <action id="Subversion.Copy" class="org.jetbrains.idea.svn.branchConfig.CreateBranchOrTagAction"/> <separator/> <action id="Subversion.Lock" class="org.jetbrains.idea.svn.actions.LockAction"/> <action id="Subversion.Unlock" class="org.jetbrains.idea.svn.actions.UnlockAction"/> @@ -122,16 +122,16 @@ <applicationService serviceInterface="org.jetbrains.idea.svn.SvnApplicationSettings" serviceImplementation="org.jetbrains.idea.svn.SvnApplicationSettings"/> <projectService serviceImplementation="org.jetbrains.idea.svn.SvnConfiguration"/> - <projectService serviceInterface="org.jetbrains.idea.svn.SvnBranchConfigurationManager" - serviceImplementation="org.jetbrains.idea.svn.SvnBranchConfigurationManager"/> + <projectService serviceInterface="org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager" + serviceImplementation="org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager"/> <projectService serviceInterface="org.jetbrains.idea.svn.history.LoadedRevisionsCache" serviceImplementation="org.jetbrains.idea.svn.history.LoadedRevisionsCache"/> <projectService serviceInterface="org.jetbrains.idea.svn.mergeinfo.SvnMergeInfoCache" serviceImplementation="org.jetbrains.idea.svn.mergeinfo.SvnMergeInfoCache"/> - <projectService serviceInterface="org.jetbrains.idea.svn.SvnLoadedBrachesStorage" - serviceImplementation="org.jetbrains.idea.svn.SvnLoadedBrachesStorage"/> - <applicationService serviceInterface="org.jetbrains.idea.svn.SvnBranchMapperManager" - serviceImplementation="org.jetbrains.idea.svn.SvnBranchMapperManager"/> + <projectService serviceInterface="org.jetbrains.idea.svn.branchConfig.SvnLoadedBranchesStorage" + serviceImplementation="org.jetbrains.idea.svn.branchConfig.SvnLoadedBranchesStorage"/> + <applicationService serviceInterface="org.jetbrains.idea.svn.branchConfig.SvnBranchMapperManager" + serviceImplementation="org.jetbrains.idea.svn.branchConfig.SvnBranchMapperManager"/> <applicationService serviceInterface="org.jetbrains.idea.svn.dialogs.browserCache.SvnRepositoryCache" serviceImplementation="org.jetbrains.idea.svn.dialogs.browserCache.SvnRepositoryCache"/> <applicationService serviceInterface="org.jetbrains.idea.svn.dialogs.browserCache.Loader" diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java index 06138b345b74..c33dd38f2eba 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java @@ -105,7 +105,7 @@ public class RootsToWorkingCopies implements VcsListener { @CalledInBackground @Nullable - public WorkingCopy getWcRoot(final VirtualFile root) { + public WorkingCopy getWcRoot(@NotNull VirtualFile root) { assert (! ApplicationManager.getApplication().isDispatchThread()) || ApplicationManager.getApplication().isUnitTestMode(); synchronized (myLock) { @@ -117,7 +117,7 @@ public class RootsToWorkingCopies implements VcsListener { } @Nullable - private WorkingCopy calculateRoot(final VirtualFile root) { + private WorkingCopy calculateRoot(@NotNull VirtualFile root) { File workingCopyRoot = SvnUtil.getWorkingCopyRootNew(new File(root.getPath())); WorkingCopy workingCopy = null; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties index df545b0373a1..3f4ae40677ae 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties @@ -526,6 +526,7 @@ action.Subversion.integrate.changes.alien.commit.changelist.title=Integrated action.Subversion.integrate.changes.dialog.add.wc.text=Add action.Subversion.integrate.changes.dialog.remove.wc.text=Remove action.Subversion.integrate.changes.message.files.up.to.date.text=All files are up to date +action.Subversion.integrate.changes.collecting.changes.to.commit.task.title=Collecting changes to commit action.Subversion.integrate.changes.error.unable.to.collect.changes.text=Error while collecting changes to commit: {0} error.cannot.load.revisions=Can not load revision list action.Subversion.integrate.changes.message.canceled.text=Integration was canceled diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java index 9ae90c722cb3..1fc5f9ce075a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java @@ -27,6 +27,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.actions.AbstractShowPropertiesDiffAction; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager; import org.jetbrains.idea.svn.info.Info; import org.jetbrains.idea.svn.lock.Lock; import org.jetbrains.idea.svn.status.Status; @@ -244,7 +245,13 @@ class SvnChangeProviderContext implements StatusReceiver { myChangelistBuilder.processLocallyDeletedFile(createLocallyDeletedChange(filePath, status)); } else if (status.is(StatusType.STATUS_IGNORED)) { - if (!myVcs.isWcRoot(filePath)) { + if (filePath.getVirtualFile() == null) { + filePath.hardRefresh(); + } + if (filePath.getVirtualFile() == null) { + LOG.error("No virtual file for ignored file: " + filePath.getPresentableUrl() + ", isNonLocal: " + filePath.isNonLocal()); + } + else if (!myVcs.isWcRoot(filePath)) { myChangelistBuilder.processIgnoredFile(filePath.getVirtualFile()); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java index 6f5013c4a929..9d8df6591268 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java @@ -30,6 +30,7 @@ import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.auth.SvnAuthenticationManager; import org.jetbrains.idea.svn.auth.SvnAuthenticationProvider; import org.jetbrains.idea.svn.auth.SvnInteractiveAuthenticationProvider; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager; import org.jetbrains.idea.svn.config.SvnServerFileKeys; import org.jetbrains.idea.svn.diff.DiffOptions; import org.jetbrains.idea.svn.update.MergeRootInfo; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java index 11838314acbd..5c660643dc66 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java @@ -221,11 +221,16 @@ public class SvnFileUrlMappingImpl implements SvnFileUrlMapping, PersistentState } public void realRefresh(final Runnable afterRefreshCallback) { - final SvnVcs vcs = SvnVcs.getInstance(myProject); - final VirtualFile[] roots = myHelper.executeDefended(myProject); - final SvnRootsDetector rootsDetector = new SvnRootsDetector(vcs, this, myNestedCopiesHolder); - // do not send additional request for nested copies when in init state - rootsDetector.detectCopyRoots(roots, init(), afterRefreshCallback); + if (myProject.isDisposed()) { + afterRefreshCallback.run(); + } + else { + final SvnVcs vcs = SvnVcs.getInstance(myProject); + final VirtualFile[] roots = myHelper.executeDefended(myProject); + final SvnRootsDetector rootsDetector = new SvnRootsDetector(vcs, this, myNestedCopiesHolder); + // do not send additional request for nested copies when in init state + rootsDetector.detectCopyRoots(roots, init(), afterRefreshCallback); + } } public void applyDetectionResult(@NotNull SvnRootsDetector.Result result) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnScopeZipper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnScopeZipper.java index a5612a69172a..d4c98221a567 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnScopeZipper.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnScopeZipper.java @@ -19,22 +19,25 @@ import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.FilePathImpl; import com.intellij.openapi.vcs.changes.VcsDirtyScope; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; public class SvnScopeZipper implements Runnable { - private final VcsDirtyScope myIn; - private final List<FilePath> myRecursiveDirs; + + @NotNull private final VcsDirtyScope myIn; + @NotNull private final List<FilePath> myRecursiveDirs; // instead of set and heavy equals of file path - private final Map<String, MyDirNonRecursive> myNonRecursiveDirs; - // those alone in their immediate parent - private final List<FilePath> mySingleFiles; + @NotNull private final Map<String, MyDirNonRecursive> myNonRecursiveDirs; - public SvnScopeZipper(final VcsDirtyScope in) { + public SvnScopeZipper(@NotNull VcsDirtyScope in) { myIn = in; - myRecursiveDirs = new ArrayList<FilePath>(in.getRecursivelyDirtyDirectories()); - myNonRecursiveDirs = new HashMap<String, MyDirNonRecursive>(); - mySingleFiles = new ArrayList<FilePath>(); + myRecursiveDirs = ContainerUtil.newArrayList(in.getRecursivelyDirtyDirectories()); + myNonRecursiveDirs = ContainerUtil.newHashMap(); } public void run() { @@ -46,85 +49,72 @@ public class SvnScopeZipper implements Runnable { final VirtualFile vFile = file.getVirtualFile(); // todo take care about this 'not valid' - right now keeping things as they used to be final MyDirNonRecursive me = createOrGet(file); - me.setInterestedInParent(true); if (vFile != null && vFile.isValid()) { for (VirtualFile child : vFile.getChildren()) { me.add(new FilePathImpl(child)); } } } - final FilePath parent = file.getParentPath(); - if (parent != null) { - final MyDirNonRecursive item = createOrGet(parent); - item.add(file); + else { + final FilePath parent = file.getParentPath(); + if (parent != null) { + final MyDirNonRecursive item = createOrGet(parent); + item.add(file); + } } } - - // move alone files into a separate list - /*for (Iterator<Map.Entry<String, MyDirNonRecursive>> iterator = myNonRecursiveDirs.entrySet().iterator(); iterator.hasNext();) { - final Map.Entry<String, MyDirNonRecursive> entry = iterator.next(); - final MyDirNonRecursive item = entry.getValue(); - if ((! item.isInterestedInParent()) && (item.getChildrenList().size() == 1)) { - iterator.remove(); - mySingleFiles.add(item.getChildrenList().iterator().next()); - } - }*/ } - private MyDirNonRecursive createOrGet(final FilePath parent) { - final String key = getKey(parent); - final MyDirNonRecursive result = myNonRecursiveDirs.get(key); - if (result != null) return result; - final MyDirNonRecursive newItem = new MyDirNonRecursive(parent); - myNonRecursiveDirs.put(key, newItem); - return newItem; + @NotNull + private MyDirNonRecursive createOrGet(@NotNull FilePath parent) { + String key = getKey(parent); + MyDirNonRecursive result = myNonRecursiveDirs.get(key); + + if (result == null) { + result = new MyDirNonRecursive(parent); + myNonRecursiveDirs.put(key, result); + } + + return result; } + @NotNull public List<FilePath> getRecursiveDirs() { return myRecursiveDirs; } + @NotNull public Map<String, MyDirNonRecursive> getNonRecursiveDirs() { return myNonRecursiveDirs; } - public List<FilePath> getSingleFiles() { - return mySingleFiles; + public static String getKey(@NotNull FilePath path) { + return path.getPresentableUrl(); } static class MyDirNonRecursive { - private boolean myInterestedInParent; - private final FilePath myDir; + + @NotNull private final FilePath myDir; // instead of set and heavy equals of file path - private final Map<String, FilePath> myChildren; + @NotNull private final Map<String, FilePath> myChildren; - private MyDirNonRecursive(final FilePath dir) { + private MyDirNonRecursive(@NotNull FilePath dir) { myDir = dir; - myChildren = new HashMap<String, FilePath>(); - } - - public boolean isInterestedInParent() { - return myInterestedInParent; - } - - public void setInterestedInParent(boolean interestedInParent) { - myInterestedInParent = interestedInParent; + myChildren = ContainerUtil.newHashMap(); } - public void add(final FilePath path) { + public void add(@NotNull FilePath path) { myChildren.put(getKey(path), path); } + @NotNull public Collection<FilePath> getChildrenList() { return myChildren.values(); } + @NotNull public FilePath getDir() { return myDir; } } - - public static String getKey(final FilePath path) { - return path.getPresentableUrl(); - } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java index 43407f4b2064..aaf46003c1dd 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java @@ -49,6 +49,7 @@ import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.api.EventAction; import org.jetbrains.idea.svn.api.ProgressEvent; import org.jetbrains.idea.svn.api.ProgressTracker; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.browse.DirectoryEntry; import org.jetbrains.idea.svn.browse.DirectoryEntryConsumer; @@ -58,11 +59,15 @@ import org.jetbrains.idea.svn.info.Info; import org.jetbrains.idea.svn.status.Status; import org.tmatesoft.sqljet.core.SqlJetException; import org.tmatesoft.sqljet.core.table.SqlJetDb; -import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.SVNErrorCode; +import org.tmatesoft.svn.core.SVNErrorMessage; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import org.tmatesoft.svn.core.internal.wc.SVNFileUtil; import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration; -import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc.SVNWCUtil; import org.tmatesoft.svn.core.wc2.SvnOperationFactory; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -343,7 +348,7 @@ public class SvnUtil { for (T committable : committables) { final RootUrlInfo path = vcs.getSvnFileUrlMapping().getWcRootForFilePath(convertor.convert(committable)); if (path == null) { - result.putValue(new Pair<SVNURL, WorkingCopyFormat>(null, null), committable); + result.putValue(Pair.create((SVNURL)null, WorkingCopyFormat.UNKNOWN), committable); } else { result.putValue(Pair.create(path.getRepositoryUrlUrl(), path.getFormat()), committable); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index b44fd16f979f..e5018f3319d5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -68,6 +68,7 @@ import org.jetbrains.idea.svn.api.CmdClientFactory; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.api.SvnKitClientFactory; import org.jetbrains.idea.svn.auth.SvnAuthenticationNotifier; +import org.jetbrains.idea.svn.branchConfig.SvnLoadedBranchesStorage; import org.jetbrains.idea.svn.checkin.SvnCheckinEnvironment; import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider; import org.jetbrains.idea.svn.commandLine.SvnBindException; @@ -81,7 +82,6 @@ import org.jetbrains.idea.svn.history.SvnHistoryProvider; import org.jetbrains.idea.svn.info.Info; import org.jetbrains.idea.svn.info.InfoConsumer; import org.jetbrains.idea.svn.properties.PropertyClient; -import org.jetbrains.idea.svn.properties.PropertyData; import org.jetbrains.idea.svn.properties.PropertyValue; import org.jetbrains.idea.svn.rollback.SvnRollbackEnvironment; import org.jetbrains.idea.svn.status.Status; @@ -89,7 +89,10 @@ import org.jetbrains.idea.svn.status.StatusType; import org.jetbrains.idea.svn.svnkit.SvnKitManager; import org.jetbrains.idea.svn.update.SvnIntegrateEnvironment; import org.jetbrains.idea.svn.update.SvnUpdateEnvironment; -import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.SVNErrorCode; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNNodeKind; +import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.wc.SVNAdminUtil; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -145,7 +148,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> { private final RootsToWorkingCopies myRootsToWorkingCopies; private final SvnAuthenticationNotifier myAuthNotifier; - private final SvnLoadedBrachesStorage myLoadedBranchesStorage; + private final SvnLoadedBranchesStorage myLoadedBranchesStorage; private final SvnExecutableChecker myChecker; @@ -157,7 +160,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> { private final boolean myLogExceptions; - public SvnVcs(final Project project, MessageBus bus, SvnConfiguration svnConfiguration, final SvnLoadedBrachesStorage storage) { + public SvnVcs(final Project project, MessageBus bus, SvnConfiguration svnConfiguration, final SvnLoadedBranchesStorage storage) { super(project, VCS_NAME); myLoadedBranchesStorage = storage; @@ -723,9 +726,10 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> { return WorkingCopyFormat.UNKNOWN.equals(format) ? SvnFormatSelector.findRootAndGetFormat(ioFile) : format; } - public boolean isWcRoot(FilePath filePath) { + public boolean isWcRoot(@NotNull FilePath filePath) { boolean isWcRoot = false; - WorkingCopy wcRoot = myRootsToWorkingCopies.getWcRoot(filePath.getVirtualFile()); + VirtualFile file = filePath.getVirtualFile(); + WorkingCopy wcRoot = file != null ? myRootsToWorkingCopies.getWcRoot(file) : null; if (wcRoot != null) { isWcRoot = wcRoot.getFile().getAbsolutePath().equals(filePath.getIOFile().getAbsolutePath()); } @@ -917,7 +921,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> { } @Override - public boolean isVcsBackgroundOperationsAllowed(VirtualFile root) { + public boolean isVcsBackgroundOperationsAllowed(@NotNull VirtualFile root) { // TODO: Currently myAuthNotifier.isAuthenticatedFor directly uses SVNKit to check credentials - so assume for now that background // TODO: operations are always allowed for command line. As sometimes this leads to errors - for instance, incoming changes are not // TODO: displayed in "Incoming" tab - incoming changes are collected using command line but not displayed because diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractIntegrateChangesAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractIntegrateChangesAction.java index ff0f158f32a8..468399e93679 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractIntegrateChangesAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractIntegrateChangesAction.java @@ -24,6 +24,7 @@ import com.intellij.openapi.vcs.changes.committed.CommittedChangesBrowserUseCase import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnBundle; +import org.jetbrains.idea.svn.branchConfig.SelectBranchPopup; import org.jetbrains.idea.svn.integrate.MergerFactory; import org.jetbrains.idea.svn.integrate.SelectedCommittedStuffChecker; import org.jetbrains.idea.svn.integrate.SvnIntegrateChangesActionPerformer; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java index ddd9bd572f0e..ee4f807c2570 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java @@ -26,6 +26,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcsUtil.VcsRunnable; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnPropertyKeys; import org.jetbrains.idea.svn.SvnRevisionNumber; import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.SvnVcs; @@ -33,7 +34,6 @@ import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.info.Info; import org.jetbrains.idea.svn.properties.PropertyClient; import org.jetbrains.idea.svn.properties.PropertyValue; -import org.tmatesoft.svn.core.SVNProperty; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -162,8 +162,8 @@ public class SvnMergeProvider implements MergeProvider { File ioFile = new File(file.getPath()); PropertyClient client = vcs.getFactory(ioFile).createPropertyClient(); - PropertyValue value = client.getProperty(SvnTarget.fromFile(ioFile), SVNProperty.MIME_TYPE, false, SVNRevision.WORKING); - if (value != null && SVNProperty.isBinaryMimeType(value.toString())) { + PropertyValue value = client.getProperty(SvnTarget.fromFile(ioFile), SvnPropertyKeys.SVN_MIME_TYPE, false, SVNRevision.WORKING); + if (value != null && isBinaryMimeType(value.toString())) { return true; } } @@ -173,4 +173,8 @@ public class SvnMergeProvider implements MergeProvider { return false; } + + private static boolean isBinaryMimeType(@NotNull String mimeType) { + return !mimeType.startsWith("text/"); + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java index a615fd4e3afa..e40569d720de 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java @@ -70,7 +70,7 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn if (! svnRevision.isValid()) { throw new VcsException("Can not get last changed revision for file: " + file.getPath() + "\nPlease run svn info for this file and file an issue."); } - return annotate(file, new SvnFileRevision(myVcs, currentRevision, currentRevision, null, null, null, null, null, file.getCharset()), + return annotate(file, new SvnFileRevision(myVcs, currentRevision, currentRevision, null, null, null, null, null), lastChangedRevision.getRevisionNumber(), true); } @@ -438,7 +438,7 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn myProgress.checkCanceled(); myProgress.setText2(SvnBundle.message("progress.text2.revision.processed", logEntry.getRevision())); } - myResult.setRevision(logEntry.getRevision(), new SvnFileRevision(myVcs, SVNRevision.UNDEFINED, logEntry, myUrl, "", myCharset)); + myResult.setRevision(logEntry.getRevision(), new SvnFileRevision(myVcs, SVNRevision.UNDEFINED, logEntry, myUrl, "")); } }); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java index 57c835daef2f..ffc21a011334 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java @@ -223,7 +223,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica /** * Bases on presence of notifications! */ - public ThreeState isAuthenticatedFor(final VirtualFile vf) { + public ThreeState isAuthenticatedFor(@NotNull VirtualFile vf) { final WorkingCopy wcCopy = myRootsToWorkingCopies.getWcRoot(vf); if (wcCopy == null) return ThreeState.UNSURE; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.form b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.form index a416aa145505..b68010c827db 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.form +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.form @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.idea.svn.dialogs.BranchConfigurationDialog"> +<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.idea.svn.branchConfig.BranchConfigurationDialog"> <grid id="27dc6" binding="myTopPanel" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="0" left="0" bottom="0" right="0"/> <constraints> diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java index 50ddd9615d41..0e0fce947088 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.idea.svn.dialogs; +package org.jetbrains.idea.svn.branchConfig; import com.intellij.openapi.actionSystem.ActionToolbarPosition; import com.intellij.openapi.project.Project; @@ -32,12 +32,8 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; -import org.jetbrains.idea.svn.branchConfig.InfoReliability; -import org.jetbrains.idea.svn.branchConfig.InfoStorage; -import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigManager; -import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.commandLine.SvnBindException; -import org.jetbrains.idea.svn.integrate.SvnBranchItem; +import org.jetbrains.idea.svn.dialogs.SelectLocationDialog; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.util.SVNURLUtil; @@ -59,7 +55,7 @@ public class BranchConfigurationDialog extends DialogWrapper { private JList myLocationList; private JPanel myListPanel; private JLabel myErrorPrompt; - private final SvnBranchConfigManager mySvnBranchConfigManager; + private final NewRootBunch mySvnBranchConfigManager; private final VirtualFile myRoot; public BranchConfigurationDialog(@NotNull final Project project, @@ -115,7 +111,7 @@ public class BranchConfigurationDialog extends DialogWrapper { if (!configuration.getBranchUrls().contains(selectedUrl)) { configuration .addBranches(selectedUrl, new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(), InfoReliability.empty)); - mySvnBranchConfigManager.reloadBranches(myRoot, selectedUrl, null); + mySvnBranchConfigManager.reloadBranchesAsync(myRoot, selectedUrl, InfoReliability.setByUser); listModel.fireItemAdded(); myLocationList.setSelectedIndex(listModel.getSize() - 1); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java index 10f4574c7f39..ba0288da9699 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.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. @@ -16,14 +16,16 @@ package org.jetbrains.idea.svn.branchConfig; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; +import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.browse.DirectoryEntry; import org.jetbrains.idea.svn.browse.DirectoryEntryConsumer; -import org.jetbrains.idea.svn.integrate.SvnBranchItem; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.wc.SVNLogClient; import org.tmatesoft.svn.core.wc.SVNRevision; @@ -33,27 +35,60 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; -public class BranchesLoader { +/** + * @author Konstantin Kolosovsky. + */ +public class BranchesLoader implements Runnable { + @NotNull private final Project myProject; + @NotNull private final NewRootBunch myBunch; + @NotNull private final VirtualFile myRoot; + @NotNull private final String myUrl; + @NotNull private final InfoReliability myInfoReliability; + private final boolean myPassive; + + public BranchesLoader(@NotNull Project project, + @NotNull NewRootBunch bunch, + @NotNull String url, + @NotNull InfoReliability infoReliability, + @NotNull VirtualFile root, + boolean passive) { + myProject = project; + myBunch = bunch; + myUrl = url; + myInfoReliability = infoReliability; + myRoot = root; + myPassive = passive; + } - private BranchesLoader() { + public void run() { + try { + List<SvnBranchItem> branches = loadBranches(); + myBunch.updateBranches(myRoot, myUrl, new InfoStorage<List<SvnBranchItem>>(branches, myInfoReliability)); + } + catch (VcsException e) { + showError(e); + } + catch (SVNException e) { + showError(e); + } } - public static List<SvnBranchItem> loadBranches(final Project project, final String url, boolean passive) throws SVNException, - VcsException { - final SvnConfiguration configuration = SvnConfiguration.getInstance(project); - final SvnVcs vcs = SvnVcs.getInstance(project); - SVNURL branchesUrl = SVNURL.parseURIEncoded(url); + @NotNull + public List<SvnBranchItem> loadBranches() throws SVNException, VcsException { + final SvnConfiguration configuration = SvnConfiguration.getInstance(myProject); + final SvnVcs vcs = SvnVcs.getInstance(myProject); + SVNURL branchesUrl = SVNURL.parseURIEncoded(myUrl); List<SvnBranchItem> result = new LinkedList<SvnBranchItem>(); SvnTarget target = SvnTarget.fromURL(branchesUrl); - if (!passive) { + if (!myPassive) { // TODO: Implement ability to specify interactive/non-interactive auth mode for clients DirectoryEntryConsumer handler = createConsumer(branchesUrl, result); vcs.getFactory(target).createBrowseClient().list(target, SVNRevision.HEAD, Depth.IMMEDIATES, handler); } else { ISVNDirEntryHandler handler = createHandler(branchesUrl, result); - SVNLogClient client = vcs.getSvnKitManager().createLogClient(configuration.getPassiveAuthenticationManager(project)); + SVNLogClient client = vcs.getSvnKitManager().createLogClient(configuration.getPassiveAuthenticationManager(myProject)); client .doList(target.getURL(), target.getPegRevision(), SVNRevision.HEAD, false, SVNDepth.IMMEDIATES, SVNDirEntry.DIRENT_ALL, handler); } @@ -62,6 +97,13 @@ public class BranchesLoader { return result; } + private void showError(Exception e) { + // already logged inside + if (InfoReliability.setByUser.equals(myInfoReliability)) { + VcsBalloonProblemNotifier.showOverChangesView(myProject, "Branches load error: " + e.getMessage(), MessageType.ERROR); + } + } + @NotNull private static ISVNDirEntryHandler createHandler(@NotNull final SVNURL branchesUrl, @NotNull final List<SvnBranchItem> result) { return new ISVNDirEntryHandler() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ConfigureBranchesAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/ConfigureBranchesAction.java index 1993a1caa0fe..3615c4b4792d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ConfigureBranchesAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/ConfigureBranchesAction.java @@ -13,12 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.actions; +package org.jetbrains.idea.svn.branchConfig; 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.project.DumbAware; import com.intellij.openapi.project.Project; @@ -28,7 +27,6 @@ import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; import icons.SvnIcons; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnVcs; -import org.jetbrains.idea.svn.dialogs.BranchConfigurationDialog; import org.jetbrains.idea.svn.history.SvnChangeList; public class ConfigureBranchesAction extends AnAction implements DumbAware { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagAction.java index c6f633416a15..da1557922a44 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagAction.java @@ -15,7 +15,7 @@ */ -package org.jetbrains.idea.svn.actions; +package org.jetbrains.idea.svn.branchConfig; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.Application; @@ -35,10 +35,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnStatusUtil; import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.actions.BasicAction; import org.jetbrains.idea.svn.checkin.CommitEventHandler; import org.jetbrains.idea.svn.checkin.IdeaCommitHandler; import org.jetbrains.idea.svn.commandLine.SvnBindException; -import org.jetbrains.idea.svn.dialogs.CreateBranchOrTagDialog; import org.jetbrains.idea.svn.update.AutoSvnUpdater; import org.jetbrains.idea.svn.update.SingleRootSwitcher; import org.tmatesoft.svn.core.SVNErrorCode; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CreateBranchOrTagDialog.form b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagDialog.form index 6dfcae6c9f6f..96eaeaaf2c4c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CreateBranchOrTagDialog.form +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagDialog.form @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.idea.svn.dialogs.CreateBranchOrTagDialog"> +<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.idea.svn.branchConfig.CreateBranchOrTagDialog"> <grid id="9287c" binding="myTopPanel" layout-manager="GridBagLayout"> <constraints> <xy x="10" y="10" width="561" height="502"/> diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CreateBranchOrTagDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagDialog.java index a09de54fdbc4..95ae986dd72d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CreateBranchOrTagDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagDialog.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.dialogs; +package org.jetbrains.idea.svn.branchConfig; import com.intellij.icons.AllIcons; import com.intellij.openapi.diagnostic.Logger; @@ -33,10 +33,9 @@ import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.RootUrlInfo; -import org.jetbrains.idea.svn.SvnBranchConfigurationManager; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnVcs; -import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; +import org.jetbrains.idea.svn.dialogs.SelectLocationDialog; import org.jetbrains.idea.svn.info.Info; import org.jetbrains.idea.svn.update.SvnRevisionPanel; import org.tmatesoft.svn.core.internal.util.SVNEncodingUtil; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultBranchConfigInitializer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultBranchConfigInitializer.java new file mode 100644 index 000000000000..37b78459448c --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultBranchConfigInitializer.java @@ -0,0 +1,155 @@ +/* + * 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 org.jetbrains.idea.svn.branchConfig; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.SvnUtil; +import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.api.Depth; +import org.jetbrains.idea.svn.browse.DirectoryEntry; +import org.jetbrains.idea.svn.browse.DirectoryEntryConsumer; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.internal.util.SVNPathUtil; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc2.SvnTarget; + +import java.util.ArrayList; +import java.util.List; + +/** +* @author Konstantin Kolosovsky. +*/ +public class DefaultBranchConfigInitializer implements Runnable { + + private static final Logger LOG = Logger.getInstance(DefaultBranchConfigInitializer.class); + + @NonNls private static final String DEFAULT_TRUNK_NAME = "trunk"; + @NonNls private static final String DEFAULT_BRANCHES_NAME = "branches"; + @NonNls private static final String DEFAULT_TAGS_NAME = "tags"; + + @NotNull private final Project myProject; + @NotNull private final NewRootBunch myBunch; + @NotNull private final VirtualFile myRoot; + + public DefaultBranchConfigInitializer(@NotNull Project project, @NotNull NewRootBunch bunch, @NotNull VirtualFile root) { + myProject = project; + myRoot = root; + myBunch = bunch; + } + + public void run() { + SvnBranchConfigurationNew configuration = getDefaultConfiguration(); + + if (configuration != null) { + for (String url : configuration.getBranchUrls()) { + myBunch.reloadBranchesAsync(myRoot, url, InfoReliability.defaultValues); + } + + myBunch.updateForRoot(myRoot, new InfoStorage<SvnBranchConfigurationNew>(configuration, InfoReliability.defaultValues), false); + } + } + + @Nullable + public SvnBranchConfigurationNew getDefaultConfiguration() { + SvnBranchConfigurationNew result = null; + SvnVcs vcs = SvnVcs.getInstance(myProject); + SVNURL rootUrl = SvnUtil.getUrl(vcs, VfsUtilCore.virtualToIoFile(myRoot)); + + if (rootUrl != null) { + try { + result = getDefaultConfiguration(vcs, rootUrl); + } + catch (SVNException e) { + LOG.info(e); + } + catch (VcsException e) { + LOG.info(e); + } + } + else { + LOG.info("Directory is not a working copy: " + myRoot.getPresentableUrl()); + } + + return result; + } + + @NotNull + private static SvnBranchConfigurationNew getDefaultConfiguration(@NotNull SvnVcs vcs, @NotNull SVNURL url) + throws SVNException, VcsException { + SvnBranchConfigurationNew result = new SvnBranchConfigurationNew(); + result.setTrunkUrl(url.toString()); + + SVNURL branchLocationsParent = getBranchLocationsParent(url); + if (branchLocationsParent != null) { + SvnTarget target = SvnTarget.fromURL(branchLocationsParent); + + vcs.getFactory(target).createBrowseClient().list(target, SVNRevision.HEAD, Depth.IMMEDIATES, createHandler(result, target.getURL())); + } + + return result; + } + + @Nullable + private static SVNURL getBranchLocationsParent(@NotNull SVNURL url) throws SVNException { + while (!hasEmptyName(url) && !hasDefaultName(url)) { + url = url.removePathTail(); + } + + return hasDefaultName(url) ? url.removePathTail() : null; + } + + private static boolean hasEmptyName(@NotNull SVNURL url) { + return StringUtil.isEmpty(SVNPathUtil.tail(url.getPath())); + } + + private static boolean hasDefaultName(@NotNull SVNURL url) { + String name = SVNPathUtil.tail(url.getPath()); + + return name.equalsIgnoreCase(DEFAULT_TRUNK_NAME) || + name.equalsIgnoreCase(DEFAULT_BRANCHES_NAME) || + name.equalsIgnoreCase(DEFAULT_TAGS_NAME); + } + + @NotNull + private static DirectoryEntryConsumer createHandler(@NotNull final SvnBranchConfigurationNew result, @NotNull final SVNURL rootPath) { + return new DirectoryEntryConsumer() { + + @Override + public void consume(final DirectoryEntry entry) throws SVNException { + if (entry.isDirectory()) { + SVNURL childUrl = rootPath.appendPath(entry.getName(), false); + + if (StringUtil.endsWithIgnoreCase(entry.getName(), DEFAULT_TRUNK_NAME)) { + result.setTrunkUrl(childUrl.toString()); + } + else { + result.addBranches(childUrl.toString(), + new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(0), InfoReliability.defaultValues)); + } + } + } + }; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java deleted file mode 100644 index d52798e6bfc3..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.svn.branchConfig; - -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.SvnVcs; -import org.jetbrains.idea.svn.api.Depth; -import org.jetbrains.idea.svn.browse.DirectoryEntry; -import org.jetbrains.idea.svn.browse.DirectoryEntryConsumer; -import org.jetbrains.idea.svn.info.Info; -import org.jetbrains.idea.svn.integrate.SvnBranchItem; -import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.internal.util.SVNPathUtil; -import org.tmatesoft.svn.core.wc.SVNRevision; -import org.tmatesoft.svn.core.wc2.SvnTarget; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -public class DefaultConfigLoader { - - private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.branchConfig.DefaultConfigLoader"); - - @NonNls private static final String DEFAULT_TRUNK_NAME = "trunk"; - @NonNls private static final String DEFAULT_BRANCHES_NAME = "branches"; - @NonNls private static final String DEFAULT_TAGS_NAME = "tags"; - - private DefaultConfigLoader() { - } - - @Nullable - public static SvnBranchConfigurationNew loadDefaultConfiguration(final Project project, final VirtualFile vcsRoot) { - try { - final SvnVcs vcs = SvnVcs.getInstance(project); - - File rootFile = new File(vcsRoot.getPath()); - final Info info = vcs.getInfo(rootFile); - if (info == null || info.getURL() == null) { - LOG.info("Directory is not a working copy: " + vcsRoot.getPresentableUrl()); - return null; - } - SVNURL baseUrl = info.getURL(); - - final SvnBranchConfigurationNew result = new SvnBranchConfigurationNew(); - result.setTrunkUrl(baseUrl.toString()); - while(true) { - final String s = SVNPathUtil.tail(baseUrl.getPath()); - if (s.equalsIgnoreCase(DEFAULT_TRUNK_NAME) || s.equalsIgnoreCase(DEFAULT_BRANCHES_NAME) || s.equalsIgnoreCase(DEFAULT_TAGS_NAME)) { - SVNURL rootPath = baseUrl.removePathTail(); - SvnTarget target = SvnTarget.fromURL(rootPath); - - vcs.getFactory(target).createBrowseClient().list(target, SVNRevision.HEAD, Depth.IMMEDIATES, createHandler(result, rootPath)); - break; - } - if (SVNPathUtil.removeTail(baseUrl.getPath()).length() == 0) { - break; - } - baseUrl = baseUrl.removePathTail(); - } - return result; - } - catch (SVNException e) { - LOG.info(e); - return null; - } - catch (VcsException e) { - LOG.info(e); - return null; - } - } - - @NotNull - private static DirectoryEntryConsumer createHandler(final SvnBranchConfigurationNew result, final SVNURL rootPath) { - return new DirectoryEntryConsumer() { - - @Override - public void consume(final DirectoryEntry entry) throws SVNException { - if (entry.isDirectory()) { - SVNURL childUrl = rootPath.appendPath(entry.getName(), false); - - if (StringUtil.endsWithIgnoreCase(entry.getName(), DEFAULT_TRUNK_NAME)) { - result.setTrunkUrl(childUrl.toString()); - } - else { - result.addBranches(childUrl.toString(), - new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(0), InfoReliability.defaultValues)); - } - } - } - }; - } -} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoStorage.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoStorage.java index 493721e3a8d1..fe10696768c1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoStorage.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoStorage.java @@ -15,9 +15,6 @@ */ package org.jetbrains.idea.svn.branchConfig; -import com.intellij.util.PairConsumer; -import org.jetbrains.annotations.Nullable; - public class InfoStorage<T> { public T myT; public InfoReliability myInfoReliability; @@ -27,14 +24,15 @@ public class InfoStorage<T> { myInfoReliability = infoReliability; } - public void accept(final InfoStorage<T> infoStorage, @Nullable final PairConsumer<T, T> callbackOnUpdate) { - if (infoStorage.myInfoReliability.shouldOverride(myInfoReliability)) { - if (callbackOnUpdate != null) { - callbackOnUpdate.consume(myT, infoStorage.myT); - } + public boolean accept(final InfoStorage<T> infoStorage) { + boolean override = infoStorage.myInfoReliability.shouldOverride(myInfoReliability); + + if (override) { myT = infoStorage.myT; myInfoReliability = infoStorage.myInfoReliability; } + + return override; } public T getValue() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java index 2c7444ed85b0..6f7f4185a815 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java @@ -15,31 +15,23 @@ */ package org.jetbrains.idea.svn.branchConfig; -import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManagerQueue; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.util.Ref; import com.intellij.openapi.vcs.CalledInBackground; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.Consumer; -import com.intellij.util.PairConsumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.integrate.SvnBranchItem; +import org.jetbrains.idea.svn.SvnVcs; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; // synch is here -public class NewRootBunch implements SvnBranchConfigManager { +public class NewRootBunch { private final static Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.branchConfig.NewRootBunch"); private final Object myLock = new Object(); private final Project myProject; @@ -52,17 +44,31 @@ public class NewRootBunch implements SvnBranchConfigManager { myMap = new HashMap<VirtualFile, InfoStorage<SvnBranchConfigurationNew>>(); } - public void updateForRoot(@NotNull final VirtualFile root, @NotNull final InfoStorage<SvnBranchConfigurationNew> config, - @Nullable final PairConsumer<SvnBranchConfigurationNew, SvnBranchConfigurationNew> callbackOnUpdate) { + public void updateForRoot(@NotNull final VirtualFile root, + @NotNull final InfoStorage<SvnBranchConfigurationNew> config, + boolean reload) { synchronized (myLock) { + final SvnBranchConfigurationNew previous; + boolean override; final InfoStorage<SvnBranchConfigurationNew> existing = myMap.get(root); + if (existing == null) { + previous = null; + override = true; myMap.put(root, config); - if (callbackOnUpdate != null) { - callbackOnUpdate.consume(null, config.getValue()); - } - } else { - existing.accept(config, callbackOnUpdate); + } + else { + previous = existing.getValue(); + override = existing.accept(config); + } + + if (reload && override) { + myBranchesLoader.run(new Runnable() { + @Override + public void run() { + reloadBranches(root, previous, config.getValue()); + } + }); } } } @@ -88,17 +94,44 @@ public class NewRootBunch implements SvnBranchConfigManager { result = new SvnBranchConfigurationNew(); myMap.put(root, new InfoStorage<SvnBranchConfigurationNew>(result, InfoReliability.empty)); myBranchesLoader.run(new DefaultBranchConfigInitializer(myProject, this, root)); - } else { + } + else { result = value.getValue(); } return result; } } - public void reloadBranches(@NotNull final VirtualFile root, @NotNull final String branchParentUrl, - final Consumer<List<SvnBranchItem>> callback) { - ApplicationManager.getApplication().executeOnPooledThread(new BranchesLoadRunnable(myProject, this, branchParentUrl, - InfoReliability.setByUser, root, callback, true)); + public void reloadBranchesAsync(@NotNull final VirtualFile root, + @NotNull final String branchLocation, + @NotNull final InfoReliability reliability) { + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + reloadBranches(root, branchLocation, reliability, true); + } + }); + } + + public void reloadBranches(@NotNull VirtualFile root, @Nullable SvnBranchConfigurationNew prev, @NotNull SvnBranchConfigurationNew next) { + final Set<String> oldUrls = (prev == null) ? Collections.<String>emptySet() : new HashSet<String>(prev.getBranchUrls()); + final SvnVcs vcs = SvnVcs.getInstance(myProject); + if (!vcs.isVcsBackgroundOperationsAllowed(root)) return; + + for (String newBranchUrl : next.getBranchUrls()) { + // check if cancel had been put + if (!vcs.isVcsBackgroundOperationsAllowed(root)) return; + if (!oldUrls.contains(newBranchUrl)) { + reloadBranches(root, newBranchUrl, InfoReliability.defaultValues, true); + } + } + } + + public void reloadBranches(@NotNull VirtualFile root, + @NotNull String branchLocation, + @NotNull InfoReliability reliability, + boolean passive) { + new BranchesLoader(myProject, this, branchLocation, reliability, root, passive).run(); } @Nullable @@ -108,28 +141,11 @@ public class NewRootBunch implements SvnBranchConfigManager { try { final SvnBranchConfigurationNew configuration = myMap.get(root).getValue(); final String group = configuration.getGroupToLoadToReachUrl(svnurl); - final Runnable runnable = new Runnable() { - public void run() { - final SvnBranchConfigurationNew reloadedConfiguration = myMap.get(root).getValue(); - try { - result.set(reloadedConfiguration.getWorkingBranch(svnurl)); - } - catch (SVNException e) { - // - } - } - }; - if (group == null) { - runnable.run(); - } else { - new BranchesLoadRunnable(myProject, this, group, InfoReliability.setByUser, root, - new Consumer<List<SvnBranchItem>>() { - public void consume(List<SvnBranchItem> svnBranchItems) { - runnable.run(); - } - }, true).run(); + if (group != null) { + reloadBranches(root, group, InfoReliability.setByUser, true); } + result.set(myMap.get(root).getValue().getWorkingBranch(svnurl)); } catch (SVNException e) { // @@ -137,88 +153,6 @@ public class NewRootBunch implements SvnBranchConfigManager { return result.get(); } - public static class BranchesLoadRunnable implements Runnable { - private final Project myProject; - private final SvnBranchConfigManager myBunch; - private final VirtualFile myRoot; - @Nullable - private final Consumer<List<SvnBranchItem>> myCallback; - private final String myUrl; - private final InfoReliability myInfoReliability; - private boolean myPassive; - - public BranchesLoadRunnable(final Project project, - final SvnBranchConfigManager bunch, - final String url, - final InfoReliability infoReliability, - final VirtualFile root, - @Nullable final Consumer<List<SvnBranchItem>> callback, - boolean passive) { - myProject = project; - myBunch = bunch; - myUrl = url; - myInfoReliability = infoReliability; - myRoot = root; - myCallback = callback; - myPassive = passive; - } - - public void run() { - boolean callbackCalled = false; - try { - final List<SvnBranchItem> items = BranchesLoader.loadBranches(myProject, myUrl, myPassive); - myBunch.updateBranches(myRoot, myUrl, new InfoStorage<List<SvnBranchItem>>(items, myInfoReliability)); - if (myCallback != null) { - myCallback.consume(items); - callbackCalled = true; - } - } - catch (VcsException e) { - showError(e); - } - catch (SVNException e) { - showError(e); - } - finally { - // callback must be called by contract - if (myCallback != null && (! callbackCalled)) { - myCallback.consume(null); - } - } - } - - private void showError(Exception e) { - // already logged inside - if (InfoReliability.setByUser.equals(myInfoReliability)) { - VcsBalloonProblemNotifier.showOverChangesView(myProject, "Branches load error: " + e.getMessage(), MessageType.ERROR); - } - } - } - - private static class DefaultBranchConfigInitializer implements Runnable { - private final Project myProject; - private final SvnBranchConfigManager myBunch; - private final VirtualFile myRoot; - - private DefaultBranchConfigInitializer(final Project project, final SvnBranchConfigManager bunch, final VirtualFile root) { - myProject = project; - myRoot = root; - myBunch = bunch; - } - - public void run() { - final SvnBranchConfigurationNew result = DefaultConfigLoader.loadDefaultConfiguration(myProject, myRoot); - if (result != null) { - final Application application = ApplicationManager.getApplication(); - for (String url : result.getBranchUrls()) { - application.executeOnPooledThread(new BranchesLoadRunnable(myProject, myBunch, url, InfoReliability.defaultValues, myRoot, null, - true)); - } - myBunch.updateForRoot(myRoot, new InfoStorage<SvnBranchConfigurationNew>(result, InfoReliability.defaultValues), null); - } - } - } - public Map<VirtualFile, SvnBranchConfigurationNew> getMapCopy() { synchronized (myLock) { final Map<VirtualFile, SvnBranchConfigurationNew> result = new HashMap<VirtualFile, SvnBranchConfigurationNew>(); @@ -228,4 +162,4 @@ public class NewRootBunch implements SvnBranchConfigManager { return result; } } -} +}
\ No newline at end of file diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SelectBranchPopup.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java index 5e634f3b9b87..445ce4e9afe3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SelectBranchPopup.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.actions; +package org.jetbrains.idea.svn.branchConfig; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; @@ -30,13 +30,10 @@ import com.intellij.util.text.DateFormatUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.*; -import org.jetbrains.idea.svn.branchConfig.InfoReliability; -import org.jetbrains.idea.svn.branchConfig.NewRootBunch; -import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigManager; -import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; -import org.jetbrains.idea.svn.dialogs.BranchConfigurationDialog; -import org.jetbrains.idea.svn.integrate.SvnBranchItem; +import org.jetbrains.idea.svn.RootUrlInfo; +import org.jetbrains.idea.svn.SvnBundle; +import org.jetbrains.idea.svn.SvnFileUrlMapping; +import org.jetbrains.idea.svn.SvnVcs; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; @@ -221,8 +218,9 @@ public class SelectBranchPopup { @Override protected void runImpl(@NotNull ProgressIndicator indicator) { - final SvnBranchConfigManager manager = SvnBranchConfigurationManager.getInstance(myProject).getSvnBranchConfigManager(); - new NewRootBunch.BranchesLoadRunnable(myProject, manager, selectedBranchesHolder, InfoReliability.setByUser, myVcsRoot, null, false).run(); + final NewRootBunch manager = SvnBranchConfigurationManager.getInstance(myProject).getSvnBranchConfigManager(); + + manager.reloadBranches(myVcsRoot, selectedBranchesHolder, InfoReliability.setByUser, false); } }); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigManager.java deleted file mode 100644 index 0a47a7771171..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigManager.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.svn.branchConfig; - -import com.intellij.openapi.vcs.CalledInBackground; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.Consumer; -import com.intellij.util.PairConsumer; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.integrate.SvnBranchItem; -import org.tmatesoft.svn.core.SVNURL; - -import java.util.List; -import java.util.Map; - -public interface SvnBranchConfigManager { - void updateForRoot(@NotNull VirtualFile root, @NotNull InfoStorage<SvnBranchConfigurationNew> config, - @Nullable final PairConsumer<SvnBranchConfigurationNew, SvnBranchConfigurationNew> callbackOnUpdate); - - void updateBranches(@NotNull VirtualFile root, @NotNull String branchesParent, - @NotNull InfoStorage<List<SvnBranchItem>> items); - - @NotNull - SvnBranchConfigurationNew getConfig(@NotNull VirtualFile root); - - void reloadBranches(@NotNull VirtualFile root, @NotNull String branchParentUrl, - Consumer<List<SvnBranchItem>> callback); - @Nullable - @CalledInBackground - SVNURL getWorkingBranchWithReload(final SVNURL svnurl, final VirtualFile root); - - Map<VirtualFile, SvnBranchConfigurationNew> getMapCopy(); -} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfiguration.java index c167fd868531..0c6138fd08c2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfiguration.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfiguration.java @@ -14,24 +14,36 @@ * limitations under the License. */ -package org.jetbrains.idea.svn; +package org.jetbrains.idea.svn.branchConfig; + +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** + * Default constructor and setters are necessary for serialization purposes. + * * @author yole */ +@SuppressWarnings("UnusedDeclaration") public class SvnBranchConfiguration { private String myTrunkUrl; - private List<String> myBranchUrls; + @NotNull private List<String> myBranchUrls; private boolean myUserinfoInUrl; public SvnBranchConfiguration() { myBranchUrls = new ArrayList<String>(); } + public SvnBranchConfiguration(String trunkUrl, @NotNull List<String> branchUrls, boolean userinfoInUrl) { + myTrunkUrl = trunkUrl; + myBranchUrls = branchUrls; + Collections.sort(myBranchUrls); + myUserinfoInUrl = userinfoInUrl; + } + public boolean isUserinfoInUrl() { return myUserinfoInUrl; } @@ -39,8 +51,8 @@ public class SvnBranchConfiguration { public void setUserinfoInUrl(final boolean userinfoInUrl) { myUserinfoInUrl = userinfoInUrl; } - - public void setBranchUrls(final List<String> branchUrls) { + + public void setBranchUrls(@NotNull List<String> branchUrls) { myBranchUrls = branchUrls; Collections.sort(myBranchUrls); } @@ -53,6 +65,7 @@ public class SvnBranchConfiguration { return myTrunkUrl; } + @NotNull public List<String> getBranchUrls() { return myBranchUrls; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationManager.java index f13ed5a97a03..772e5edd2755 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationManager.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.idea.svn; +package org.jetbrains.idea.svn.branchConfig; import com.intellij.lifecycle.PeriodicalTasksCloser; import com.intellij.openapi.application.ApplicationManager; @@ -27,7 +27,6 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressManagerQueue; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.Ref; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.committed.VcsConfigurationChangeListener; @@ -35,14 +34,10 @@ import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl; import com.intellij.openapi.vcs.impl.VcsInitObject; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.PairConsumer; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBus; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.branchConfig.*; -import org.jetbrains.idea.svn.integrate.SvnBranchItem; -import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.SVNURL; +import org.jetbrains.idea.svn.SvnVcs; import java.io.File; import java.util.*; @@ -58,15 +53,16 @@ import java.util.*; )} ) public class SvnBranchConfigurationManager implements PersistentStateComponent<SvnBranchConfigurationManager.ConfigurationBean> { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnBranchConfigurationManager"); + private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager"); private final Project myProject; private final ProjectLevelVcsManager myVcsManager; - private final SvnLoadedBrachesStorage myStorage; + private final SvnLoadedBranchesStorage myStorage; private final ProgressManagerQueue myBranchesLoader; + private boolean myIsInitialized; public SvnBranchConfigurationManager(final Project project, final ProjectLevelVcsManager vcsManager, - final SvnLoadedBrachesStorage storage) { + final SvnLoadedBranchesStorage storage) { myProject = project; myVcsManager = vcsManager; myStorage = storage; @@ -91,7 +87,13 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent<S } public static SvnBranchConfigurationManager getInstance(final Project project) { - return PeriodicalTasksCloser.getInstance().safeGetService(project, SvnBranchConfigurationManager.class); + SvnBranchConfigurationManager result = PeriodicalTasksCloser.getInstance().safeGetService(project, SvnBranchConfigurationManager.class); + + if (result != null) { + result.initialize(); + } + + return result; } public static class ConfigurationBean { @@ -108,19 +110,18 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent<S } private ConfigurationBean myConfigurationBean = new ConfigurationBean(); - private final SvnBranchConfigManager myBunch; + private final NewRootBunch myBunch; public SvnBranchConfigurationNew get(@NotNull final VirtualFile vcsRoot) throws VcsException { return myBunch.getConfig(vcsRoot); } - public SvnBranchConfigManager getSvnBranchConfigManager() { + public NewRootBunch getSvnBranchConfigManager() { return myBunch; } public void setConfiguration(final VirtualFile vcsRoot, final SvnBranchConfigurationNew configuration) { - myBunch.updateForRoot(vcsRoot, new InfoStorage<SvnBranchConfigurationNew>(configuration, InfoReliability.setByUser), - new BranchesPreloader(myProject, myBunch, vcsRoot, myBranchesLoader)); + myBunch.updateForRoot(vcsRoot, new InfoStorage<SvnBranchConfigurationNew>(configuration, InfoReliability.setByUser), true); SvnBranchMapperManager.getInstance().notifyBranchesChanged(myProject, vcsRoot, configuration); @@ -136,71 +137,33 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent<S for (VirtualFile root : myBunch.getMapCopy().keySet()) { final String key = root.getPath(); final SvnBranchConfigurationNew configOrig = myBunch.getConfig(root); - final SvnBranchConfiguration configuration = new SvnBranchConfiguration(); - configuration.setTrunkUrl(configOrig.getTrunkUrl()); - configuration.setUserinfoInUrl(configOrig.isUserinfoInUrl()); - configuration.setBranchUrls(configOrig.getBranchUrls()); - final HashMap<String, List<SvnBranchItem>> map = new HashMap<String, List<SvnBranchItem>>(); - final Map<String, InfoStorage<List<SvnBranchItem>>> origMap = configOrig.getBranchMap(); - for (String origKey : origMap.keySet()) { - map.put(origKey, origMap.get(origKey).getValue()); - } + final SvnBranchConfiguration configuration = + new SvnBranchConfiguration(configOrig.getTrunkUrl(), configOrig.getBranchUrls(), configOrig.isUserinfoInUrl()); + result.myConfigurationMap.put(key, helper.prepareForSerialization(configuration)); } result.mySupportsUserInfoFilter = true; return result; } - private static class BranchesPreloader implements PairConsumer<SvnBranchConfigurationNew, SvnBranchConfigurationNew> { - private final Project myProject; - private final VirtualFile myRoot; - private final ProgressManagerQueue myQueue; - private final SvnBranchConfigManager myBunch; - private boolean myAll; + public void loadState(ConfigurationBean object) { + myConfigurationBean = object; + } - public BranchesPreloader(Project project, @NotNull final SvnBranchConfigManager bunch, VirtualFile root, - final ProgressManagerQueue queue) { - myBunch = bunch; - myProject = project; - myRoot = root; - myQueue = queue; - } + private synchronized void initialize() { + if (!myIsInitialized) { + myIsInitialized = true; - public void consume(final SvnBranchConfigurationNew prev, final SvnBranchConfigurationNew next) { - myQueue.run(new Runnable() { - public void run() { - loadImpl(prev, next); - } - }); - } - - protected void loadImpl(final SvnBranchConfigurationNew prev, final SvnBranchConfigurationNew next) { - final Set<String> oldUrls = (prev == null) ? Collections.<String>emptySet() : new HashSet<String>(prev.getBranchUrls()); - final SvnVcs vcs = SvnVcs.getInstance(myProject); - if (! vcs.isVcsBackgroundOperationsAllowed(myRoot)) return; - - for (String newBranchUrl : next.getBranchUrls()) { - // check if cancel had been put - if (! vcs.isVcsBackgroundOperationsAllowed(myRoot)) return; - if (myAll || (! oldUrls.contains(newBranchUrl))) { - new NewRootBunch.BranchesLoadRunnable(myProject, myBunch, newBranchUrl, InfoReliability.defaultValues, myRoot, null, true).run(); - } - } - } - - public void setAll(boolean all) { - myAll = all; + preloadBranches(resolveAllBranchPoints()); } } - public void loadState(final ConfigurationBean object) { - final UrlSerializationHelper helper = new UrlSerializationHelper(SvnVcs.getInstance(myProject)); - final Map<String, SvnBranchConfiguration> map = object.myConfigurationMap; - final Map<String, SvnBranchConfiguration> newMap = new HashMap<String, SvnBranchConfiguration>(map.size(), 1); + @NotNull + private Set<Pair<VirtualFile, SvnBranchConfigurationNew>> resolveAllBranchPoints() { final LocalFileSystem lfs = LocalFileSystem.getInstance(); - - final Set<Pair<VirtualFile, SvnBranchConfigurationNew>> whatToInit = new HashSet<Pair<VirtualFile, SvnBranchConfigurationNew>>(); - for (Map.Entry<String, SvnBranchConfiguration> entry : map.entrySet()) { + final UrlSerializationHelper helper = new UrlSerializationHelper(SvnVcs.getInstance(myProject)); + final Set<Pair<VirtualFile, SvnBranchConfigurationNew>> branchPointsToLoad = ContainerUtil.newHashSet(); + for (Map.Entry<String, SvnBranchConfiguration> entry : myConfigurationBean.myConfigurationMap.entrySet()) { final SvnBranchConfiguration configuration = entry.getValue(); final VirtualFile root = lfs.refreshAndFindFileByIoFile(new File(entry.getKey())); if (root == null) { @@ -222,22 +185,24 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent<S if (stored != null && ! stored.isEmpty()) { newConfig.addBranches(branchUrl, new InfoStorage<List<SvnBranchItem>>(stored, InfoReliability.setByUser)); } else { - whatToInit.add(Pair.create(root, newConfig)); + branchPointsToLoad.add(Pair.create(root, newConfig)); newConfig.addBranches(branchUrl, new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(), InfoReliability.empty)); } } - myBunch.updateForRoot(root, new InfoStorage<SvnBranchConfigurationNew>(newConfig, InfoReliability.setByUser), null); + myBunch.updateForRoot(root, new InfoStorage<SvnBranchConfigurationNew>(newConfig, InfoReliability.setByUser), false); } + return branchPointsToLoad; + } + + private void preloadBranches(@NotNull final Collection<Pair<VirtualFile, SvnBranchConfigurationNew>> branchPoints) { ((ProjectLevelVcsManagerImpl) myVcsManager).addInitializationRequest(VcsInitObject.BRANCHES, new Runnable() { public void run() { ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { public void run() { try { - for (Pair<VirtualFile, SvnBranchConfigurationNew> pair : whatToInit) { - final BranchesPreloader branchesPreloader = new BranchesPreloader(myProject, myBunch, pair.getFirst(), myBranchesLoader); - branchesPreloader.setAll(true); - branchesPreloader.loadImpl(null, pair.getSecond()); + for (Pair<VirtualFile, SvnBranchConfigurationNew> pair : branchPoints) { + myBunch.reloadBranches(pair.getFirst(), null, pair.getSecond()); } } catch (ProcessCanceledException e) { @@ -247,9 +212,6 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent<S }); } }); - object.myConfigurationMap.clear(); - object.myConfigurationMap.putAll(newMap); - myConfigurationBean = object; } private List<SvnBranchItem> getStored(String branchUrl) { @@ -259,93 +221,4 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent<S Collections.sort(items); return items; } - - private static class UrlSerializationHelper { - private final SvnVcs myVcs; - - private UrlSerializationHelper(final SvnVcs vcs) { - myVcs = vcs; - } - - public SvnBranchConfiguration prepareForSerialization(final SvnBranchConfiguration configuration) { - final Ref<Boolean> withUserInfo = new Ref<Boolean>(); - final String trunkUrl = serializeUrl(configuration.getTrunkUrl(), withUserInfo); - - if (Boolean.FALSE.equals(withUserInfo.get())) { - return configuration; - } - - final List<String> branches = configuration.getBranchUrls(); - final List<String> newBranchesList = new ArrayList<String>(branches.size()); - for (String s : branches) { - newBranchesList.add(serializeUrl(s, withUserInfo)); - } - - final SvnBranchConfiguration result = new SvnBranchConfiguration(); - result.setTrunkUrl(trunkUrl); - result.setBranchUrls(newBranchesList); - result.setUserinfoInUrl(withUserInfo.isNull() ? false : withUserInfo.get()); - return result; - } - - public SvnBranchConfiguration afterDeserialization(final String path, final SvnBranchConfiguration configuration) { - if (! configuration.isUserinfoInUrl()) { - return configuration; - } - final String userInfo = getUserInfo(path); - if (userInfo == null) { - return configuration; - } - - final String newTrunkUrl = deserializeUrl(configuration.getTrunkUrl(), userInfo); - final List<String> branches = configuration.getBranchUrls(); - final List<String> newBranchesList = new ArrayList<String>(branches.size()); - for (String s : branches) { - newBranchesList.add(deserializeUrl(s, userInfo)); - } - - final SvnBranchConfiguration result = new SvnBranchConfiguration(); - result.setTrunkUrl(newTrunkUrl); - result.setBranchUrls(newBranchesList); - result.setUserinfoInUrl(userInfo != null && userInfo.length() > 0); - return result; - } - - private static String serializeUrl(final String url, final Ref<Boolean> withUserInfo) { - if (Boolean.FALSE.equals(withUserInfo.get())) { - return url; - } - try { - final SVNURL svnurl = SVNURL.parseURIEncoded(url); - if (withUserInfo.isNull()) { - final String userInfo = svnurl.getUserInfo(); - withUserInfo.set((userInfo != null) && (userInfo.length() > 0)); - } - if (withUserInfo.get()) { - return SVNURL.create(svnurl.getProtocol(), null, svnurl.getHost(), SvnUtil.resolvePort(svnurl), svnurl.getURIEncodedPath(), true) - .toString(); - } - } - catch (SVNException e) { - // - } - return url; - } - - @Nullable - private String getUserInfo(final String path) { - final SVNURL svnurl = myVcs.getSvnFileUrlMapping().getUrlForFile(new File(path)); - return svnurl != null ? svnurl.getUserInfo() : null; - } - - private static String deserializeUrl(final String url, final String userInfo) { - try { - final SVNURL svnurl = SVNURL.parseURIEncoded(url); - return SVNURL.create(svnurl.getProtocol(), userInfo, svnurl.getHost(), SvnUtil.resolvePort(svnurl), svnurl.getURIEncodedPath(), - true).toString(); - } catch (SVNException e) { - return url; - } - } - } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java index 4102210a657a..3ce3c986c8ae 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java @@ -24,7 +24,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.info.Info; -import org.jetbrains.idea.svn.integrate.SvnBranchItem; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; @@ -98,7 +97,7 @@ public class SvnBranchConfigurationNew { LOG.info("Branches list not updated for : '" + branchParentName + "; since config has changed."); return; } - current.accept(items, null); + current.accept(items); } public Map<String, InfoStorage<List<SvnBranchItem>>> getBranchMap() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnBranchItem.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchItem.java index f9e428d1becf..a0bd0868b6d2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnBranchItem.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchItem.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.integrate; +package org.jetbrains.idea.svn.branchConfig; import java.util.Date; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchMapperManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchMapperManager.java index e82e363f598a..f9f99bea1e17 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchMapperManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchMapperManager.java @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn; +package org.jetbrains.idea.svn.branchConfig; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.messages.Topic; -import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import java.io.File; -import java.util.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; /** * Holds what working copies we have for URLs @@ -56,7 +56,6 @@ public class SvnBranchMapperManager implements PersistentStateComponent<SvnBranc public void put(final String url, final String value) { myStateHolder.put(url, value); - notifyWcRootsChanged(url, Collections.unmodifiableCollection(myStateHolder.get(url))); } public void remove(final String url, final File value) { @@ -64,11 +63,6 @@ public class SvnBranchMapperManager implements PersistentStateComponent<SvnBranc if (set != null) { set.remove(value.getAbsolutePath()); } - notifyWcRootsChanged(url, Collections.unmodifiableCollection(set)); - } - - private static void notifyWcRootsChanged(final String url, final Collection<String> roots) { - ApplicationManager.getApplication().getMessageBus().syncPublisher(WC_ROOTS_CHANGED).rootsChanged(url, roots); } public void notifyBranchesChanged(final Project project, final VirtualFile vcsRoot, final SvnBranchConfigurationNew configuration) { @@ -104,11 +98,4 @@ public class SvnBranchMapperManager implements PersistentStateComponent<SvnBranc return myMapping.get(key); } } - - public static interface WcRootsChangeConsumer { - void rootsChanged(final String url, final Collection<String> roots); - } - - public static final Topic<WcRootsChangeConsumer> WC_ROOTS_CHANGED = - new Topic<WcRootsChangeConsumer>("SVN_WC_ROOTS_CHANGED", WcRootsChangeConsumer.class); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnLoadedBrachesStorage.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnLoadedBranchesStorage.java index 8fe1fa52a938..041e33cc5ac7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnLoadedBrachesStorage.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnLoadedBranchesStorage.java @@ -13,19 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn; +package org.jetbrains.idea.svn.branchConfig; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.persistent.SmallMapSerializer; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.EnumeratorStringDescriptor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.branchConfig.InfoStorage; -import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; -import org.jetbrains.idea.svn.integrate.SvnBranchItem; import java.io.DataInput; import java.io.DataOutput; @@ -39,13 +37,13 @@ import java.util.*; * Date: 8/24/11 * Time: 1:21 PM */ -public class SvnLoadedBrachesStorage { +public class SvnLoadedBranchesStorage { private final Object myLock; private SmallMapSerializer<String, Map<String, Collection<SvnBranchItem>>> myState; private final File myFile; private final Project myProject; - public SvnLoadedBrachesStorage(final Project project) { + public SvnLoadedBranchesStorage(final Project project) { myProject = project; final File vcsFile = new File(PathManager.getSystemPath(), "vcs"); File file = new File(vcsFile, "svn_branches"); @@ -63,18 +61,6 @@ public class SvnLoadedBrachesStorage { } } - public void put(final String url, final Collection<SvnBranchItem> items) { - synchronized (myLock) { - if (myState == null) return; - Map<String, Collection<SvnBranchItem>> map = myState.get(""); - if (map == null) { - map = new HashMap<String, Collection<SvnBranchItem>>(); - myState.put("", map); - } - map.put(url, items); - } - } - public void activate() { synchronized (myLock) { myState = new SmallMapSerializer<String, Map<String, Collection<SvnBranchItem>>>(myFile, new EnumeratorStringDescriptor(), createExternalizer()); @@ -83,15 +69,19 @@ public class SvnLoadedBrachesStorage { public void deactivate() { + Map<String, Collection<SvnBranchItem>> branchLocationToBranchItemsMap = ContainerUtil.newHashMap(); SvnBranchConfigurationManager manager = SvnBranchConfigurationManager.getInstance(myProject); Map<VirtualFile,SvnBranchConfigurationNew> mapCopy = manager.getSvnBranchConfigManager().getMapCopy(); for (Map.Entry<VirtualFile, SvnBranchConfigurationNew> entry : mapCopy.entrySet()) { Map<String,InfoStorage<List<SvnBranchItem>>> branchMap = entry.getValue().getBranchMap(); for (Map.Entry<String, InfoStorage<List<SvnBranchItem>>> storageEntry : branchMap.entrySet()) { - put(storageEntry.getKey(), storageEntry.getValue().getValue()); + branchLocationToBranchItemsMap.put(storageEntry.getKey(), storageEntry.getValue().getValue()); } } synchronized (myLock) { + // TODO: Possibly implement optimization - do not perform save if there are no changes in branch locations and branch items + // ensure myState.put() is called - so myState will treat itself as dirty and myState.force() will invoke real persisting + myState.put("", branchLocationToBranchItemsMap); myState.force(); myState = null; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/UrlSerializationHelper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/UrlSerializationHelper.java new file mode 100644 index 000000000000..36c16f33a0fc --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/UrlSerializationHelper.java @@ -0,0 +1,111 @@ +/* + * 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 org.jetbrains.idea.svn.branchConfig; + +import com.intellij.openapi.util.Ref; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.SvnUtil; +import org.jetbrains.idea.svn.SvnVcs; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** +* @author Konstantin Kolosovsky. +*/ +public class UrlSerializationHelper { + private final SvnVcs myVcs; + + public UrlSerializationHelper(final SvnVcs vcs) { + myVcs = vcs; + } + + public SvnBranchConfiguration prepareForSerialization(final SvnBranchConfiguration configuration) { + final Ref<Boolean> withUserInfo = new Ref<Boolean>(); + final String trunkUrl = serializeUrl(configuration.getTrunkUrl(), withUserInfo); + + if (Boolean.FALSE.equals(withUserInfo.get())) { + return configuration; + } + + final List<String> branches = configuration.getBranchUrls(); + final List<String> newBranchesList = new ArrayList<String>(branches.size()); + for (String s : branches) { + newBranchesList.add(serializeUrl(s, withUserInfo)); + } + + return new SvnBranchConfiguration(trunkUrl, newBranchesList, withUserInfo.isNull() ? false : withUserInfo.get()); + } + + public SvnBranchConfiguration afterDeserialization(final String path, final SvnBranchConfiguration configuration) { + if (! configuration.isUserinfoInUrl()) { + return configuration; + } + final String userInfo = getUserInfo(path); + if (userInfo == null) { + return configuration; + } + + final String newTrunkUrl = deserializeUrl(configuration.getTrunkUrl(), userInfo); + final List<String> branches = configuration.getBranchUrls(); + final List<String> newBranchesList = new ArrayList<String>(branches.size()); + for (String s : branches) { + newBranchesList.add(deserializeUrl(s, userInfo)); + } + + return new SvnBranchConfiguration(newTrunkUrl, newBranchesList, userInfo.length() > 0); + } + + private static String serializeUrl(final String url, final Ref<Boolean> withUserInfo) { + if (Boolean.FALSE.equals(withUserInfo.get())) { + return url; + } + try { + final SVNURL svnurl = SVNURL.parseURIEncoded(url); + if (withUserInfo.isNull()) { + final String userInfo = svnurl.getUserInfo(); + withUserInfo.set((userInfo != null) && (userInfo.length() > 0)); + } + if (withUserInfo.get()) { + return SVNURL.create(svnurl.getProtocol(), null, svnurl.getHost(), SvnUtil.resolvePort(svnurl), svnurl.getURIEncodedPath(), true) + .toString(); + } + } + catch (SVNException e) { + // + } + return url; + } + + @Nullable + private String getUserInfo(final String path) { + final SVNURL svnurl = myVcs.getSvnFileUrlMapping().getUrlForFile(new File(path)); + return svnurl != null ? svnurl.getUserInfo() : null; + } + + private static String deserializeUrl(final String url, final String userInfo) { + try { + final SVNURL svnurl = SVNURL.parseURIEncoded(url); + return SVNURL.create(svnurl.getProtocol(), userInfo, svnurl.getHost(), SvnUtil.resolvePort(svnurl), svnurl.getURIEncodedPath(), + true).toString(); + } catch (SVNException e) { + return url; + } + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java index c9a843501253..3f43d7452b5e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java @@ -124,7 +124,7 @@ public class SvnCheckinEnvironment implements CheckinEnvironment { String comment, List<VcsException> exception, final Set<String> feedback, - final WorkingCopyFormat format) + @NotNull WorkingCopyFormat format) throws VcsException { if (committables.isEmpty()) { return; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java index 602a6e8c460e..cfb4a935bc14 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java @@ -16,6 +16,9 @@ package org.jetbrains.idea.svn.commandLine; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.Stack; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.api.EventAction; @@ -43,17 +46,13 @@ public class UpdateOutputLineConverter { private final static String RECORDING_MERGE_INFO = "--- Recording mergeinfo"; private final static String UPDATING = "Updating"; - private final static String AT_REVISION = "At revision (\\d+)\\."; - private final static String UPDATED_TO_REVISION = "Updated to revision (\\d+)\\."; private final static String SKIPPED = "Skipped"; private final static String RESTORED = "Restored"; private final static String FETCHING_EXTERNAL = "Fetching external"; - private final static String EXTERNAL = "External at (\\d+)\\."; - private final static String UPDATED_EXTERNAL = "Updated external to revision (\\d+)\\."; - - private final static Pattern ourAtRevision = Pattern.compile(AT_REVISION); - private final static Pattern ourUpdatedToRevision = Pattern.compile(UPDATED_TO_REVISION); + + private final static Pattern ourAtRevision = Pattern.compile("At revision (\\d+)\\."); + private final static Pattern ourUpdatedToRevision = Pattern.compile("Updated to revision (\\d+)\\."); private final static Pattern ourCheckedOutRevision = Pattern.compile("Checked out revision (\\d+)\\."); // export from repository @@ -61,8 +60,8 @@ public class UpdateOutputLineConverter { // export from working copy private final static Pattern ourExportComplete = Pattern.compile("Export complete\\."); - private final static Pattern ourExternal = Pattern.compile(EXTERNAL); - private final static Pattern ourUpdatedExternal = Pattern.compile(UPDATED_EXTERNAL); + private final static Pattern ourExternal = Pattern.compile("External at (\\d+)\\."); + private final static Pattern ourUpdatedExternal = Pattern.compile("Updated external to revision (\\d+)\\."); private final static Pattern ourCheckedOutExternal = Pattern.compile("Checked out external at revision (\\d+)\\."); private final static Pattern[] ourCompletePatterns = @@ -70,15 +69,14 @@ public class UpdateOutputLineConverter { ourCheckedOutExternal, ourExportComplete}; private final File myBase; - private File myCurrentFile; + @NotNull private final Stack<File> myRootsUnderProcessing; public UpdateOutputLineConverter(File base) { myBase = base; - // checkout output does not have special line like "Updating '.'" on start - so set current file directly - // to correctly detect complete event - myCurrentFile = base; + myRootsUnderProcessing = ContainerUtil.newStack(); } + @Nullable public ProgressEvent convert(final String line) { // TODO: Add direct processing of "Summary of conflicts" lines at the end of "svn update" output (if there are conflicts). // TODO: Now it works ok because parseNormalLine could not determine necessary statuses from that and further lines @@ -87,35 +85,45 @@ public class UpdateOutputLineConverter { if (line.startsWith(MERGING) || line.startsWith(RECORDING_MERGE_INFO)) { return null; } else if (line.startsWith(UPDATING)) { - myCurrentFile = parseForPath(line); - return new ProgressEvent(myCurrentFile, -1, null, null, EventAction.UPDATE_NONE, null, null); + myRootsUnderProcessing.push(parseForPath(line)); + return createEvent(myRootsUnderProcessing.peek(), EventAction.UPDATE_NONE); } else if (line.startsWith(RESTORED)) { - myCurrentFile = parseForPath(line); - return new ProgressEvent(myCurrentFile, -1, null, null, EventAction.RESTORE, null, null); + return createEvent(parseForPath(line), EventAction.RESTORE); } else if (line.startsWith(SKIPPED)) { // called, for instance, when folder is not working copy - myCurrentFile = parseForPath(line); final String comment = parseComment(line); - return new ProgressEvent(myCurrentFile, -1, null, null, EventAction.SKIP, - comment == null ? null : SVNErrorMessage.create(SVNErrorCode.WC_OBSTRUCTED_UPDATE, comment), null); + return createEvent(parseForPath(line), -1, EventAction.SKIP, + comment == null ? null : SVNErrorMessage.create(SVNErrorCode.WC_OBSTRUCTED_UPDATE, comment)); } else if (line.startsWith(FETCHING_EXTERNAL)) { - myCurrentFile = parseForPath(line); - return new ProgressEvent(myCurrentFile, -1, null, null, EventAction.UPDATE_EXTERNAL, null, null); + myRootsUnderProcessing.push(parseForPath(line)); + return createEvent(myRootsUnderProcessing.peek(), EventAction.UPDATE_EXTERNAL); } - for (int i = 0; i < ourCompletePatterns.length; i++) { - final Pattern pattern = ourCompletePatterns[i]; + for (final Pattern pattern : ourCompletePatterns) { final long revision = matchAndGetRevision(pattern, line); if (revision != -1) { - // TODO: seems that myCurrentFile will not always be correct - complete update message could be right after complete externals update - // TODO: check this and use Stack instead - return new ProgressEvent(myCurrentFile, revision, null, null, EventAction.UPDATE_COMPLETED, null, null); + // checkout output does not have special line like "Updating '.'" on start - so stack could be empty and we should use myBase + File currentRoot = myRootsUnderProcessing.size() > 0 ? myRootsUnderProcessing.pop() : myBase; + return createEvent(currentRoot, revision, EventAction.UPDATE_COMPLETED, null); } } return parseNormalString(line); } + @NotNull + private static ProgressEvent createEvent(File file, @NotNull EventAction action) { + return createEvent(file, -1, action, null); + } + + @NotNull + private static ProgressEvent createEvent(File file, + long revision, + @NotNull EventAction action, + @Nullable SVNErrorMessage error) { + return new ProgressEvent(file, revision, null, null, action, error, null); + } + private final static Set<Character> ourActions = new HashSet<Character>(Arrays.asList(new Character[] {'A', 'D', 'U', 'C', 'G', 'E', 'R'})); @Nullable @@ -134,7 +142,7 @@ public class UpdateOutputLineConverter { final String path = line.substring(4).trim(); if (StringUtil.isEmptyOrSpaces(path)) return null; - final File file = createFile(path); + final File file = SvnUtil.resolvePath(myBase, path); if (StatusType.STATUS_OBSTRUCTED.equals(contentsStatus)) { // obstructed return new ProgressEvent(file, -1, contentsStatus, propertiesStatus, EventAction.UPDATE_SKIP_OBSTRUCTION, null, null); @@ -157,12 +165,7 @@ public class UpdateOutputLineConverter { return new ProgressEvent(file, -1, contentsStatus, propertiesStatus, action, null, null); } - private File createFile(String path) { - return SvnUtil.resolvePath(myBase, path); - } - - @Nullable - private long matchAndGetRevision(final Pattern pattern, final String line) { + private static long matchAndGetRevision(final Pattern pattern, final String line) { final Matcher matcher = pattern.matcher(line); if (matcher.matches()) { if (pattern == ourExportComplete) { @@ -181,22 +184,26 @@ public class UpdateOutputLineConverter { } @Nullable - private String parseComment(final String line) { - final int idx = line.lastIndexOf("--"); - if (idx != -1 && idx < (line.length() - 2)) { - return line.substring(idx + 2).trim(); - } - return null; + private static String parseComment(final String line) { + int index = line.lastIndexOf("--"); + + return index != -1 && index < line.length() - 2 ? line.substring(index + 2).trim() : null; } @Nullable - private File parseForPath(final String line) { - final int idx1 = line.indexOf('\''); - if (idx1 == -1) return null; - final int idx2 = line.indexOf('\'', idx1 + 1); - if (idx2 == -1) return null; - final String substring = line.substring(idx1 + 1, idx2); - if (".".equals(substring)) return myBase; - return createFile(substring); + private File parseForPath(@NotNull String line) { + File result = null; + int start = line.indexOf('\''); + + if (start != -1) { + int end = line.indexOf('\'', start + 1); + + if (end != -1) { + String path = line.substring(start + 1, end); + result = SvnUtil.resolvePath(myBase, path); + } + } + + return result; } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java index 9ca5b89d517a..1b48f9d70e5b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java @@ -45,7 +45,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; import org.jetbrains.idea.svn.actions.CleanupWorker; -import org.jetbrains.idea.svn.actions.SelectBranchPopup; +import org.jetbrains.idea.svn.branchConfig.BranchConfigurationDialog; +import org.jetbrains.idea.svn.branchConfig.SelectBranchPopup; import org.jetbrains.idea.svn.api.ClientFactory; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java index cd504be56077..437e7f57e464 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java @@ -41,7 +41,6 @@ import org.jetbrains.idea.svn.properties.PropertyConsumer; import org.jetbrains.idea.svn.properties.PropertyData; import org.jetbrains.idea.svn.properties.PropertyValue; import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.SVNProperty; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -309,7 +308,7 @@ public class PropertiesComponent extends JPanel { PropertyValue propValue = null; try { propValue = myVcs.getFactory(myFile).createPropertyClient() - .getProperty(SvnTarget.fromFile(myFile), SVNProperty.KEYWORDS, false, SVNRevision.WORKING); + .getProperty(SvnTarget.fromFile(myFile), SvnPropertyKeys.SVN_KEYWORDS, false, SVNRevision.WORKING); } catch (VcsException e1) { // show erorr message diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java index 163be4922224..f7e54a64f0ad 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java @@ -266,7 +266,7 @@ public class RepositoryBrowserComponent extends JPanel implements Disposable, Da if (entry.getName().lastIndexOf('.') > 0 && !manager.getFileTypeByFileName(name).isBinary()) { SVNURL url = node.getURL(); final SvnFileRevision revision = new SvnFileRevision(myVCS, SVNRevision.UNDEFINED, SVNRevision.HEAD, url.toString(), - entry.getAuthor(), entry.getDate(), null, null, null); + entry.getAuthor(), entry.getDate(), null, null); return new VcsVirtualFile(node.getSVNDirEntry().getName(), revision, VcsFileSystem.getInstance()); } else { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java index a8e0ca9e5e7a..278c7d0b5e1c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java @@ -26,7 +26,7 @@ import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.*; -import org.jetbrains.idea.svn.actions.SelectBranchPopup; +import org.jetbrains.idea.svn.branchConfig.SelectBranchPopup; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; /** diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LoadedRevisionsCache.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LoadedRevisionsCache.java index 5da830f0ca87..7e1c9d155a0e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LoadedRevisionsCache.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LoadedRevisionsCache.java @@ -22,13 +22,13 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vcs.RepositoryLocation; -import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.committed.ChangesBunch; +import com.intellij.openapi.vcs.changes.committed.CommittedChangesAdapter; import com.intellij.openapi.vcs.changes.committed.CommittedChangesCache; -import com.intellij.openapi.vcs.changes.committed.CommittedChangesListener; import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; import com.intellij.util.containers.SoftHashMap; import com.intellij.util.messages.MessageBusConnection; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -51,7 +51,9 @@ public class LoadedRevisionsCache implements Disposable { myMap = (ApplicationManager.getApplication().isUnitTestMode()) ? new HashMap<String, Bunch>() : new SoftHashMap<String, Bunch>(); myConnection = project.getMessageBus().connect(); - myConnection.subscribe(CommittedChangesCache.COMMITTED_TOPIC, new CommittedChangesListener() { + myConnection.subscribe(CommittedChangesCache.COMMITTED_TOPIC, new CommittedChangesAdapter() { + + @Override public void changesLoaded(final RepositoryLocation location, final List<CommittedChangeList> changes) { ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { @@ -60,20 +62,6 @@ public class LoadedRevisionsCache implements Disposable { } }); } - - @Override - public void changesCleared() { - } - - @Override - public void presentationChanged() { - } - - public void incomingChangesUpdated(@Nullable final List<CommittedChangeList> receivedChanges) { - } - - public void refreshErrorStatusChanged(@Nullable final VcsException lastError) { - } }); Disposer.register(myProject, this); setRefreshTime(0); @@ -90,18 +78,20 @@ public class LoadedRevisionsCache implements Disposable { myRefreshTime = refreshTime; } } - - private void debugInfo(final List<CommittedChangeList> data, final boolean consistentWithPrevious, final Bunch bindTo) { + + private static void debugInfo(@NotNull List<CommittedChangeList> data, final boolean consistentWithPrevious, final Bunch bindTo) { LOG.debug(">>> cache internal >>> consistent: " + consistentWithPrevious + " bindTo: " + bindTo + " oldest list: " + data.get(data.size() - 1).getNumber() + ", youngest list: " + data.get(0).getNumber()); } public void dispose() { + // TODO: Seems that dispose could be removed as connection will be disposed anyway on project dispose and clearing map is not necessary myConnection.disconnect(); myMap.clear(); } - private List<List<CommittedChangeList>> split(final List<CommittedChangeList> list, final int size) { + @NotNull + private static List<List<CommittedChangeList>> split(final List<CommittedChangeList> list, final int size) { final int listSize = list.size(); if (listSize < size) { return Collections.singletonList(list); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java index 83642894711e..4712a080ad36 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java @@ -48,7 +48,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.SvnVcs; -import org.jetbrains.idea.svn.actions.ConfigureBranchesAction; +import org.jetbrains.idea.svn.branchConfig.ConfigureBranchesAction; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.jetbrains.idea.svn.status.Status; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java index 007df92a403b..e636c9c0a8ef 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java @@ -22,10 +22,10 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Throwable2Computable; import com.intellij.openapi.vcs.RepositoryLocation; import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.actions.VcsContextFactory; import com.intellij.openapi.vcs.history.VcsFileRevision; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vcs.impl.ContentRevisionCache; +import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnBundle; @@ -37,7 +37,6 @@ import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.IOException; -import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -55,7 +54,6 @@ public class SvnFileRevision implements VcsFileRevision { private final SVNRevision myRevision; private final String myCopyFromPath; private final List<SvnFileRevision> myMergeSources; - private final Charset myCharset; public SvnFileRevision(SvnVcs vcs, SVNRevision pegRevision, @@ -64,8 +62,7 @@ public class SvnFileRevision implements VcsFileRevision { String author, Date date, String commitMessage, - String copyFromPath, Charset charset) { - myCharset = charset; + String copyFromPath) { myRevisionNumber = new SvnRevisionNumber(revision); myPegRevision = pegRevision; myRevision = revision; @@ -82,8 +79,7 @@ public class SvnFileRevision implements VcsFileRevision { SVNRevision pegRevision, LogEntry logEntry, String url, - String copyFromPath, Charset charset) { - myCharset = charset; + String copyFromPath) { final SVNRevision revision = SVNRevision.create(logEntry.getRevision()); myRevisionNumber = new SvnRevisionNumber(revision); myPegRevision = pegRevision; @@ -155,30 +151,37 @@ public class SvnFileRevision implements VcsFileRevision { else { loader.run(); } - if (loader.getException() == null) { + + VcsException exception = loader.getException(); + if (exception == null) { final byte[] contents = loader.getContents(); ContentRevisionCache.checkContentsSize(myURL, contents.length); return contents; } else { - final VcsException vcsException = loader.getException(); - LOG.info("Failed to load file '" + myURL + "' content at revision: " + myRevision + "\n" + vcsException.getMessage(), vcsException); - throw vcsException; + LOG.info("Failed to load file '" + myURL + "' content at revision: " + myRevision + "\n" + exception.getMessage(), exception); + throw exception; } } public byte[] getContent() throws IOException, VcsException { - return ContentRevisionCache.getOrLoadAsBytes(myVCS.getProject(), VcsContextFactory.SERVICE.getInstance() - .createFilePathOnNonLocal(myURL, false), - getRevisionNumber(), myVCS.getKeyInstanceMethod(), ContentRevisionCache.UniqueType.REMOTE_CONTENT, - new Throwable2Computable<byte[], VcsException, IOException>() { - @Override - public byte[] compute() throws VcsException, IOException { - byte[] bytes = loadContent(); - return bytes; - //return SvnUtil.decode(myCharset, bytes); - } - }); + byte[] result; + + if (SVNRevision.HEAD.equals(myRevision)) { + result = loadContent(); + } + else { + result = ContentRevisionCache.getOrLoadAsBytes(myVCS.getProject(), VcsUtil.getFilePathOnNonLocal(myURL, false), getRevisionNumber(), + myVCS.getKeyInstanceMethod(), ContentRevisionCache.UniqueType.REMOTE_CONTENT, + new Throwable2Computable<byte[], VcsException, IOException>() { + @Override + public byte[] compute() throws VcsException, IOException { + return loadContent(); + } + }); + } + + return result; } public String getCopyFromPath() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java index b23b57772535..2ff19fcc56e6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java @@ -614,7 +614,7 @@ public class SvnHistoryProvider final SVNURL url = myRepositoryRoot.appendPath(myLastPath, true); // final SVNURL url = entryPath != null ? myRepositoryRoot.appendPath(entryPath.getPath(), true) : // myRepositoryRoot.appendPath(myLastPathCorrector.getBefore(), false); - return new SvnFileRevision(myVcs, myPegRevision, rev, url.toString(), author, date, message, copyPath, myCharset); + return new SvnFileRevision(myVcs, myPegRevision, rev, url.toString(), author, date, message, copyPath); } } @@ -633,7 +633,7 @@ public class SvnHistoryProvider throws SVNException { final SVNURL url = entryPath == null ? myRepositoryRoot.appendPath(myLastPathCorrector.getBefore(), false) : myRepositoryRoot.appendPath(entryPath.getPath(), true); - return new SvnFileRevision(myVcs, SVNRevision.UNDEFINED, logEntry, url.toString(), copyPath, null); + return new SvnFileRevision(myVcs, SVNRevision.UNDEFINED, logEntry, url.toString(), copyPath); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeInfoRootPanelManual.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeInfoRootPanelManual.java index c6ed3c59a5c7..d4b48281f7ca 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeInfoRootPanelManual.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeInfoRootPanelManual.java @@ -24,10 +24,10 @@ import com.intellij.util.NullableFunction; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.SvnBranchMapperManager; +import org.jetbrains.idea.svn.branchConfig.SvnBranchMapperManager; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnUtil; -import org.jetbrains.idea.svn.actions.SelectBranchPopup; +import org.jetbrains.idea.svn.branchConfig.SelectBranchPopup; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.dialogs.WCInfoWithBranches; import org.jetbrains.idea.svn.integrate.IntegratedSelectedOptionsDialog; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/WcInfoLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/WcInfoLoader.java index e0ab6ff02ae5..bbac377776b8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/WcInfoLoader.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/WcInfoLoader.java @@ -23,10 +23,11 @@ import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.dialogs.WCInfo; import org.jetbrains.idea.svn.dialogs.WCInfoWithBranches; -import org.jetbrains.idea.svn.integrate.SvnBranchItem; +import org.jetbrains.idea.svn.branchConfig.SvnBranchItem; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import java.io.File; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/info/Info.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/Info.java index 96dbdbbcbc99..71fb0a9ec51f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/info/Info.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/Info.java @@ -35,6 +35,8 @@ import java.util.Date; */ public class Info extends BaseNodeDescription { + public static final String SCHEDULE_ADD = "add"; + private final File myFile; private final String myPath; private final SVNURL myURL; @@ -49,10 +51,10 @@ public class Info extends BaseNodeDescription { private final String mySchedule; private final SVNURL myCopyFromURL; private final SVNRevision myCopyFromRevision; - private final File myConflictOldFile; - private final File myConflictNewFile; - private final File myConflictWrkFile; - private final File myPropConflictFile; + @Nullable private final File myConflictOldFile; + @Nullable private final File myConflictNewFile; + @Nullable private final File myConflictWrkFile; + @Nullable private final File myPropConflictFile; private final Depth myDepth; @Nullable private final TreeConflictDescription myTreeConflict; @@ -69,8 +71,8 @@ public class Info extends BaseNodeDescription { result = new Info(info.getFile(), info.getURL(), info.getRepositoryRootURL(), info.getRevision().getNumber(), NodeKind.from(info.getKind()), info.getRepositoryUUID(), info.getCommittedRevision().getNumber(), toString(info.getCommittedDate()), info.getAuthor(), - info.getSchedule(), info.getCopyFromURL(), info.getCopyFromRevision().getNumber(), getPath(info.getConflictOldFile()), - getPath(info.getConflictNewFile()), getPath(info.getConflictWrkFile()), getPath(info.getPropConflictFile()), + info.getSchedule(), info.getCopyFromURL(), info.getCopyFromRevision().getNumber(), getName(info.getConflictOldFile()), + getName(info.getConflictNewFile()), getName(info.getConflictWrkFile()), getName(info.getPropConflictFile()), Lock.create(info.getLock()), Depth.from(info.getDepth()), TreeConflictDescription.create(info.getTreeConflict())); } @@ -89,10 +91,10 @@ public class Info extends BaseNodeDescription { String schedule, SVNURL copyFromURL, long copyFromRevision, - String conflictOld, - String conflictNew, - String conflictWorking, - String propRejectFile, + @Nullable String conflictOldFileName, + @Nullable String conflictNewFileName, + @Nullable String conflictWorkingFileName, + @Nullable String propRejectFileName, @Nullable Lock lock, Depth depth, @Nullable TreeConflictDescription treeConflict) { @@ -115,10 +117,10 @@ public class Info extends BaseNodeDescription { myLock = lock; myTreeConflict = treeConflict; - myConflictOldFile = resolveConflictFile(file, conflictOld); - myConflictNewFile = resolveConflictFile(file, conflictNew); - myConflictWrkFile = resolveConflictFile(file, conflictWorking); - myPropConflictFile = resolveConflictFile(file, propRejectFile); + myConflictOldFile = resolveConflictFile(file, conflictOldFileName); + myConflictNewFile = resolveConflictFile(file, conflictNewFileName); + myConflictWrkFile = resolveConflictFile(file, conflictWorkingFileName); + myPropConflictFile = resolveConflictFile(file, propRejectFileName); myIsRemote = false; myDepth = depth; @@ -175,14 +177,17 @@ public class Info extends BaseNodeDescription { return myCommittedRevision; } + @Nullable public File getConflictNewFile() { return myConflictNewFile; } + @Nullable public File getConflictOldFile() { return myConflictOldFile; } + @Nullable public File getConflictWrkFile() { return myConflictWrkFile; } @@ -222,6 +227,7 @@ public class Info extends BaseNodeDescription { return myPath; } + @Nullable public File getPropConflictFile() { return myPropConflictFile; } @@ -256,8 +262,8 @@ public class Info extends BaseNodeDescription { } @Nullable - private static String getPath(@Nullable File file) { - return file != null ? file.getPath() : null; + private static String getName(@Nullable File file) { + return file != null ? file.getName() : null; } @Nullable diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java index 3b2184c22484..7ff6e71ab75a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java @@ -32,6 +32,7 @@ import com.intellij.util.PlatformIcons; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.branchConfig.SvnBranchMapperManager; import org.jetbrains.idea.svn.info.Info; import org.tmatesoft.svn.core.SVNURL; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SourceUrlCorrectionTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SourceUrlCorrectionTask.java index 39d51de62943..99d4696ede3f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SourceUrlCorrectionTask.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SourceUrlCorrectionTask.java @@ -18,7 +18,7 @@ package org.jetbrains.idea.svn.integrate; import com.intellij.util.continuation.ContinuationContext; import com.intellij.util.continuation.Where; import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.svn.SvnBranchConfigurationManager; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager; import org.jetbrains.idea.svn.dialogs.MergeContext; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java index e07fac011c9e..2ccd2242db10 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java @@ -23,7 +23,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.SvnVcs; -import org.jetbrains.idea.svn.actions.SelectBranchPopup; +import org.jetbrains.idea.svn.branchConfig.SelectBranchPopup; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java index 5dd6f24b10ba..0dd27d442ae5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java @@ -19,7 +19,9 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; +import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.Change; @@ -28,6 +30,7 @@ import com.intellij.openapi.vcs.changes.InvokeAfterUpdateMode; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; import com.intellij.openapi.vcs.changes.ui.CommitChangeListDialog; import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx; +import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.openapi.vcs.update.*; import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; @@ -330,18 +333,37 @@ public class SvnIntegrateChangesTask extends Task.Backgroundable { }); } - final SvnChangeProvider provider = new SvnChangeProvider(myVcs); - final GatheringChangelistBuilder clb = new GatheringChangelistBuilder(myVcs, myAccomulatedFiles); - try { - provider.getChanges(dirtyScope, clb, ProgressManager.getInstance().getProgressIndicator(), null); - } catch (VcsException e) { - Messages.showErrorDialog(SvnBundle.message("action.Subversion.integrate.changes.error.unable.to.collect.changes.text", - e.getMessage()), myTitle); - return; - } + new Task.Backgroundable(myVcs.getProject(), + SvnBundle.message("action.Subversion.integrate.changes.collecting.changes.to.commit.task.title")) { - if (! clb.getChanges().isEmpty()) { - CommitChangeListDialog.commitAlienChanges(myProject, clb.getChanges(), myVcs, myMerger.getComment(), myMerger.getComment()); - } + private final GatheringChangelistBuilder changesBuilder = new GatheringChangelistBuilder(myVcs, myAccomulatedFiles); + private final Ref<String> caughtError = new Ref<String>(); + + @Override + public void run(@NotNull ProgressIndicator indicator) { + indicator.setIndeterminate(true); + if (!myVcs.getProject().isDisposed()) { + final SvnChangeProvider provider = new SvnChangeProvider(myVcs); + + try { + provider.getChanges(dirtyScope, changesBuilder, indicator, null); + } + catch (VcsException e) { + caughtError.set(SvnBundle.message("action.Subversion.integrate.changes.error.unable.to.collect.changes.text", e.getMessage())); + } + } + } + + @Override + public void onSuccess() { + if (!caughtError.isNull()) { + VcsBalloonProblemNotifier.showOverVersionControlView(myVcs.getProject(), caughtError.get(), MessageType.ERROR); + } + else if (!changesBuilder.getChanges().isEmpty()) { + CommitChangeListDialog + .commitAlienChanges(myProject, changesBuilder.getChanges(), myVcs, myMerger.getComment(), myMerger.getComment()); + } + } + }.queue(); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java index 701bb2575001..f69aac4a4133 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java @@ -19,11 +19,15 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vcs.VcsException; import com.intellij.util.containers.MultiMap; +import org.jetbrains.idea.svn.SvnPropertyKeys; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.history.SvnChangeList; import org.jetbrains.idea.svn.info.Info; import org.jetbrains.idea.svn.properties.PropertyValue; -import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNMergeRange; +import org.tmatesoft.svn.core.SVNMergeRangeList; +import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.util.SVNMergeInfoUtil; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import org.tmatesoft.svn.core.wc.SVNRevision; @@ -209,7 +213,8 @@ public class BranchInfo { SvnTarget target = SvnTarget.fromURL(branchUrl); try { - mergeinfoProperty = myVcs.getFactory(target).createPropertyClient().getProperty(target, SVNProperty.MERGE_INFO, false, SVNRevision.create(targetRevision)); + mergeinfoProperty = myVcs.getFactory(target).createPropertyClient().getProperty(target, SvnPropertyKeys.MERGE_INFO, false, + SVNRevision.create(targetRevision)); } catch (VcsException e) { LOG.info(e); @@ -283,13 +288,13 @@ public class BranchInfo { // look in WC SvnTarget target = SvnTarget.fromFile(pathFile, SVNRevision.WORKING); mergeinfoProperty = - myVcs.getFactory(target).createPropertyClient().getProperty(target, SVNProperty.MERGE_INFO, false, SVNRevision.WORKING); + myVcs.getFactory(target).createPropertyClient().getProperty(target, SvnPropertyKeys.MERGE_INFO, false, SVNRevision.WORKING); } else { // in repo myMixedRevisionsFound = true; SvnTarget target = SvnTarget.fromURL(svnInfo.getURL()); mergeinfoProperty = myVcs.getFactory(target).createPropertyClient() - .getProperty(target, SVNProperty.MERGE_INFO, false, SVNRevision.create(targetRevisionCorrected)); + .getProperty(target, SvnPropertyKeys.MERGE_INFO, false, SVNRevision.create(targetRevisionCorrected)); } } catch (VcsException e) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java index 225bc6ad0396..b17d3317a801 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java @@ -21,12 +21,16 @@ import com.intellij.openapi.vcs.AreaMap; import com.intellij.openapi.vcs.VcsException; import com.intellij.util.PairProcessor; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnPropertyKeys; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.dialogs.MergeContext; import org.jetbrains.idea.svn.properties.PropertyConsumer; import org.jetbrains.idea.svn.properties.PropertyData; import org.jetbrains.idea.svn.properties.PropertyValue; -import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNMergeRange; +import org.tmatesoft.svn.core.SVNMergeRangeList; +import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.util.SVNMergeInfoUtil; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import org.tmatesoft.svn.core.wc.SVNRevision; @@ -83,7 +87,7 @@ public class OneRecursiveShotMergeInfoWorker implements MergeInfoWorker { File path = new File(myMergeContext.getWcInfo().getPath()); myMergeContext.getVcs().getFactory(path).createPropertyClient() - .getProperty(SvnTarget.fromFile(path), SVNProperty.MERGE_INFO, SVNRevision.WORKING, depth, handler); + .getProperty(SvnTarget.fromFile(path), SvnPropertyKeys.MERGE_INFO, SVNRevision.WORKING, depth, handler); } public SvnMergeInfoCache.MergeCheckResult isMerged(final String relativeToRepoURLPath, final long revisionNumber) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java index e053776d14ce..f00c4bd7341d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java @@ -1,5 +1,7 @@ package org.jetbrains.idea.svn.properties; +import com.intellij.openapi.diagnostic.Attachment; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.vcs.VcsException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -30,6 +32,8 @@ import java.util.Map; */ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { + private static final Logger LOG = Logger.getInstance(CmdPropertyClient.class); + @Nullable @Override public PropertyValue getProperty(@NotNull SvnTarget target, @@ -57,7 +61,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { parameters.add("--xml"); CommandExecutor command = execute(myVcs, target, SvnCommandName.propget, parameters, null); - PropertyData data = parseSingleProperty(target, command.getOutput()); + PropertyData data = parseSingleProperty(target, command); return data != null ? data.getValue() : null; } @@ -74,7 +78,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { fillListParameters(target, revision, depth, parameters, false); CommandExecutor command = execute(myVcs, target, SvnCommandName.propget, parameters, null); - parseOutput(target, command.getOutput(), handler); + parseOutput(target, command, handler); } @Override @@ -86,7 +90,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { fillListParameters(target, revision, depth, parameters, true); CommandExecutor command = execute(myVcs, target, SvnCommandName.proplist, parameters, null); - parseOutput(target, command.getOutput(), handler); + parseOutput(target, command, handler); } @Override @@ -183,7 +187,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { } @Nullable - private PropertyData parseSingleProperty(SvnTarget target, String output) throws VcsException { + private PropertyData parseSingleProperty(SvnTarget target, @NotNull CommandExecutor command) throws VcsException { final PropertyData[] data = new PropertyData[1]; PropertyConsumer handler = new PropertyConsumer() { @Override @@ -202,14 +206,14 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { } }; - parseOutput(target, output, handler); + parseOutput(target, command, handler); return data[0]; } - private static void parseOutput(SvnTarget target, String output, PropertyConsumer handler) throws VcsException { + private static void parseOutput(SvnTarget target, @NotNull CommandExecutor command, PropertyConsumer handler) throws VcsException { try { - Properties properties = CommandUtil.parse(output, Properties.class); + Properties properties = CommandUtil.parse(command.getOutput(), Properties.class); if (properties != null) { for (Target childInfo : properties.targets) { @@ -227,6 +231,8 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { } } catch (JAXBException e) { + LOG.error("Could not parse properties. Command: " + command.getCommandText() + ", Warning: " + command.getErrorOutput(), + new Attachment("output.xml", command.getOutput())); throw new VcsException(e); } catch (SVNException e) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java index 7b09461b3766..16904b673b5f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java @@ -37,8 +37,10 @@ import org.jetbrains.idea.svn.info.Info; import org.jetbrains.idea.svn.properties.PropertiesMap; import org.jetbrains.idea.svn.properties.PropertyConsumer; import org.jetbrains.idea.svn.properties.PropertyData; -import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.core.SVNErrorCode; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; @@ -312,7 +314,7 @@ public class SvnRollbackEnvironment extends DefaultRollbackEnvironment { if (info.isFile()) { doRevert(file, false); } else { - if (SVNProperty.SCHEDULE_ADD.equals(info.getSchedule())) { + if (Info.SCHEDULE_ADD.equals(info.getSchedule())) { doRevert(file, true); } else { boolean is17OrGreater = is17OrGreaterCopy(file, info); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java index 4030c83005ea..8100d73da220 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java @@ -103,6 +103,7 @@ public class CmdStatusClient extends BaseSvnClient implements StatusClient { // so it does not contain any <entry> element and current parsing logic returns null PortableStatus status = new PortableStatus(); + status.setFile(path); status.setPath(path.getAbsolutePath()); status.setContentsStatus(StatusType.STATUS_NORMAL); status.setInfoGetter(new Getter<Info>() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdateIntegrateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdateIntegrateEnvironment.java index b4e788c75260..ef3529aec092 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdateIntegrateEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdateIntegrateEnvironment.java @@ -46,7 +46,6 @@ public abstract class AbstractSvnUpdateIntegrateEnvironment implements UpdateEnv protected final SvnVcs myVcs; private final ProjectLevelVcsManager myVcsManager; @NonNls public static final String REPLACED_ID = "replaced"; - @NonNls public static final String EXTERNAL_ID = "external"; protected AbstractSvnUpdateIntegrateEnvironment(final SvnVcs vcs) { myVcs = vcs; @@ -145,6 +144,7 @@ public abstract class AbstractSvnUpdateIntegrateEnvironment implements UpdateEnv } public void onRefreshFilesCompleted() { + // TODO: why do we need to mark all roots as dirty here??? dirtyRoots(); for (Runnable groupWorker : myGroupWorkers) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java index 554b2c29bc48..41bfd61fded1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java @@ -89,8 +89,6 @@ public class SvnUpdateEnvironment extends AbstractSvnUpdateIntegrateEnvironment rev = updateClient.doUpdate(root, updateTo, configuration.getUpdateDepth(), configuration.isForceUpdate(), false); } - myPostUpdateFiles.setRevisions(root.getAbsolutePath(), myVcs, new SvnRevisionNumber(SVNRevision.create(rev))); - return rev; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateRootOptionsPanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateRootOptionsPanel.java index d232fdc3037f..9103c845ae75 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateRootOptionsPanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateRootOptionsPanel.java @@ -22,7 +22,7 @@ import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.vcs.FilePath; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; -import org.jetbrains.idea.svn.actions.SelectBranchPopup; +import org.jetbrains.idea.svn.branchConfig.SelectBranchPopup; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.dialogs.SelectLocationDialog; import org.jetbrains.idea.svn.history.SvnChangeList; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java index fc552dbd1655..aff94e123a31 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java @@ -16,10 +16,13 @@ package org.jetbrains.idea.svn.update; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vcs.update.FileGroup; import com.intellij.openapi.vcs.update.UpdatedFiles; import com.intellij.openapi.wm.StatusBar; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.Stack; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnFileUrlMapping; @@ -32,11 +35,12 @@ import org.jetbrains.idea.svn.status.StatusType; import org.tmatesoft.svn.core.SVNCancelException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.wc.SVNErrorManager; -import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.util.SVNLogType; import java.io.File; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -49,6 +53,10 @@ public class UpdateEventHandler implements ProgressTracker { private final SvnVcs myVCS; @Nullable private final SvnUpdateContext mySequentialUpdatesContext; private final Map<File, SVNURL> myUrlToCheckForSwitch; + // pair.first - group id, pair.second - file path + // Stack is used to correctly handle cases when updates of externals occur during ordinary update, because these inner updates could have + // its own revisions. + private final Stack<List<Pair<String, String>>> myFilesWaitingForRevision; protected String myText; protected String myText2; @@ -60,6 +68,11 @@ public class UpdateEventHandler implements ProgressTracker { mySequentialUpdatesContext = sequentialUpdatesContext; myExternalsCount = 1; myUrlToCheckForSwitch = new HashMap<File, SVNURL>(); + myFilesWaitingForRevision = ContainerUtil.newStack(); + // It is more suitable to make this push while handling UPDATE_NONE event - for command line like "svn update <folder>" this event will + // be fired when update of <folder> is started. But it's not clear if this event won't be fired in other cases by SVNKit. So currently + // first push is made here. If further we want to support commands like "svn update <folder1> <folder2>" this logic should be revised. + myFilesWaitingForRevision.push(ContainerUtil.<Pair<String, String>>newArrayList()); } public void addToSwitch(final File file, final SVNURL url) { @@ -153,13 +166,8 @@ public class UpdateEventHandler implements ProgressTracker { if (mySequentialUpdatesContext != null) { mySequentialUpdatesContext.registerExternalRootBeingUpdated(event.getFile()); } + myFilesWaitingForRevision.push(ContainerUtil.<Pair<String, String>>newArrayList()); myExternalsCount++; - if (myUpdatedFiles.getGroupById(AbstractSvnUpdateIntegrateEnvironment.EXTERNAL_ID) == null) { - myUpdatedFiles.registerGroup(new FileGroup(SvnBundle.message("status.group.name.externals"), - SvnBundle.message("status.group.name.externals"), - false, AbstractSvnUpdateIntegrateEnvironment.EXTERNAL_ID, true)); - } - addFileToGroup(AbstractSvnUpdateIntegrateEnvironment.EXTERNAL_ID, event); myText = SvnBundle.message("progress.text.updating.external.location", event.getFile().getAbsolutePath()); } else if (event.getAction() == EventAction.RESTORE) { @@ -168,6 +176,7 @@ public class UpdateEventHandler implements ProgressTracker { } else if (event.getAction() == EventAction.UPDATE_COMPLETED && event.getRevision() >= 0) { possiblySwitched(event); + setRevisionForWaitingFiles(event.getRevision()); myExternalsCount--; myText2 = SvnBundle.message("progres.text2.updated.to.revision", event.getRevision()); if (myExternalsCount == 0) { @@ -218,12 +227,22 @@ public class UpdateEventHandler implements ProgressTracker { protected void addFileToGroup(final String id, final ProgressEvent event) { final FileGroup fileGroup = myUpdatedFiles.getGroupById(id); final String path = event.getFile().getAbsolutePath(); - fileGroup.add(path, SvnVcs.getKey(), new SvnRevisionNumber(SVNRevision.create(event.getRevision()))); + myFilesWaitingForRevision.peek().add(Pair.create(id, path)); if (event.getErrorMessage() != null) { fileGroup.addError(path, event.getErrorMessage().getMessage()); } } + private void setRevisionForWaitingFiles(long revisionNumber) { + SvnRevisionNumber revision = new SvnRevisionNumber(SVNRevision.create(revisionNumber)); + + for (Pair<String, String> pair : myFilesWaitingForRevision.pop()) { + FileGroup fileGroup = myUpdatedFiles.getGroupById(pair.getFirst()); + + fileGroup.add(pair.getSecond(), SvnVcs.getKey(), revision); + } + } + public void checkCancelled() throws SVNCancelException { if (myProgressIndicator != null) { myProgressIndicator.checkCanceled(); diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java b/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java index 17ae6b5ce551..364906460fe6 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.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. @@ -17,10 +17,7 @@ package org.jetbrains.idea; import com.intellij.execution.process.ProcessOutput; import com.intellij.ide.startup.impl.StartupManagerImpl; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.PluginPathManager; @@ -506,7 +503,7 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase { } return null; } - }, "test", new Presentation(), null, 0)); + }, "test", new Presentation(), ActionManager.getInstance(), 0)); final ChangeListManager clManager = ChangeListManager.getInstance(project); clManager.ensureUpToDate(false); diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAnnotationIsClosedTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAnnotationIsClosedTest.java index f29b5d0bc45b..73000a14880e 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAnnotationIsClosedTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAnnotationIsClosedTest.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. @@ -15,10 +15,7 @@ */ package org.jetbrains.idea.svn; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.VcsConfiguration; import com.intellij.openapi.vcs.VcsException; @@ -144,7 +141,7 @@ public class SvnAnnotationIsClosedTest extends Svn17TestCase { } return null; } - }, "test", new Presentation(), null, 0)); + }, "test", new Presentation(), ActionManager.getInstance(), 0)); myChangeListManager.ensureUpToDate(false); myChangeListManager.ensureUpToDate(false); // wait for after-events like annotations recalculation @@ -191,7 +188,7 @@ public class SvnAnnotationIsClosedTest extends Svn17TestCase { } return null; } - }, "test", new Presentation(), null, 0)); + }, "test", new Presentation(), ActionManager.getInstance(), 0)); myChangeListManager.ensureUpToDate(false); myChangeListManager.ensureUpToDate(false); // wait for after-events like annotations recalculation diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java index 6853141b8d45..a663e13d3b29 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java @@ -36,9 +36,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.SvnTestCase; import org.jetbrains.idea.svn.branchConfig.InfoReliability; import org.jetbrains.idea.svn.branchConfig.InfoStorage; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.dialogs.*; -import org.jetbrains.idea.svn.integrate.SvnBranchItem; +import org.jetbrains.idea.svn.branchConfig.SvnBranchItem; import org.jetbrains.idea.svn.mergeinfo.MergeChecker; import org.junit.Before; import org.junit.Test; diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/pivotal/PivotalTrackerRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/pivotal/PivotalTrackerRepository.java index 559247356bcb..f327e0ad968a 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/pivotal/PivotalTrackerRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/pivotal/PivotalTrackerRepository.java @@ -386,6 +386,6 @@ public class PivotalTrackerRepository extends BaseRepositoryImpl { @Override protected int getFeatures() { - return super.getFeatures() | BASIC_HTTP_AUTHORIZATION; + return super.getFeatures() | BASIC_HTTP_AUTHORIZATION | STATE_UPDATING; } } diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java index d252c93bcb34..f671b1a19fc6 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java @@ -155,8 +155,7 @@ public abstract class AbstractTerminalRunner<T extends Process> { return new CloseAction(defaultExecutor, myDescriptor, myProject); } - - protected void showConsole(Executor defaultExecutor, RunContentDescriptor myDescriptor, final Component toFocus) { + protected void showConsole(Executor defaultExecutor, @NotNull RunContentDescriptor myDescriptor, final Component toFocus) { // Show in run toolwindow ExecutionManager.getInstance(myProject).getContentManager().showRunContent(defaultExecutor, myDescriptor); diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java index 7a9a7a1e428a..6040e6c6c9ad 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java @@ -1,9 +1,25 @@ +/* + * 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 org.jetbrains.plugins.terminal; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowFactory; +import org.jetbrains.annotations.NotNull; /** * @author traff @@ -12,7 +28,7 @@ public class TerminalToolWindowFactory implements ToolWindowFactory, DumbAware { public static final String TOOL_WINDOW_ID = "Terminal"; @Override - public void createToolWindowContent(Project project, ToolWindow toolWindow) { + public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) { TerminalView terminalView = TerminalView.getInstance(project); terminalView.initTerminal(toolWindow); } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java index ce26a9b44264..49766b110bfa 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java @@ -25,6 +25,8 @@ import com.intellij.execution.executors.DefaultRunExecutor; import com.intellij.execution.process.ProcessAdapter; import com.intellij.execution.process.ProcessEvent; import com.intellij.execution.runners.ExecutionEnvironment; +import com.intellij.execution.runners.ExecutionEnvironmentBuilder; +import com.intellij.execution.runners.ExecutionUtil; import com.intellij.execution.runners.ProgramRunner; import com.intellij.lang.properties.PropertiesFileType; import com.intellij.lang.properties.PropertiesReferenceManager; @@ -312,12 +314,9 @@ public final class PreviewFormAction extends AnAction{ } try { - final RunProfile profile = new MyRunProfile(module, parameters, tempPath, - UIDesignerBundle.message("progress.preview.started", formFile.getPresentableUrl())); - ProgramRunner defaultRunner = RunnerRegistry.getInstance().getRunner(DefaultRunExecutor.EXECUTOR_ID, profile); - LOG.assertTrue(defaultRunner != null); - Executor executor = DefaultRunExecutor.getRunExecutorInstance(); - defaultRunner.execute(new ExecutionEnvironment(profile, executor, module.getProject(), null)); + RunProfile profile = new MyRunProfile(module, parameters, tempPath, + UIDesignerBundle.message("progress.preview.started", formFile.getPresentableUrl())); + ExecutionEnvironmentBuilder.create(module.getProject(), DefaultRunExecutor.getRunExecutorInstance(), profile).buildAndExecute(); } catch (ExecutionException e) { Messages.showErrorDialog( diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/CreateSnapShotAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/CreateSnapShotAction.java index 284ce42ec867..6ecb61920100 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/CreateSnapShotAction.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/CreateSnapShotAction.java @@ -16,12 +16,14 @@ package com.intellij.uiDesigner.snapShooter; -import com.intellij.execution.*; +import com.intellij.execution.ExecutionException; +import com.intellij.execution.RunManager; +import com.intellij.execution.RunnerAndConfigurationSettings; import com.intellij.execution.application.ApplicationConfiguration; import com.intellij.execution.application.ApplicationConfigurationType; import com.intellij.execution.executors.DefaultRunExecutor; -import com.intellij.execution.runners.ExecutionEnvironment; -import com.intellij.execution.runners.ProgramRunner; +import com.intellij.execution.runners.ExecutionEnvironmentBuilder; +import com.intellij.execution.runners.ExecutionUtil; import com.intellij.execution.util.JreVersionDetector; import com.intellij.icons.AllIcons; import com.intellij.ide.IdeView; @@ -168,13 +170,9 @@ public class CreateSnapShotAction extends AnAction { }); } }); - + try { - final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(DefaultRunExecutor.EXECUTOR_ID, appConfig); - LOG.assertTrue(runner != null, "Runner MUST not be null!"); - Executor executor = DefaultRunExecutor.getRunExecutorInstance(); - runner.execute( - new ExecutionEnvironment(executor, runner, snapshotConfiguration, project)); + ExecutionEnvironmentBuilder.create(DefaultRunExecutor.getRunExecutorInstance(), snapshotConfiguration).buildAndExecute(); } catch (ExecutionException ex) { Messages.showMessageDialog(project, UIDesignerBundle.message("snapshot.run.error", ex.getMessage()), diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java index 6406db9f23b8..50bd5c5720ed 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java @@ -65,12 +65,14 @@ public class XsltCommandLineState extends CommandLineState { private UserDataHolder myExtensionData; @SuppressWarnings({ "RawUseOfParameterizedType" }) - public XsltCommandLineState(XsltRunConfiguration xsltRunConfiguration, ExecutionEnvironment env) { - super(env); + public XsltCommandLineState(XsltRunConfiguration xsltRunConfiguration, ExecutionEnvironment environment) { + super(environment); + myXsltRunConfiguration = xsltRunConfiguration; - myIsDebugger = "Debug".equals(env.getRunnerId()); + myIsDebugger = "Debug".equals(environment.getRunner().getRunnerId()); } + @Override @NotNull protected OSProcessHandler startProcess() throws ExecutionException { final OSProcessHandler osProcessHandler = createJavaParameters().createOSProcessHandler(); @@ -204,12 +206,15 @@ public class XsltCommandLineState extends CommandLineState { private class MyProcessAdapter extends ProcessAdapter { + @Override public void processTerminated(final ProcessEvent event) { if (myXsltRunConfiguration.isSaveToFile()) { Runnable runnable = new Runnable() { + @Override public void run() { Runnable runnable = new Runnable() { + @Override public void run() { if (event.getExitCode() == 0) { if (myXsltRunConfiguration.myOpenInBrowser) { |