diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/VariablesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/VariablesPanel.java index dc80f8b139af..1bda597586e8 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/VariablesPanel.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/VariablesPanel.java @@ -64,7 +64,9 @@ public class VariablesPanel extends DebuggerTreePanel implements DataProvider { registerDisposable(myXTree); myCards.add(myXTree.getTree(), X_TREE); - add(ScrollPaneFactory.createScrollPane(myCards), BorderLayout.CENTER); + JScrollPane pane = ScrollPaneFactory.createScrollPane(myCards); + pane.getVerticalScrollBar().setUnitIncrement(10); + add(pane, BorderLayout.CENTER); registerDisposable(DebuggerAction.installEditAction(frameTree, DebuggerActions.EDIT_NODE_SOURCE)); overrideShortcut(frameTree, DebuggerActions.COPY_VALUE, CommonShortcuts.getCopy()); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeCastFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeCastFix.java index 68e3554ce314..0ccad5cadf48 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeCastFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeCastFix.java @@ -86,9 +86,10 @@ public class AddTypeCastFix extends LocalQuickFixAndIntentionActionOnPsiElement PsiElement expression = PsiUtil.deparenthesizeExpression(original); if (expression == null) return null; - PsiElementFactory factory = JavaPsiFacade.getInstance(original.getProject()).getElementFactory(); + if (type.equals(PsiType.NULL)) return null; if (type instanceof PsiEllipsisType) type = ((PsiEllipsisType)type).toArrayType(); String text = "(" + type.getCanonicalText(false) + ")value"; + PsiElementFactory factory = JavaPsiFacade.getInstance(original.getProject()).getElementFactory(); PsiTypeCastExpression typeCast = (PsiTypeCastExpression)factory.createExpressionFromText(text, original); typeCast = (PsiTypeCastExpression)CodeStyleManager.getInstance(project).reformat(typeCast); diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java index 5653701d616f..0a831d2d8efb 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.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. @@ -13,11 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/** - * created at Sep 17, 2001 - * @author Jeka - */ package com.intellij.refactoring.changeSignature; import com.intellij.openapi.application.ApplicationManager; @@ -36,6 +31,7 @@ import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.util.IncorrectOperationException; import com.intellij.util.VisibilityUtil; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashSet; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; @@ -43,6 +39,12 @@ import org.jetbrains.annotations.Nullable; import java.util.*; +import static com.intellij.util.ObjectUtils.assertNotNull; + +/** + * @author Jeka + * @since Sep 17, 2001 + */ public class ChangeSignatureProcessor extends ChangeSignatureProcessorBase { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.ChangeSignatureProcessor"); @@ -99,18 +101,22 @@ public class ChangeSignatureProcessor extends ChangeSignatureProcessorBase { ThrownExceptionInfo[] thrownExceptions, Set propagateParametersMethods, Set propagateExceptionsMethods) { - Set myPropagateParametersMethods = - propagateParametersMethods != null ? propagateParametersMethods : new HashSet(); - Set myPropagateExceptionsMethods = - propagateExceptionsMethods != null ? propagateExceptionsMethods : new HashSet(); - LOG.assertTrue(method.isValid()); + + if (propagateParametersMethods == null) { + propagateParametersMethods = ContainerUtil.newHashSet(); + } + + if (propagateExceptionsMethods == null) { + propagateExceptionsMethods = ContainerUtil.newHashSet(); + } + if (newVisibility == null) { newVisibility = VisibilityUtil.getVisibilityModifier(method.getModifierList()); } return new JavaChangeInfoImpl(newVisibility, method, newName, newType, parameterInfo, thrownExceptions, generateDelegate, - myPropagateParametersMethods, myPropagateExceptionsMethods); + propagateParametersMethods, propagateExceptionsMethods); } @NotNull @@ -177,7 +183,7 @@ public class ChangeSignatureProcessor extends ChangeSignatureProcessorBase { for (UsageInfo usageInfo : usages) { if (usageInfo instanceof OverriderUsageInfo) { final OverriderUsageInfo info = (OverriderUsageInfo)usageInfo; - PsiMethod overrider = info.getElement(); + PsiMethod overrider = assertNotNull(info.getElement()); PsiMethod baseMethod = info.getBaseMethod(); PsiSubstitutor substitutor = calculateSubstitutor(overrider, baseMethod); PsiType type; @@ -212,9 +218,8 @@ public class ChangeSignatureProcessor extends ChangeSignatureProcessorBase { } protected boolean isProcessCovariantOverriders() { - return Messages - .showYesNoDialog(myProject, RefactoringBundle.message("do.you.want.to.process.overriding.methods.with.covariant.return.type"), - JavaChangeSignatureHandler.REFACTORING_NAME, Messages.getQuestionIcon()) == Messages.YES; + String message = RefactoringBundle.message("do.you.want.to.process.overriding.methods.with.covariant.return.type"); + return Messages.showYesNoDialog(myProject, message, ChangeSignatureHandler.REFACTORING_NAME, Messages.getQuestionIcon()) == Messages.YES; } public static void makeEmptyBody(final PsiElementFactory factory, final PsiMethod delegate) throws IncorrectOperationException { @@ -229,7 +234,7 @@ public class ChangeSignatureProcessor extends ChangeSignatureProcessorBase { } @Nullable - public static PsiCallExpression addDelegatingCallTemplate(final PsiMethod delegate, final String newName) throws IncorrectOperationException { + public static PsiCallExpression addDelegatingCallTemplate(PsiMethod delegate, String newName) throws IncorrectOperationException { Project project = delegate.getProject(); PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); PsiCodeBlock body = delegate.getBody(); @@ -240,7 +245,8 @@ public class ChangeSignatureProcessor extends ChangeSignatureProcessorBase { callStatement = CodeStyleManager.getInstance(project).reformat(callStatement); callStatement = body.add(callStatement); callExpression = (PsiCallExpression)((PsiExpressionStatement) callStatement).getExpression(); - } else { + } + else { if (PsiType.VOID.equals(delegate.getReturnType())) { PsiElement callStatement = factory.createStatementFromText(newName + "();", null); callStatement = CodeStyleManager.getInstance(project).reformat(callStatement); @@ -261,16 +267,18 @@ public class ChangeSignatureProcessor extends ChangeSignatureProcessorBase { PsiSubstitutor substitutor; if (derivedMethod.getManager().areElementsEquivalent(derivedMethod, baseMethod)) { substitutor = PsiSubstitutor.EMPTY; - } else { - final PsiClass baseClass = baseMethod.getContainingClass(); - final PsiClass derivedClass = derivedMethod.getContainingClass(); - if(baseClass != null && derivedClass != null && InheritanceUtil.isInheritorOrSelf(derivedClass, baseClass, true)) { - final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, derivedClass, PsiSubstitutor.EMPTY); - final MethodSignature superMethodSignature = baseMethod.getSignature(superClassSubstitutor); - final MethodSignature methodSignature = derivedMethod.getSignature(PsiSubstitutor.EMPTY); - final PsiSubstitutor superMethodSubstitutor = MethodSignatureUtil.getSuperMethodSignatureSubstitutor(methodSignature, superMethodSignature); + } + else { + PsiClass baseClass = baseMethod.getContainingClass(); + PsiClass derivedClass = derivedMethod.getContainingClass(); + if (baseClass != null && derivedClass != null && InheritanceUtil.isInheritorOrSelf(derivedClass, baseClass, true)) { + PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, derivedClass, PsiSubstitutor.EMPTY); + MethodSignature superMethodSignature = baseMethod.getSignature(superClassSubstitutor); + MethodSignature methodSignature = derivedMethod.getSignature(PsiSubstitutor.EMPTY); + PsiSubstitutor superMethodSubstitutor = MethodSignatureUtil.getSuperMethodSignatureSubstitutor(methodSignature, superMethodSignature); substitutor = superMethodSubstitutor != null ? superMethodSubstitutor : superClassSubstitutor; - } else { + } + else { substitutor = PsiSubstitutor.EMPTY; } } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureUtil.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureUtil.java index ccf13bcce327..c83a0ba2a51c 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureUtil.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. @@ -17,12 +17,15 @@ package com.intellij.refactoring.changeSignature; import com.intellij.lang.LanguageRefactoringSupport; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; import com.intellij.psi.JavaTokenType; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiType; import com.intellij.psi.impl.source.tree.Factory; import com.intellij.psi.impl.source.tree.SharedImplUtil; -import com.intellij.psi.util.PsiUtilBase; +import com.intellij.psi.util.PsiUtilCore; +import com.intellij.util.CharTable; import com.intellij.util.IncorrectOperationException; import java.util.ArrayList; @@ -32,16 +35,19 @@ import java.util.List; * @author dsl */ public class ChangeSignatureUtil { - private ChangeSignatureUtil() { + private ChangeSignatureUtil() { } + + public interface ChildrenGenerator { + List getChildren(Parent parent); } - public static void synchronizeList(Parent list, - final List newElements, - ChildrenGenerator generator, - final boolean[] shouldRemoveChild) - throws IncorrectOperationException { - - ArrayList elementsToRemove = null; + public static void synchronizeList( + Parent list, + List newElements, + ChildrenGenerator generator, + boolean[] shouldRemoveChild) throws IncorrectOperationException + { + List elementsToRemove = null; List elements; int index = 0; @@ -67,33 +73,36 @@ public class ChangeSignatureUtil { index--; } else { - assert list.isWritable() : PsiUtilBase.getVirtualFile(list); + assert list.isWritable() : PsiUtilCore.getVirtualFile(list); list.addBefore(newElement, oldElement); if (list.equals(newElement.getParent())) { newElement.delete(); } } } - } else { + } + else { if (newElements.size() > 1 && (!elements.isEmpty() || index < newElements.size() - 1)) { PsiElement anchor; if (index == 0) { anchor = list.getFirstChild(); - } else { + } + else { anchor = index - 1 < elements.size() ? elements.get(index - 1) : null; } - final PsiElement psi = Factory - .createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, SharedImplUtil.findCharTableByTree(list.getNode()), list.getManager()) - .getPsi(); + CharTable charTable = SharedImplUtil.findCharTableByTree(list.getNode()); + PsiElement psi = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, charTable, list.getManager()).getPsi(); if (anchor != null) { list.addAfter(psi, anchor); - } else { + } + else { list.add(psi); } } } index++; } + for (int i = newElements.size(); i < elements.size(); i++) { Child element = elements.get(i); element.delete(); @@ -101,12 +110,15 @@ public class ChangeSignatureUtil { } public static void invokeChangeSignatureOn(PsiMethod method, Project project) { - final ChangeSignatureHandler handler = - LanguageRefactoringSupport.INSTANCE.forLanguage(method.getLanguage()).getChangeSignatureHandler(); - handler.invoke(project, new PsiElement[]{method}, null); + ChangeSignatureHandler handler = LanguageRefactoringSupport.INSTANCE.forLanguage(method.getLanguage()).getChangeSignatureHandler(); + if (handler != null) { + handler.invoke(project, new PsiElement[]{method}, null); + } } - public interface ChildrenGenerator { - List getChildren(Parent parent); + public static boolean deepTypeEqual(PsiType type1, PsiType type2) { + if (type1 == type2) return true; + if (type1 == null || !type1.equals(type2)) return false; + return Comparing.equal(type1.getCanonicalText(true), type2.getCanonicalText(true)); } } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java index 8b721b62a009..2157b7040d16 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,6 +33,8 @@ import org.jetbrains.annotations.Nullable; import java.util.*; +import static com.intellij.refactoring.changeSignature.ChangeSignatureUtil.deepTypeEqual; + class JavaChangeInfoImpl implements JavaChangeInfo { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.JavaChangeInfoImpl"); @@ -195,22 +197,22 @@ class JavaChangeInfoImpl implements JavaChangeInfo { if (isNameChanged) { newNameIdentifier = factory.createIdentifier(newName); } - } protected void fillOldParams(PsiMethod method) { PsiParameter[] parameters = method.getParameterList().getParameters(); oldParameterNames = new String[parameters.length]; oldParameterTypes = new String[parameters.length]; - for(int i = 0; i < parameters.length; i++){ + + PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); + for (int i = 0; i < parameters.length; i++) { PsiParameter parameter = parameters[i]; oldParameterNames[i] = parameter.getName(); - oldParameterTypes[i] = - JavaPsiFacade.getInstance(parameter.getProject()).getElementFactory().createTypeElement(parameter.getType()).getText(); + oldParameterTypes[i] = factory.createTypeElement(parameter.getType()).getText(); } if (!method.isConstructor()){ try { - isReturnTypeChanged = !newReturnType.getType(this.method, method.getManager()).equals(this.method.getReturnType()); + isReturnTypeChanged = !deepTypeEqual(newReturnType.getType(this.method, method.getManager()), this.method.getReturnType()); } catch (IncorrectOperationException e) { isReturnTypeChanged = true; @@ -233,7 +235,9 @@ class JavaChangeInfoImpl implements JavaChangeInfo { } private void setupExceptions(ThrownExceptionInfo[] newExceptions, final PsiMethod method) { - if (newExceptions == null) newExceptions = JavaThrownExceptionInfo.extractExceptions(method); + if (newExceptions == null) { + newExceptions = JavaThrownExceptionInfo.extractExceptions(method); + } this.newExceptions = newExceptions; @@ -242,7 +246,7 @@ class JavaChangeInfoImpl implements JavaChangeInfo { if (!isExceptionSetChanged) { for (int i = 0; i < newExceptions.length; i++) { try { - if (newExceptions[i].getOldIndex() < 0 || !types[i].equals(newExceptions[i].createType(method, method.getManager()))) { + if (newExceptions[i].getOldIndex() < 0 || !deepTypeEqual(types[i], newExceptions[i].createType(method, method.getManager()))) { isExceptionSetChanged = true; break; } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java index 69fc99031e80..ecb68903d1da 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java @@ -33,8 +33,6 @@ import java.util.ArrayList; import java.util.List; public class ParameterInfoImpl implements JavaParameterInfo { - public static final ParameterInfoImpl[] EMPTY_ARRAY = {}; - private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.ParameterInfoImpl"); public int oldParameterIndex; diff --git a/java/java-impl/src/com/intellij/refactoring/util/CanonicalTypes.java b/java/java-impl/src/com/intellij/refactoring/util/CanonicalTypes.java index f7fac6349135..131750f17179 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/CanonicalTypes.java +++ b/java/java-impl/src/com/intellij/refactoring/util/CanonicalTypes.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,18 +15,16 @@ */ package com.intellij.refactoring.util; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import java.util.Collection; import java.util.List; import java.util.Map; @@ -34,61 +32,72 @@ import java.util.Map; * @author dsl */ public class CanonicalTypes { - private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.util.CanonicalTypes"); - private CanonicalTypes() { } public abstract static class Type { @NotNull - public abstract PsiType getType(PsiElement context, final PsiManager manager) throws IncorrectOperationException; + public abstract PsiType getType(PsiElement context, PsiManager manager) throws IncorrectOperationException; @NonNls public abstract String getTypeText(); - public abstract void addImportsTo(final JavaCodeFragment codeFragment); + public void addImportsTo(JavaCodeFragment fragment) { } public boolean isValid() { return true; } } - private static class Primitive extends Type { + private abstract static class AnnotatedType extends Type { + protected final PsiAnnotation[] myAnnotations; + + protected AnnotatedType(PsiAnnotation[] annotations) { + myAnnotations = annotations; + } + } + + private static class Primitive extends AnnotatedType { private final PsiPrimitiveType myType; private Primitive(PsiPrimitiveType type) { + super(type.getAnnotations()); myType = type; } @NotNull - public PsiType getType(PsiElement context, final PsiManager manager) { - return myType; + @Override + public PsiType getType(PsiElement context, PsiManager manager) { + return myAnnotations.length == 0 ? myType : new PsiPrimitiveType(myType.getCanonicalText(false), myAnnotations); } + @Override public String getTypeText() { return myType.getPresentableText(); } - - public void addImportsTo(final JavaCodeFragment codeFragment) {} } - private static class Array extends Type { - private final Type myComponentType; + private static class Array extends AnnotatedType { + protected final Type myComponentType; - private Array(Type componentType) { + private Array(PsiType original, Type componentType) { + super(original.getAnnotations()); myComponentType = componentType; } @NotNull - public PsiType getType(PsiElement context, final PsiManager manager) throws IncorrectOperationException { - return myComponentType.getType(context, manager).createArrayType(); + @Override + public PsiType getType(PsiElement context, PsiManager manager) throws IncorrectOperationException { + return myComponentType.getType(context, manager).createArrayType(myAnnotations); } + @Override public String getTypeText() { return myComponentType.getTypeText() + "[]"; } - public void addImportsTo(final JavaCodeFragment codeFragment) { - myComponentType.addImportsTo(codeFragment); + @Override + public void addImportsTo(JavaCodeFragment fragment) { + myComponentType.addImportsTo(fragment); } @Override @@ -97,59 +106,64 @@ public class CanonicalTypes { } } - private static class Ellipsis extends Type { - private final Type myComponentType; - - private Ellipsis(Type componentType) { - myComponentType = componentType; + private static class Ellipsis extends Array { + private Ellipsis(PsiType original, Type componentType) { + super(original, componentType); } @NotNull - public PsiType getType(PsiElement context, final PsiManager manager) throws IncorrectOperationException { - return new PsiEllipsisType(myComponentType.getType(context, manager)); - } - - public String getTypeText() { - return myComponentType.getTypeText() + "..."; - } - - public void addImportsTo(final JavaCodeFragment codeFragment) { - myComponentType.addImportsTo(codeFragment); + @Override + public PsiType getType(PsiElement context, PsiManager manager) throws IncorrectOperationException { + return new PsiEllipsisType(myComponentType.getType(context, manager), myAnnotations); } @Override - public boolean isValid() { - return myComponentType.isValid(); + public String getTypeText() { + return myComponentType.getTypeText() + "..."; } } - private static class WildcardType extends Type { + private static class WildcardType extends AnnotatedType { private final boolean myIsExtending; private final Type myBound; - private WildcardType(boolean isExtending, Type bound) { + private WildcardType(PsiType original, boolean isExtending, Type bound) { + super(original.getAnnotations()); myIsExtending = isExtending; myBound = bound; } @NotNull - public PsiType getType(PsiElement context, final PsiManager manager) throws IncorrectOperationException { - if(myBound == null) return PsiWildcardType.createUnbounded(context.getManager()); - if (myIsExtending) { - return PsiWildcardType.createExtends(context.getManager(), myBound.getType(context, manager)); + @Override + public PsiType getType(PsiElement context, PsiManager manager) throws IncorrectOperationException { + PsiWildcardType type; + if (myBound == null) { + type = PsiWildcardType.createUnbounded(manager); + } + else if (myIsExtending) { + type = PsiWildcardType.createExtends(manager, myBound.getType(context, manager)); } else { - return PsiWildcardType.createSuper(context.getManager(), myBound.getType(context, manager)); + type = PsiWildcardType.createSuper(manager, myBound.getType(context, manager)); + } + return type.annotate(myAnnotations); + } + + @Override + public String getTypeText() { + if (myBound == null) { + return "?"; + } + else { + return "? " + (myIsExtending ? "extends " : "super ") + myBound.getTypeText(); } } - public String getTypeText() { - if (myBound == null) return "?"; - return "? " + (myIsExtending ? "extends " : "super ") + myBound.getTypeText(); - } - - public void addImportsTo(final JavaCodeFragment codeFragment) { - if (myBound != null) myBound.addImportsTo(codeFragment); + @Override + public void addImportsTo(JavaCodeFragment fragment) { + if (myBound != null) { + myBound.addImportsTo(fragment); + } } @Override @@ -158,73 +172,74 @@ public class CanonicalTypes { } } - private static class WrongType extends Type { - private final String myText; + private static class UnresolvedType extends Type { + private final String myPresentableText; + private final String myCanonicalText; - private WrongType(String text) { - myText = text; + private UnresolvedType(PsiType original) { + myPresentableText = original.getPresentableText(); + myCanonicalText = original.getCanonicalText(true); } @NotNull - public PsiType getType(PsiElement context, final PsiManager manager) throws IncorrectOperationException { - return JavaPsiFacade.getInstance(context.getProject()).getElementFactory().createTypeFromText(myText, context); + @Override + public PsiType getType(PsiElement context, PsiManager manager) throws IncorrectOperationException { + return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeFromText(myCanonicalText, context); } + @Override public String getTypeText() { - return myText; + return myPresentableText; } - public void addImportsTo(final JavaCodeFragment codeFragment) {} - @Override public boolean isValid() { return false; } } - private static class ClassType extends Type { - private final String myOriginalText; + private static class ClassType extends AnnotatedType { + private final String myPresentableText; private final String myClassQName; - private final Map mySubstitutor; + private final Map mySubstitutor; - private ClassType(String originalText, String classQName, Map substitutor) { - myOriginalText = originalText; + private ClassType(PsiType original, String classQName, Map substitutor) { + super(original.getAnnotations()); + myPresentableText = original.getPresentableText(); myClassQName = classQName; mySubstitutor = substitutor; } @NotNull - public PsiType getType(PsiElement context, final PsiManager manager) throws IncorrectOperationException { - final JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject()); - final PsiElementFactory factory = facade.getElementFactory(); - final PsiResolveHelper resolveHelper = facade.getResolveHelper(); - final PsiClass aClass = resolveHelper.resolveReferencedClass(myClassQName, context); + @Override + public PsiType getType(PsiElement context, PsiManager manager) throws IncorrectOperationException { + JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject()); + PsiElementFactory factory = facade.getElementFactory(); + + PsiClass aClass = facade.getResolveHelper().resolveReferencedClass(myClassQName, context); if (aClass == null) { return factory.createTypeFromText(myClassQName, context); } - Map substitutionMap = new HashMap(); + + Map substitutionMap = ContainerUtil.newHashMap(); for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(aClass)) { - final String name = typeParameter.getName(); - final Type type = mySubstitutor.get(name); - if (type != null) { - substitutionMap.put(typeParameter, type.getType(context, manager)); - } else { - substitutionMap.put(typeParameter, null); - } + Type substitute = mySubstitutor.get(typeParameter.getName()); + substitutionMap.put(typeParameter, substitute != null ? substitute.getType(context, manager) : null); } - return factory.createType(aClass, factory.createSubstitutor(substitutionMap)); + return factory.createType(aClass, factory.createSubstitutor(substitutionMap), null, myAnnotations); } + @Override public String getTypeText() { - return myOriginalText; + return myPresentableText; } - public void addImportsTo(final JavaCodeFragment codeFragment) { - codeFragment.addImportsFromString(myClassQName); - final Collection types = mySubstitutor.values(); - for (Type type : types) { + @Override + public void addImportsTo(JavaCodeFragment fragment) { + fragment.addImportsFromString(myClassQName); + for (Type type : mySubstitutor.values()) { if (type != null) { - type.addImportsTo(codeFragment); + type.addImportsTo(fragment); } } } @@ -233,15 +248,18 @@ public class CanonicalTypes { private static class DisjunctionType extends Type { private final List myTypes; - private DisjunctionType(final List types) { + private DisjunctionType(List types) { myTypes = types; } @NotNull @Override public PsiType getType(final PsiElement context, final PsiManager manager) throws IncorrectOperationException { - final List types = ContainerUtil.map(myTypes, new Function() { - @Override public PsiType fun(Type type) { return type.getType(context, manager); } + List types = ContainerUtil.map(myTypes, new Function() { + @Override + public PsiType fun(Type type) { + return type.getType(context, manager); + } }); return new PsiDisjunctionType(types, manager); } @@ -249,14 +267,17 @@ public class CanonicalTypes { @Override public String getTypeText() { return StringUtil.join(myTypes, new Function() { - @Override public String fun(Type type) { return type.getTypeText(); } + @Override + public String fun(Type type) { + return type.getTypeText(); + } }, "|"); } @Override - public void addImportsTo(final JavaCodeFragment codeFragment) { + public void addImportsTo(JavaCodeFragment fragment) { for (Type type : myTypes) { - type.addImportsTo(codeFragment); + type.addImportsTo(fragment); } } } @@ -265,65 +286,61 @@ public class CanonicalTypes { public static final Creator INSTANCE = new Creator(); @Override - public Type visitPrimitiveType(final PsiPrimitiveType primitiveType) { - return new Primitive(primitiveType); + public Type visitPrimitiveType(PsiPrimitiveType type) { + return new Primitive(type); } @Override - public Type visitEllipsisType(final PsiEllipsisType ellipsisType) { - return new Ellipsis(ellipsisType.getComponentType().accept(this)); + public Type visitEllipsisType(PsiEllipsisType type) { + return new Ellipsis(type, type.getComponentType().accept(this)); } @Override - public Type visitArrayType(final PsiArrayType arrayType) { - return new Array(arrayType.getComponentType().accept(this)); + public Type visitArrayType(PsiArrayType type) { + return new Array(type, type.getComponentType().accept(this)); } @Override - public Type visitWildcardType(final PsiWildcardType wildcardType) { - final PsiType wildcardBound = wildcardType.getBound(); - final Type bound = wildcardBound == null ? null : wildcardBound.accept(this); - return new WildcardType(wildcardType.isExtends(), bound); + public Type visitWildcardType(PsiWildcardType type) { + PsiType bound = type.getBound(); + return new WildcardType(type, type.isExtends(), bound == null ? null : bound.accept(this)); } @Override - public Type visitClassType(final PsiClassType classType) { - final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics(); - final PsiClass aClass = resolveResult.getElement(); + public Type visitClassType(PsiClassType type) { + PsiClassType.ClassResolveResult resolveResult = type.resolveGenerics(); + PsiClass aClass = resolveResult.getElement(); if (aClass instanceof PsiAnonymousClass) { return visitClassType(((PsiAnonymousClass)aClass).getBaseClassType()); } - final String originalText = classType.getPresentableText(); - if (aClass == null) { - return new WrongType(originalText); - } else { - final Map substitutionMap = new HashMap(); - final PsiSubstitutor substitutor = resolveResult.getSubstitutor(); + else if (aClass == null) { + return new UnresolvedType(type); + } + else { + Map substitutionMap = ContainerUtil.newHashMap(); + PsiSubstitutor substitutor = resolveResult.getSubstitutor(); for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(aClass)) { - final PsiType type = substitutor.substitute(typeParameter); - final String name = typeParameter.getName(); - if (type == null) { - substitutionMap.put(name, null); - } else { - substitutionMap.put(name, type.accept(this)); - } + PsiType substitute = substitutor.substitute(typeParameter); + substitutionMap.put(typeParameter.getName(), substitute != null ? substitute.accept(this) : null); } - final String qualifiedName = aClass.getQualifiedName(); - LOG.assertTrue(aClass.getName() != null); - return new ClassType(originalText, qualifiedName != null ? qualifiedName : aClass.getName(), substitutionMap); + String qualifiedName = ObjectUtils.notNull(aClass.getQualifiedName(), aClass.getName()); + return new ClassType(type, qualifiedName, substitutionMap); } } @Override - public Type visitDisjunctionType(final PsiDisjunctionType disjunctionType) { - final List types = ContainerUtil.map(disjunctionType.getDisjunctions(), new Function() { - @Override public Type fun(PsiType type) { return createTypeWrapper(type); } + public Type visitDisjunctionType(PsiDisjunctionType type) { + List types = ContainerUtil.map(type.getDisjunctions(), new Function() { + @Override + public Type fun(PsiType type) { + return type.accept(Creator.this); + } }); return new DisjunctionType(types); } } - public static Type createTypeWrapper(@NotNull final PsiType type) { + public static Type createTypeWrapper(@NotNull PsiType type) { return type.accept(Creator.INSTANCE); } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java index 57390de57c9f..79b947527a1a 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.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. @@ -511,7 +511,8 @@ public class PsiSubstitutorImpl implements PsiSubstitutor { buffer.append(" of "); buffer.append(((PsiMethod)owner).getName()); buffer.append(" in "); - buffer.append(((PsiMethod)owner).getContainingClass().getQualifiedName()); + PsiClass aClass = ((PsiMethod)owner).getContainingClass(); + buffer.append(aClass != null ? aClass.getQualifiedName() : ""); } buffer.append(" -> "); if (entry.getValue() != null) { diff --git a/java/java-tests/testData/refactoring/changeSignature/TypeAnnotationsAllAround.java b/java/java-tests/testData/refactoring/changeSignature/TypeAnnotationsAllAround.java new file mode 100644 index 000000000000..c9387c2ebdc3 --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignature/TypeAnnotationsAllAround.java @@ -0,0 +1,14 @@ +import java.lang.annotation.*; +import java.util.List; + +@Target({ElementType.TYPE_USE}) +@interface TA { int value() default 0; } + +class C { + class Inner { } + + //public @TA(0) List<@TA(1) C.@TA(1) Inner> m(@TA(2) int @TA(3) [] p1, @TA(4) List<@TA(5) Class<@TA(6) ?>> p2, @TA(7) String @TA(8) ... p3) throws @TA(42) IllegalArgumentException, @TA(43) IllegalStateException { + public List m() { + return null; + } +} diff --git a/java/java-tests/testData/refactoring/changeSignature/TypeAnnotationsAllAround_after.java b/java/java-tests/testData/refactoring/changeSignature/TypeAnnotationsAllAround_after.java new file mode 100644 index 000000000000..7b21bd166fcb --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignature/TypeAnnotationsAllAround_after.java @@ -0,0 +1,14 @@ +import java.lang.annotation.*; +import java.util.List; + +@Target({ElementType.TYPE_USE}) +@interface TA { int value() default 0; } + +class C { + class Inner { } + + //public @TA(0) List<@TA(1) C.@TA(1) Inner> m(@TA(2) int @TA(3) [] p1, @TA(4) List<@TA(5) Class<@TA(6) ?>> p2, @TA(7) String @TA(8) ... p3) throws @TA(42) IllegalArgumentException, @TA(43) IllegalStateException { + public @TA(0) List<@TA(1) Inner> m(@TA(2) int @TA(3) [] p1, @TA(4) List<@TA(5) Class<@TA(6) ?>> p2, @TA(7) String @TA(8) ... p3) { + return null; + } +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java index 4f6c44824ab6..e55116fb5e7a 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java @@ -36,6 +36,13 @@ import java.util.HashSet; public class ChangeSignatureTest extends LightRefactoringTestCase { private PsiElementFactory myFactory; + @NotNull + @Override + protected String getTestDataPath() { + return JavaTestUtil.getJavaTestDataPath(); + } + + @Override public void setUp() throws Exception { super.setUp(); myFactory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); @@ -413,8 +420,45 @@ public class ChangeSignatureTest extends LightRefactoringTestCase { checkResultByFile(basePath + "_after.java"); } + public void testTypeAnnotationsAllAround() { + //String[] ps = {"@TA(1) int @TA(2) []", "java.util.@TA(4) List<@TA(5) Class<@TA(6) ?>>", "@TA(7) String @TA(8) ..."}; + //String[] ex = {"@TA(42) IllegalArgumentException", "java.lang.@TA(43) IllegalStateException"}; + //doTest("java.util.@TA(0) List<@TA(1) C.@TA(1) Inner>", ps, ex, false); + String[] ps = {"@TA(2) int @TA(3) []", "@TA(4) List<@TA(5) Class<@TA(6) ?>>", "@TA(7) String @TA(8) ..."}; + String[] ex = {}; + doTest("@TA(0) List<@TA(1) Inner>", ps, ex, false); + } + /* workers */ + private void doTest(@Nullable String returnType, @Nullable final String[] parameters, @Nullable final String[] exceptions, boolean delegate) { + GenParams genParams = parameters == null ? new SimpleParameterGen() : new GenParams() { + @Override + public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException { + ParameterInfoImpl[] parameterInfos = new ParameterInfoImpl[parameters.length]; + for (int i = 0; i < parameters.length; i++) { + PsiType type = myFactory.createTypeFromText(parameters[i], method); + parameterInfos[i] = new ParameterInfoImpl(-1, "p" + (i + 1), type); + } + return parameterInfos; + } + }; + + GenExceptions genExceptions = exceptions == null ? new SimpleExceptionsGen() : new GenExceptions() { + @Override + public ThrownExceptionInfo[] genExceptions(PsiMethod method) throws IncorrectOperationException { + ThrownExceptionInfo[] exceptionInfos = new ThrownExceptionInfo[exceptions.length]; + for (int i = 0; i < exceptions.length; i++) { + PsiType type = myFactory.createTypeFromText(exceptions[i], method); + exceptionInfos[i] = new JavaThrownExceptionInfo(-1, (PsiClassType)type); + } + return exceptionInfos; + } + }; + + doTest(null, null, returnType, genParams, genExceptions, delegate); + } + private void doTest(@Nullable String newReturnType, ParameterInfoImpl[] parameterInfos, boolean generateDelegate) { doTest(null, null, newReturnType, parameterInfos, new ThrownExceptionInfo[0], generateDelegate); } @@ -425,15 +469,17 @@ public class ChangeSignatureTest extends LightRefactoringTestCase { ParameterInfoImpl[] parameterInfo, ThrownExceptionInfo[] exceptionInfo, boolean generateDelegate) { - doTest(newVisibility, newName, newReturnType, new SimpleParameterGen(parameterInfo), new SimpleExceptionsGen(exceptionInfo), generateDelegate); + SimpleParameterGen params = new SimpleParameterGen(parameterInfo); + SimpleExceptionsGen exceptions = new SimpleExceptionsGen(exceptionInfo); + doTest(newVisibility, newName, newReturnType, params, exceptions, generateDelegate); } private void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility, @Nullable String newName, @Nullable @NonNls String newReturnType, - GenParams gen, + GenParams genParams, boolean generateDelegate) { - doTest(newVisibility, newName, newReturnType, gen, new SimpleExceptionsGen(), generateDelegate); + doTest(newVisibility, newName, newReturnType, genParams, new SimpleExceptionsGen(), generateDelegate); } private void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility, @@ -461,9 +507,9 @@ public class ChangeSignatureTest extends LightRefactoringTestCase { private static class SimpleParameterGen implements GenParams { private ParameterInfoImpl[] myInfos; - private SimpleParameterGen() { } + public SimpleParameterGen() { } - private SimpleParameterGen(ParameterInfoImpl[] infos) { + public SimpleParameterGen(ParameterInfoImpl[] infos) { myInfos = infos; } @@ -493,7 +539,7 @@ public class ChangeSignatureTest extends LightRefactoringTestCase { myInfos = new ThrownExceptionInfo[0]; } - private SimpleExceptionsGen(ThrownExceptionInfo[] infos) { + public SimpleExceptionsGen(ThrownExceptionInfo[] infos) { myInfos = infos; } @@ -505,10 +551,4 @@ public class ChangeSignatureTest extends LightRefactoringTestCase { return myInfos; } } - - @NotNull - @Override - protected String getTestDataPath() { - return JavaTestUtil.getJavaTestDataPath(); - } } diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java index fcadcd170588..1d0db9f7a9db 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java @@ -28,7 +28,6 @@ import com.intellij.refactoring.introduceVariable.IntroduceVariableSettings; import com.intellij.refactoring.ui.TypeSelectorManagerImpl; import com.intellij.testFramework.LightCodeInsightTestCase; import com.intellij.util.containers.MultiMap; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -37,66 +36,65 @@ import java.util.Collection; * @author dsl */ public class IntroduceVariableTest extends LightCodeInsightTestCase { - @NotNull @Override protected String getTestDataPath() { return JavaTestUtil.getJavaTestDataPath(); } - public void testSimpleExpression() throws Exception { + public void testSimpleExpression() { doTest(new MockIntroduceVariableHandler("i", false, false, true, "int")); } - public void testInsideFor() throws Exception { + public void testInsideFor() { doTest(new MockIntroduceVariableHandler("temp", false, false, true, "int")); } - public void testReplaceAll() throws Exception { - doTest(new MockIntroduceVariableHandler("s", true, true, true, "java.lang.String")); + public void testReplaceAll() { + doTest(new MockIntroduceVariableHandler("s", true, true, true, CommonClassNames.JAVA_LANG_STRING)); } - public void testIDEADEV3678() throws Exception { + public void testIDEADEV3678() { doTest(new MockIntroduceVariableHandler("component", true, true, true, CommonClassNames.JAVA_LANG_OBJECT)); } - public void testIDEADEV13369() throws Exception { + public void testIDEADEV13369() { doTest(new MockIntroduceVariableHandler("ints", true, true, true, "int[]")); } - public void testAnonymousClass() throws Exception { + public void testAnonymousClass() { doTest(new MockIntroduceVariableHandler("temp", true, false, true, "int")); } - public void testAnonymousClass1() throws Exception { + public void testAnonymousClass1() { doTest(new MockIntroduceVariableHandler("runnable", false, false, false, CommonClassNames.JAVA_LANG_RUNNABLE)); } - public void testAnonymousClass2() throws Exception { + public void testAnonymousClass2() { doTest(new MockIntroduceVariableHandler("j", true, false, false, "int")); } - public void testAnonymousClass3() throws Exception { + public void testAnonymousClass3() { doTest(new MockIntroduceVariableHandler("j", true, false, false, "Foo")); } - public void testAnonymousClass4() throws Exception { + public void testAnonymousClass4() { doTest(new MockIntroduceVariableHandler("j", true, false, false, "int")); } - public void testAnonymousClass5() throws Exception { + public void testAnonymousClass5() { doTest(new MockIntroduceVariableHandler("j", true, false, false, "int")); } - public void testLambda() throws Exception { + public void testLambda() { doTest(new MockIntroduceVariableHandler("j", true, false, false, "int")); } - public void testParenthized() throws Exception { + public void testParenthized() { doTest(new MockIntroduceVariableHandler("temp", true, false, false, "int")); } - public void testExpectedType8Inference() throws Exception { + public void testExpectedType8Inference() { final PsiResolveHelperImpl helper = (PsiResolveHelperImpl)JavaPsiFacade.getInstance(getProject()).getResolveHelper(); helper.setTestHelper(new PsiGraphInferenceHelper(getPsiManager())); try { @@ -108,64 +106,64 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { } } - public void testMethodCall() throws Exception { + public void testMethodCall() { doTest(new MockIntroduceVariableHandler("temp", true, true, true, CommonClassNames.JAVA_LANG_OBJECT)); } - public void testMethodCallInSwitch() throws Exception { + public void testMethodCallInSwitch() { doTest(new MockIntroduceVariableHandler("i", true, true, true, "int")); } - public void testParenthizedOccurence() throws Exception { + public void testParenthizedOccurence() { doTest(new MockIntroduceVariableHandler("empty", true, true, true, "boolean")); } - public void testParenthizedOccurence1() throws Exception { - doTest(new MockIntroduceVariableHandler("s", true, true, true, "java.lang.String")); + public void testParenthizedOccurence1() { + doTest(new MockIntroduceVariableHandler("s", true, true, true, CommonClassNames.JAVA_LANG_STRING)); } - public void testConflictingField() throws Exception { - doTest(new MockIntroduceVariableHandler("name", true, false, true, "java.lang.String")); + public void testConflictingField() { + doTest(new MockIntroduceVariableHandler("name", true, false, true, CommonClassNames.JAVA_LANG_STRING)); } - public void testConflictingFieldInExpression() throws Exception { + public void testConflictingFieldInExpression() { doTest(new MockIntroduceVariableHandler("name", false, false, true, "int")); } - public void testStaticConflictingField() throws Exception { + public void testStaticConflictingField() { doTest(new MockIntroduceVariableHandler("name", false, false, true, "int")); } - public void testNonConflictingField() throws Exception { + public void testNonConflictingField() { doTest(new MockIntroduceVariableHandler("name", false, false, true, "int")); } - public void testScr16910() throws Exception { + public void testScr16910() { doTest(new MockIntroduceVariableHandler("i", true, true, false, "int")); } - public void testSCR18295() throws Exception { - doTest(new MockIntroduceVariableHandler("it", true, false, false, "java.lang.String")); + public void testSCR18295() { + doTest(new MockIntroduceVariableHandler("it", true, false, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testSCR18295a() throws Exception { - doTest(new MockIntroduceVariableHandler("it", false, false, false, "java.lang.String")); + public void testSCR18295a() { + doTest(new MockIntroduceVariableHandler("it", false, false, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testFromInjected() throws Exception { - doTest(new MockIntroduceVariableHandler("regexp", false, false, false, "java.lang.String")); + public void testFromInjected() { + doTest(new MockIntroduceVariableHandler("regexp", false, false, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testSCR10412() throws Exception { + public void testSCR10412() { doTest(new MockIntroduceVariableHandler("newVar", false, false, false, "java.lang.String[]")); } - public void testSCR22718() throws Exception { + public void testSCR22718() { doTest(new MockIntroduceVariableHandler("object", true, true, false, CommonClassNames.JAVA_LANG_OBJECT)); } - public void testSCR26075() throws Exception { - doTest(new MockIntroduceVariableHandler("wrong", false, false, false, "java.lang.String") { + public void testSCR26075() { + doTest(new MockIntroduceVariableHandler("wrong", false, false, false, CommonClassNames.JAVA_LANG_STRING) { @Override protected void assertValidationResult(boolean validationResult) { assertFalse(validationResult); @@ -182,59 +180,59 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { }); } - public void testConflictingFieldInOuterClass() throws Exception { - doTest(new MockIntroduceVariableHandler("text", true, true, false, "java.lang.String")); + public void testConflictingFieldInOuterClass() { + doTest(new MockIntroduceVariableHandler("text", true, true, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testSkipSemicolon() throws Exception { + public void testSkipSemicolon() { doTest(new MockIntroduceVariableHandler("mi5", false, false, false, "int")); } - public void testInsideIf() throws Exception { - doTest(new MockIntroduceVariableHandler("s1", false, false, false, "java.lang.String")); + public void testInsideIf() { + doTest(new MockIntroduceVariableHandler("s1", false, false, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testInsideElse() throws Exception { - doTest(new MockIntroduceVariableHandler("s1", false, false, false, "java.lang.String")); + public void testInsideElse() { + doTest(new MockIntroduceVariableHandler("s1", false, false, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testInsideWhile() throws Exception { + public void testInsideWhile() { doTest(new MockIntroduceVariableHandler("temp", false, false, false, "int")); } - public void testSCR40281() throws Exception { + public void testSCR40281() { doTest(new MockIntroduceVariableHandler("temp", false, false, false, "Set.Entry>")); } - public void testWithIfBranches() throws Exception { + public void testWithIfBranches() { doTest(new MockIntroduceVariableHandler("temp", true, false, false, "int")); } - public void testInsideForLoop() throws Exception { + public void testInsideForLoop() { doTest(new MockIntroduceVariableHandler("temp", true, false, false, "int")); } - public void testDuplicateGenericExpressions() throws Exception { + public void testDuplicateGenericExpressions() { doTest(new MockIntroduceVariableHandler("temp", true, false, false, "Foo2")); } - public void testStaticImport() throws Exception { + public void testStaticImport() { doTest(new MockIntroduceVariableHandler("i", true, true, false, "int")); } - public void testThisQualifier() throws Exception { + public void testThisQualifier() { doTest(new MockIntroduceVariableHandler("count", true, true, false, "int")); } - public void testSubLiteral() throws Exception { - doTest(new MockIntroduceVariableHandler("str", false, false, false, "java.lang.String")); + public void testSubLiteral() { + doTest(new MockIntroduceVariableHandler("str", false, false, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testSubLiteral1() throws Exception { - doTest(new MockIntroduceVariableHandler("str", false, false, false, "java.lang.String")); + public void testSubLiteral1() { + doTest(new MockIntroduceVariableHandler("str", false, false, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testSubLiteralFailure() throws Exception { + public void testSubLiteralFailure() { try { doTest(new MockIntroduceVariableHandler("str", false, false, false, "int")); } @@ -246,35 +244,35 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { fail("Should not be able to perform refactoring"); } - public void testSubLiteralFromExpression() throws Exception { - doTest(new MockIntroduceVariableHandler("str", false, false, false, "java.lang.String")); + public void testSubLiteralFromExpression() { + doTest(new MockIntroduceVariableHandler("str", false, false, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testSubExpressionFromIntellijidearulezzz() throws Exception { - doTest(new MockIntroduceVariableHandler("str", false, false, false, "java.lang.String")); + public void testSubExpressionFromIntellijidearulezzz() { + doTest(new MockIntroduceVariableHandler("str", false, false, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testSubPrimitiveLiteral() throws Exception { + public void testSubPrimitiveLiteral() { doTest(new MockIntroduceVariableHandler("str", false, false, false, "boolean")); } - public void testArrayFromVarargs() throws Exception { + public void testArrayFromVarargs() { doTest(new MockIntroduceVariableHandler("strs", false, false, false, "java.lang.String[]")); } - public void testArrayFromVarargs1() throws Exception { + public void testArrayFromVarargs1() { doTest(new MockIntroduceVariableHandler("strs", false, false, false, "java.lang.String[]")); } - public void testEnumArrayFromVarargs() throws Exception { + public void testEnumArrayFromVarargs() { doTest(new MockIntroduceVariableHandler("strs", false, false, false, "E[]")); } - public void testFromFinalFieldOnAssignment() throws Exception { - doTest(new MockIntroduceVariableHandler("strs", false, false, false, "java.lang.String")); + public void testFromFinalFieldOnAssignment() { + doTest(new MockIntroduceVariableHandler("strs", false, false, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testNoArrayFromVarargs() throws Exception { + public void testNoArrayFromVarargs() { try { doTest(new MockIntroduceVariableHandler("strs", false, false, false, "java.lang.String[]")); } @@ -286,7 +284,7 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { fail("Should not be able to perform refactoring"); } - public void testNoArrayFromVarargs1() throws Exception { + public void testNoArrayFromVarargs1() { try { doTest(new MockIntroduceVariableHandler("strs", false, false, false, "java.lang.String[]")); } @@ -298,59 +296,59 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { fail("Should not be able to perform refactoring"); } - public void testNonExpression() throws Exception { + public void testNonExpression() { doTest(new MockIntroduceVariableHandler("sum", true, true, false, "int")); } - public void testTypeAnnotations() throws Exception { + public void testTypeAnnotations() { doTest(new MockIntroduceVariableHandler("y1", true, false, false, "@TA C")); } - public void testReturnStatementWithoutSemicolon() throws Exception { - doTest(new MockIntroduceVariableHandler("b", true, true, false, "java.lang.String")); + public void testReturnStatementWithoutSemicolon() { + doTest(new MockIntroduceVariableHandler("b", true, true, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testAndAndSubexpression() throws Exception { + public void testAndAndSubexpression() { doTest(new MockIntroduceVariableHandler("ab", true, true, false, "boolean")); } - public void testSubexpressionWithSpacesInSelection() throws Exception { + public void testSubexpressionWithSpacesInSelection() { doTest(new MockIntroduceVariableHandler("ab", true, true, false, "boolean")); } - public void testDuplicatesAnonymousClassCreationWithSimilarParameters () throws Exception { + public void testDuplicatesAnonymousClassCreationWithSimilarParameters () { doTest(new MockIntroduceVariableHandler("foo1", true, true, false, "Foo")); } - public void testDifferentForeachParameters () throws Exception { - doTest(new MockIntroduceVariableHandler("tostr", true, true, false, "java.lang.String")); + public void testDifferentForeachParameters () { + doTest(new MockIntroduceVariableHandler("tostr", true, true, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testCollapsedToDiamond() throws Exception { + public void testCollapsedToDiamond() { doTest(new MockIntroduceVariableHandler("a", true, true, true, "java.util.ArrayList")); } - public void testCantCollapsedToDiamond() throws Exception { + public void testCantCollapsedToDiamond() { doTest(new MockIntroduceVariableHandler("a", true, true, true, "Foo")); } - public void testFromForInitializer() throws Exception { + public void testFromForInitializer() { doTest(new MockIntroduceVariableHandler("list", true, true, true, "java.util.List")); } - public void testInvalidPostfixExpr() throws Exception { + public void testInvalidPostfixExpr() { doTest(new MockIntroduceVariableHandler("a1", true, false, true, "int[]")); } - public void testPolyadic() throws Exception { + public void testPolyadic() { doTest(new MockIntroduceVariableHandler("b1", true, true, true, "boolean")); } - public void testAssignmentToUnresolvedReference() throws Exception { + public void testAssignmentToUnresolvedReference() { doTest(new MockIntroduceVariableHandler("collection", true, true, true, "java.util.List>")); } - public void testNameSuggestion() throws Exception { + public void testNameSuggestion() { final String expectedTypeName = "Path"; doTest(new MockIntroduceVariableHandler("path", true, false, false, expectedTypeName) { @Override @@ -370,7 +368,7 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { }); } - public void testSiblingInnerClassType() throws Exception { + public void testSiblingInnerClassType() { doTest(new MockIntroduceVariableHandler("vari", true, false, false, "A.B") { @Override public IntroduceVariableSettings getSettings(Project project, Editor editor, @@ -388,7 +386,7 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { }); } - public void testNonExpressionPriorityFailure() throws Exception { + public void testNonExpressionPriorityFailure() { doTest(new MockIntroduceVariableHandler("sum", true, true, false, "int"){ @Override protected void showErrorMessage(Project project, Editor editor, String message) { @@ -398,10 +396,9 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { }); } - - public void testIncorrectExpressionSelected() throws Exception { + public void testIncorrectExpressionSelected() { try { - doTest(new MockIntroduceVariableHandler("toString", false, false, false, "java.lang.String")); + doTest(new MockIntroduceVariableHandler("toString", false, false, false, CommonClassNames.JAVA_LANG_STRING)); } catch (Exception e) { assertEquals(e.getMessage(), "Error message:Cannot perform refactoring.\n" + @@ -411,51 +408,50 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { fail("Should not be able to perform refactoring"); } - public void testMultiCatchSimple() throws Exception { + public void testMultiCatchSimple() { doTest(new MockIntroduceVariableHandler("e", true, true, false, "java.lang.Exception", true)); } - public void testMultiCatchTyped() throws Exception { + public void testMultiCatchTyped() { doTest(new MockIntroduceVariableHandler("b", true, true, false, "java.lang.Exception", true)); } - public void testBeforeVoidStatement() throws Exception { + public void testBeforeVoidStatement() { doTest(new MockIntroduceVariableHandler("c", false, false, false, CommonClassNames.JAVA_LANG_OBJECT)); } - public void testWriteUsages() throws Exception { + public void testWriteUsages() { doTest(new MockIntroduceVariableHandler("c", true, false, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testLambdaExpr() throws Exception { - + public void testLambdaExpr() { doTest(new MockIntroduceVariableHandler("c", false, false, false, "SAM")); } - public void testMethodRef() throws Exception { + public void testMethodRef() { doTest(new MockIntroduceVariableHandler("c", false, false, false, "Test.Bar")); } - public void testLambdaExprNotAccepted() throws Exception { + public void testLambdaExprNotAccepted() { doTest(new MockIntroduceVariableHandler("c", false, false, false, "SAM")); } - public void testOneLineLambdaVoidCompatible() throws Exception { - doTest(new MockIntroduceVariableHandler("c", false, false, false, "java.lang.String")); + public void testOneLineLambdaVoidCompatible() { + doTest(new MockIntroduceVariableHandler("c", false, false, false, CommonClassNames.JAVA_LANG_STRING)); } - public void testOneLineLambdaValueCompatible() throws Exception { + public void testOneLineLambdaValueCompatible() { doTest(new MockIntroduceVariableHandler("c", false, false, false, "int")); } - public void testNormalizeDeclarations() throws Exception { + public void testNormalizeDeclarations() { doTest(new MockIntroduceVariableHandler("i3", false, false, false, "int")); } - public void testMethodReferenceExpr() throws Exception { + public void testMethodReferenceExpr() { doTest(new MockIntroduceVariableHandler("m", false, false, false, "Foo.I")); } - public void testReturnNonExportedArray() throws Exception { + public void testReturnNonExportedArray() { doTest(new MockIntroduceVariableHandler("i", false, false, false, "java.io.File[]") { @Override protected boolean isInplaceAvailableInTestMode() { @@ -464,8 +460,8 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { }); } - private void doTest(IntroduceVariableBase testMe) throws Exception { - @NonNls String baseName = "/refactoring/introduceVariable/" + getTestName(false); + private void doTest(IntroduceVariableBase testMe) { + String baseName = "/refactoring/introduceVariable/" + getTestName(false); configureByFile(baseName + ".java"); testMe.invoke(getProject(), getEditor(), getFile(), null); checkResultByFile(baseName + ".after.java"); diff --git a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java index 2f18d3c6a95f..a37059f98cfa 100644 --- a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java +++ b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java @@ -18,6 +18,8 @@ package com.intellij.ide; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.util.ExecUtil; import com.intellij.ide.browsers.BrowserLauncher; +import com.intellij.ide.browsers.BrowserLauncherAppless; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -68,7 +70,7 @@ public class BrowserUtil { } public static void browse(@NotNull File file) { - BrowserLauncher.getInstance().browse(file); + getBrowserLauncher().browse(file); } public static void browse(@NotNull URL url) { @@ -85,18 +87,22 @@ public class BrowserUtil { } public static void browse(@NotNull @NonNls String url) { - BrowserLauncher.getInstance().browse(url, null); + getBrowserLauncher().browse(url, null); + } + + private static BrowserLauncher getBrowserLauncher() { + return ApplicationManager.getApplication() == null ? new BrowserLauncherAppless() : BrowserLauncher.getInstance(); } public static void open(@NotNull @NonNls String url) { - BrowserLauncher.getInstance().open(url); + getBrowserLauncher().open(url); } /** * Main method: tries to launch a browser using every possible way */ public static void browse(@NotNull URI uri) { - BrowserLauncher.getInstance().browse(uri); + getBrowserLauncher().browse(uri); } @SuppressWarnings("UnusedDeclaration") diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java new file mode 100644 index 000000000000..235dbf9d3b45 --- /dev/null +++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java @@ -0,0 +1,459 @@ +/* + * 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.ide.browsers; + +import com.intellij.CommonBundle; +import com.intellij.Patches; +import com.intellij.execution.ExecutionException; +import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.util.ExecUtil; +import com.intellij.ide.BrowserUtil; +import com.intellij.ide.GeneralSettings; +import com.intellij.ide.IdeBundle; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.PathManager; +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.DialogWrapper; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.FileUtilRt; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.*; +import com.intellij.ui.GuiUtils; +import com.intellij.util.ArrayUtil; +import com.intellij.util.PathUtil; +import com.intellij.util.io.ZipUtil; +import com.intellij.util.ui.OptionsDialog; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.util.*; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public class BrowserLauncherAppless extends BrowserLauncher { + static final Logger LOG = Logger.getInstance(BrowserLauncherAppless.class); + + private static boolean isDesktopActionSupported(Desktop.Action action) { + return !Patches.SUN_BUG_ID_6457572 && !Patches.SUN_BUG_ID_6486393 && + Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(action); + } + + public static boolean canStartDefaultBrowser() { + return isDesktopActionSupported(Desktop.Action.BROWSE) || + SystemInfo.isMac || SystemInfo.isWindows || + SystemInfo.isUnix && SystemInfo.hasXdgOpen(); + } + + private static GeneralSettings getGeneralSettingsInstance() { + if (ApplicationManager.getApplication() != null) { + GeneralSettings settings = GeneralSettings.getInstance(); + if (settings != null) { + return settings; + } + } + + return new GeneralSettings(); + } + + @Nullable + private static List getDefaultBrowserCommand() { + if (SystemInfo.isWindows) { + return Arrays.asList(ExecUtil.getWindowsShellName(), "/c", "start", GeneralCommandLine.inescapableQuote("")); + } + else if (SystemInfo.isMac) { + return Collections.singletonList(ExecUtil.getOpenCommandPath()); + } + else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen()) { + return Collections.singletonList("xdg-open"); + } + else { + return null; + } + } + + @Override + public void open(@NotNull String url) { + openOrBrowse(url, false); + } + + @Override + public void browse(@NotNull File file) { + browse(VfsUtil.toUri(file)); + } + + @Override + public void browse(@NotNull URI uri) { + LOG.debug("Launch browser: [" + uri + "]"); + + GeneralSettings settings = getGeneralSettingsInstance(); + if (settings.isUseDefaultBrowser()) { + if (isDesktopActionSupported(Desktop.Action.BROWSE)) { + try { + Desktop.getDesktop().browse(uri); + LOG.debug("Browser launched using JDK 1.6 API"); + return; + } + catch (Exception e) { + LOG.warn("Error while using Desktop API, fallback to CLI", e); + } + } + + List command = getDefaultBrowserCommand(); + if (command != null) { + doLaunch(uri.toString(), command, null, null, ArrayUtil.EMPTY_STRING_ARRAY); + return; + } + } + + browseUsingPath(uri.toString(), settings.getBrowserPath(), null, null); + } + + private void openOrBrowse(@NotNull String url, boolean browse) { + url = url.trim(); + + if (url.startsWith("jar:")) { + String files = extractFiles(url); + if (files == null) { + return; + } + url = files; + } + + URI uri; + if (BrowserUtil.isAbsoluteURL(url)) { + uri = VfsUtil.toUri(url); + } + else { + File file = new File(url); + if (!browse && isDesktopActionSupported(Desktop.Action.OPEN)) { + try { + Desktop.getDesktop().open(file); + return; + } + catch (IOException e) { + LOG.debug(e); + } + } + + browse(file); + return; + } + + if (uri == null) { + doShowError(IdeBundle.message("error.malformed.url", url), null, null, null); + } + else { + browse(uri); + } + } + + @Nullable + private static String extractFiles(String url) { + try { + int sharpPos = url.indexOf('#'); + String anchor = ""; + if (sharpPos != -1) { + anchor = url.substring(sharpPos); + url = url.substring(0, sharpPos); + } + + VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url); + if (file == null || !(file.getFileSystem() instanceof JarFileSystem)) return null; + + JarFileSystem jarFileSystem = (JarFileSystem)file.getFileSystem(); + VirtualFile jarVirtualFile = jarFileSystem.getVirtualFileForJar(file); + if (jarVirtualFile == null) return null; + + String targetFilePath = file.getPath(); + String targetFileRelativePath = StringUtil.substringAfter(targetFilePath, JarFileSystem.JAR_SEPARATOR); + LOG.assertTrue(targetFileRelativePath != null); + + String jarVirtualFileLocationHash = jarVirtualFile.getName() + Integer.toHexString(jarVirtualFile.getUrl().hashCode()); + final File outputDir = new File(getExtractedFilesDir(), jarVirtualFileLocationHash); + + final String currentTimestamp = String.valueOf(new File(jarVirtualFile.getPath()).lastModified()); + final File timestampFile = new File(outputDir, ".idea.timestamp"); + + String previousTimestamp = null; + if (timestampFile.exists()) { + previousTimestamp = FileUtilRt.loadFile(timestampFile); + } + + if (!currentTimestamp.equals(previousTimestamp)) { + final Ref extract = new Ref(); + Runnable r = new Runnable() { + @Override + public void run() { + final ConfirmExtractDialog dialog = new ConfirmExtractDialog(); + if (dialog.isToBeShown()) { + dialog.show(); + extract.set(dialog.isOK()); + } + else { + dialog.close(DialogWrapper.OK_EXIT_CODE); + extract.set(true); + } + } + }; + + try { + GuiUtils.runOrInvokeAndWait(r); + } + catch (InvocationTargetException ignored) { + extract.set(false); + } + catch (InterruptedException ignored) { + extract.set(false); + } + + if (!extract.get()) { + return null; + } + + @SuppressWarnings("ConstantConditions") + final ZipFile zipFile = jarFileSystem.getJarFile(file).getZipFile(); + if (zipFile == null) { + return null; + } + ZipEntry entry = zipFile.getEntry(targetFileRelativePath); + if (entry == null) { + return null; + } + InputStream is = zipFile.getInputStream(entry); + try { + ZipUtil.extractEntry(entry, is, outputDir); + } + finally { + is.close(); + } + + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + new Task.Backgroundable(null, "Extracting files...", true) { + @Override + public void run(@NotNull final ProgressIndicator indicator) { + final int size = zipFile.size(); + final int[] counter = new int[]{0}; + + class MyFilter implements FilenameFilter { + private final Set myImportantDirs = new HashSet( + Arrays.asList(outputDir, new File(outputDir, "resources"))); + private final boolean myImportantOnly; + + private MyFilter(boolean importantOnly) { + myImportantOnly = importantOnly; + } + + @Override + public boolean accept(@NotNull File dir, @NotNull String name) { + indicator.checkCanceled(); + boolean result = myImportantOnly == myImportantDirs.contains(dir); + if (result) { + indicator.setFraction(((double)counter[0]) / size); + counter[0]++; + } + return result; + } + } + + try { + ZipUtil.extract(zipFile, outputDir, new MyFilter(true)); + ZipUtil.extract(zipFile, outputDir, new MyFilter(false)); + FileUtil.writeToFile(timestampFile, currentTimestamp.getBytes()); + } + catch (IOException ignore) { + } + } + }.queue(); + } + }); + } + + return VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(new File(outputDir, targetFileRelativePath).getPath())) + anchor; + } + catch (IOException e) { + LOG.warn(e); + Messages.showErrorDialog("Cannot extract files: " + e.getMessage(), "Error"); + return null; + } + } + + private static File getExtractedFilesDir() { + return new File(PathManager.getSystemPath(), "ExtractedFiles"); + } + + public static void clearExtractedFiles() { + FileUtil.delete(getExtractedFilesDir()); + } + + private static class ConfirmExtractDialog extends OptionsDialog { + private ConfirmExtractDialog() { + super(null); + setTitle("Confirmation"); + init(); + } + + @Override + protected boolean isToBeShown() { + return getGeneralSettingsInstance().isConfirmExtractFiles(); + } + + @Override + protected void setToBeShown(boolean value, boolean onOk) { + getGeneralSettingsInstance().setConfirmExtractFiles(value); + } + + @Override + protected boolean shouldSaveOptionsOnCancel() { + return true; + } + + @Override + @NotNull + protected Action[] createActions() { + setOKButtonText(CommonBundle.getYesButtonText()); + return new Action[]{getOKAction(), getCancelAction()}; + } + + @Override + protected JComponent createCenterPanel() { + JPanel panel = new JPanel(new BorderLayout()); + String message = "The files are inside an archive, do you want them to be extracted?"; + JLabel label = new JLabel(message); + + label.setIconTextGap(10); + label.setIcon(Messages.getQuestionIcon()); + + panel.add(label, BorderLayout.CENTER); + panel.add(Box.createVerticalStrut(10), BorderLayout.SOUTH); + + return panel; + } + } + + @Override + public void browse(@NotNull String url, @Nullable WebBrowser browser) { + browse(url, browser, null); + } + + @Override + public void browse(@NotNull String url, @Nullable WebBrowser browser, @Nullable Project project) { + if (browser == null) { + openOrBrowse(url, true); + } + else { + for (UrlOpener urlOpener : UrlOpener.EP_NAME.getExtensions()) { + if (urlOpener.openUrl(browser, url, project)) { + return; + } + } + } + } + + @Override + public boolean browseUsingPath(@Nullable String url, + @Nullable String browserPath, + @Nullable WebBrowser browser, + @Nullable Project project, + @NotNull String... additionalParameters) { + return doLaunch(url, browserPath == null && browser != null ? PathUtil.toSystemDependentName(browser.getPath()) : browserPath, browser, project, additionalParameters); + } + + private boolean doLaunch(@Nullable String url, + @Nullable String browserPath, + @Nullable WebBrowser browser, + @Nullable Project project, + @NotNull String[] additionalParameters) { + if (StringUtil.isEmptyOrSpaces(browserPath)) { + final String error = browser == null ? IdeBundle.message("error.please.specify.path.to.web.browser", CommonBundle.settingsActionPath()) : browser + .getBrowserNotFoundMessage(); + doShowError(error, browser, project, IdeBundle.message("title.browser.not.found")); + return false; + } + + return doLaunch(url, BrowserUtil.getOpenBrowserCommand(browserPath, false), browser, project, additionalParameters); + } + + private boolean doLaunch(@Nullable String url, + @NotNull List command, + @Nullable final WebBrowser browser, + @Nullable final Project project, + String[] additionalParameters) { + GeneralCommandLine commandLine = new GeneralCommandLine(command); + if (url != null) { + commandLine.addParameter(url); + } + + addArgs(commandLine, browser == null ? null : browser.getSpecificSettings(), additionalParameters); + + try { + Process process = commandLine.createProcess(); + checkCreatedProcess(browser, project, commandLine, process); + return true; + } + catch (ExecutionException e) { + doShowError(e.getMessage(), browser, project, null); + return false; + } + } + + protected void checkCreatedProcess(final WebBrowser browser, final Project project, GeneralCommandLine commandLine, final Process process) { + } + + protected void doShowError(final String error, final WebBrowser browser, final Project project, final String title) { + // Not started yet. Not able to show message up. (Could happen in License panel under Linux). + LOG.warn(error); + } + + private static void addArgs(@NotNull GeneralCommandLine command, @Nullable BrowserSpecificSettings settings, @NotNull String[] additional) { + List specific = settings == null ? Collections.emptyList() : settings.getAdditionalParameters(); + if (specific.size() + additional.length > 0) { + if (isOpenCommandUsed(command)) { + if (BrowserUtil.isOpenCommandSupportArgs()) { + command.addParameter("--args"); + } + else { + LOG.warn("'open' command doesn't allow to pass command line arguments so they will be ignored: " + + StringUtil.join(specific, ", ") + " " + Arrays.toString(additional)); + return; + } + } + + command.addParameters(specific); + command.addParameters(additional); + } + } + + protected static boolean isOpenCommandUsed(@NotNull GeneralCommandLine command) { + return SystemInfo.isMac && ExecUtil.getOpenCommandPath().equals(command.getExePath()); + } +} \ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java index 30788880ff66..e35eb60018d9 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java @@ -329,11 +329,13 @@ public class Messages { * @see #showMessageDialog(Component, String, String, Icon) */ public static void showMessageDialog(String message, @NotNull String title, @Nullable Icon icon) { - if (canShowMacSheetPanel()) { - MacMessages.getInstance().showOkMessageDialog(title, message, OK_BUTTON); - return; + try { + if (canShowMacSheetPanel()) { + MacMessages.getInstance().showOkMessageDialog(title, message, OK_BUTTON); + return; + } + }catch (Exception ignored) { } - showDialog(message, title, new String[]{OK_BUTTON}, 0, icon); } diff --git a/platform/platform-impl/src/com/intellij/ide/AppLifecycleListener.java b/platform/platform-impl/src/com/intellij/ide/AppLifecycleListener.java index 0a51e070f9f0..1c4357924d25 100644 --- a/platform/platform-impl/src/com/intellij/ide/AppLifecycleListener.java +++ b/platform/platform-impl/src/com/intellij/ide/AppLifecycleListener.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. @@ -39,22 +39,22 @@ public interface AppLifecycleListener { void appClosing(); abstract class Adapter implements AppLifecycleListener { - public void appFrameCreated(final String[] commandLineArgs, @NotNull final Ref willOpenProject) { - } + @Override + public void appFrameCreated(String[] commandLineArgs, @NotNull Ref willOpenProject) { } - public void appStarting(final Project projectFromCommandLine) { - } + @Override + public void appStarting(Project projectFromCommandLine) { } - public void projectFrameClosed() { - } + @Override + public void projectFrameClosed() { } - public void projectOpenFailed() { - } + @Override + public void projectOpenFailed() { } - public void welcomeScreenDisplayed() { - } + @Override + public void welcomeScreenDisplayed() { } - public void appClosing() { - } + @Override + public void appClosing() { } } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java b/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java index 2ef145f03516..e78f960d6e92 100644 --- a/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java @@ -1,6 +1,6 @@ /* - * 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. @@ -18,6 +18,7 @@ package com.intellij.ide.util; import com.intellij.CommonBundle; import com.intellij.ide.IdeBundle; +import com.intellij.internal.statistic.UsageTrigger; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.impl.DialogWrapperPeerImpl; import org.jetbrains.annotations.NotNull; @@ -63,6 +64,7 @@ public class TipDialog extends DialogWrapper{ public void actionPerformed(ActionEvent e){ myTipPanel.prevTip(); + UsageTrigger.trigger("tips.of.the.day.prev"); } } @@ -74,6 +76,7 @@ public class TipDialog extends DialogWrapper{ public void actionPerformed(ActionEvent e){ myTipPanel.nextTip(); + UsageTrigger.trigger("tips.of.the.day.next"); } } } diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/UiInfoUsageCollector.java b/platform/platform-impl/src/com/intellij/internal/statistic/UiInfoUsageCollector.java index e244a25e9b6c..d410a66b7cbf 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/UiInfoUsageCollector.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/UiInfoUsageCollector.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,6 +15,7 @@ */ package com.intellij.internal.statistic; +import com.intellij.ide.GeneralSettings; import com.intellij.ide.ui.UISettings; import com.intellij.internal.statistic.beans.GroupDescriptor; import com.intellij.internal.statistic.beans.UsageDescriptor; @@ -60,6 +61,7 @@ public class UiInfoUsageCollector extends UsagesCollector { add(set, "Tabs Left", tabPlace() == SwingConstants.LEFT ? 1 : 0); add(set, "Tabs Right", tabPlace() == SwingConstants.RIGHT ? 1 : 0); add(set, "Retina", UIUtil.isRetina() ? 1 : 0); + add(set, "Show tips on startup", GeneralSettings.getInstance().showTipsOnStartup() ? 1 : 0); return set; } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java index 6cca11c2f737..41a0f691b56c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.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,6 +19,7 @@ import com.intellij.ide.ui.search.ConfigurableHit; import com.intellij.ide.ui.search.SearchUtil; import com.intellij.ide.ui.search.SearchableOptionsRegistrar; import com.intellij.ide.util.PropertiesComponent; +import com.intellij.internal.statistic.UsageTrigger; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.AnActionListener; @@ -775,6 +776,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat for (Configurable each : modified) { try { each.apply(); + UsageTrigger.trigger("ide.settings." + each.getDisplayName().replace(" ", "_")); if (!each.isModified()) { getContext().fireModifiedRemoved(each, null); } diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java index a53c2b3f29be..edeac1746e12 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.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,13 @@ */ package com.intellij.openapi.updateSettings.impl; +import com.intellij.ide.AppLifecycleListener; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PluginsAdvertiser; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Alarm; import com.intellij.util.text.DateFormatUtil; @@ -44,14 +47,22 @@ public class UpdateCheckerComponent implements ApplicationComponent { }; private final UpdateSettings mySettings; - public UpdateCheckerComponent(@NotNull UpdateSettings settings) { + public UpdateCheckerComponent(@NotNull Application app, @NotNull UpdateSettings settings) { mySettings = settings; + app.getMessageBus().connect(app).subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() { + @Override + public void appFrameCreated(String[] commandLineArgs, @NotNull Ref willOpenProject) { + scheduleOnStartCheck(); + } + }); } @Override public void initComponent() { PluginsAdvertiser.ensureDeleted(); + } + private void scheduleOnStartCheck() { if (!mySettings.CHECK_NEEDED) { return; } diff --git a/platform/platform-resources/src/checkedPlugins.txt b/platform/platform-resources/src/checkedPlugins.txt new file mode 100644 index 000000000000..b1b8b2b1d2b7 --- /dev/null +++ b/platform/platform-resources/src/checkedPlugins.txt @@ -0,0 +1,15 @@ +org.intellij.scala +org.jetbrains.kotlin +org.jetbrains.plugins.ruby +com.jetbrains.php +org.intellij.clojure +NodeJS +com.jetbrains.lang.ejs +com.jetbrains.twig +Karma +org.jetbrains.kannotator +com.intellij.plugins.watcher +SBT +JSTestDriver Plugin +com.jetbrains.chronon +AngularJS diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogUiProperties.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogUiProperties.java index 1955bfbba67e..05c8bda79a1f 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogUiProperties.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogUiProperties.java @@ -41,6 +41,7 @@ public class VcsLogUiProperties implements PersistentStateComponent RECENTLY_FILTERED_USER_GROUPS = new ArrayDeque(); public Deque RECENTLY_FILTERED_BRANCH_GROUPS = new ArrayDeque(); } @@ -108,6 +109,14 @@ public class VcsLogUiProperties implements PersistentStateComponent users = new ArrayList(); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java index 4018c34b884b..43de441ca3e0 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java @@ -43,6 +43,7 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { @NotNull private final VcsLogColorManager myColorManager; @NotNull private final VcsLogFilterer myFilterer; @NotNull private final VcsLog myLog; + @NotNull private final VcsLogUiProperties myUiProperties; @NotNull private final Collection myFilterChangeListeners = ContainerUtil.newArrayList(); @@ -53,6 +54,7 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { myLogDataHolder = logDataHolder; myProject = project; myColorManager = manager; + myUiProperties = uiProperties; myDataPack = initialDataPack; Disposer.register(logDataHolder, this); @@ -152,6 +154,7 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { public void setLongEdgeVisibility(boolean visibility) { handleAnswer(myDataPack.getGraphFacade().performAction(LongEdgesAction.valueOf(visibility))); + myUiProperties.setLongEdgesVisibility(visibility); } public boolean areLongEdgesHidden() { @@ -288,6 +291,7 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { myDataPack = dataPack; setModel(newModel, myDataPack, previouslySelected); myMainFrame.updateDataPack(myDataPack); + setLongEdgeVisibility(myUiProperties.areLongEdgesVisible()); fireFilterChangeEvent(); repaintUI(); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultilinePopupBuilder.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultilinePopupBuilder.java index 44baa2cc5da6..0f21be4fc516 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultilinePopupBuilder.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultilinePopupBuilder.java @@ -95,10 +95,11 @@ class MultilinePopupBuilder { @NotNull Collection getSelectedValues() { - return ContainerUtil.map(StringUtil.tokenize(myTextField.getText(), new String(SEPARATORS)), new Function() { + return ContainerUtil.mapNotNull(StringUtil.tokenize(myTextField.getText(), new String(SEPARATORS)), new Function() { @Override public String fun(String value) { - return value.trim(); + String trimmed = value.trim(); + return trimmed.isEmpty() ? null : trimmed; } }); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java index 2406df3c1463..07febd5bc34c 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java @@ -107,11 +107,11 @@ class UserFilterPopupComponent extends MultipleValueFilterPopupComponent() { @Override public String fun(String user) { - VcsUser vcsUser = myData.get(root); - if (vcsUser == null) { - return null; + if (ME.equals(user)) { + VcsUser vcsUser = myData.get(root); + return vcsUser == null ? null : vcsUser.getName(); } - return ME.equals(user) ? vcsUser.getName() : user; + return user; } }); } diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubNotifications.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubNotifications.java index d2edabdf4be3..7d5abd8b9582 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubNotifications.java +++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubNotifications.java @@ -30,8 +30,6 @@ import static org.jetbrains.plugins.github.util.GithubUtil.getErrorTextFromExcep public class GithubNotifications { private static final Logger LOG = GithubUtil.LOG; - private static final String GITHUB_NOTIFICATION_GROUP = "github"; - public static void showInfo(@NotNull Project project, @NotNull String title, @NotNull String message) { LOG.info(title + "; " + message); VcsNotifier.getInstance(project).notifyImportantInfo(title, message); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java index bbdd353b51a4..4d24e33fc332 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java @@ -49,6 +49,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature; import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature; import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; @@ -1244,7 +1245,7 @@ public class PsiUtil { } public static boolean isCompileStatic(PsiElement e) { - PsiMember containingMember = PsiTreeUtil.getParentOfType(e, PsiMember.class, false); + PsiMember containingMember = PsiTreeUtil.getParentOfType(e, PsiMember.class, false, GrAnnotation.class); return containingMember != null && GroovyPsiManager.getInstance(containingMember.getProject()).isCompileStatic(containingMember); } diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java index 3e21ac0efe8e..1dd8e0caca18 100644 --- a/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java @@ -15,448 +15,23 @@ */ package com.intellij.ide.browsers; -import com.intellij.CommonBundle; -import com.intellij.Patches; import com.intellij.concurrency.JobScheduler; -import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.util.ExecUtil; -import com.intellij.ide.BrowserUtil; -import com.intellij.ide.GeneralSettings; import com.intellij.ide.IdeBundle; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.ShowSettingsUtil; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Ref; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.*; import com.intellij.ui.AppUIUtil; -import com.intellij.ui.GuiUtils; -import com.intellij.util.ArrayUtil; -import com.intellij.util.PathUtil; -import com.intellij.util.io.ZipUtil; -import com.intellij.util.ui.OptionsDialog; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import javax.swing.*; -import java.awt.*; -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.InvocationTargetException; -import java.net.URI; -import java.util.*; -import java.util.List; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -final class BrowserLauncherImpl extends BrowserLauncher { - private static final Logger LOG = Logger.getInstance(BrowserLauncherImpl.class); - - private static boolean isDesktopActionSupported(Desktop.Action action) { - return !Patches.SUN_BUG_ID_6457572 && !Patches.SUN_BUG_ID_6486393 && - Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(action); - } - - public static boolean canStartDefaultBrowser() { - return isDesktopActionSupported(Desktop.Action.BROWSE) || - SystemInfo.isMac || SystemInfo.isWindows || - SystemInfo.isUnix && SystemInfo.hasXdgOpen(); - } - - private static GeneralSettings getGeneralSettingsInstance() { - if (ApplicationManager.getApplication() != null) { - GeneralSettings settings = GeneralSettings.getInstance(); - if (settings != null) { - return settings; - } - } - - return new GeneralSettings(); - } - - @Nullable - private static List getDefaultBrowserCommand() { - if (SystemInfo.isWindows) { - return Arrays.asList(ExecUtil.getWindowsShellName(), "/c", "start", GeneralCommandLine.inescapableQuote("")); - } - else if (SystemInfo.isMac) { - return Collections.singletonList(ExecUtil.getOpenCommandPath()); - } - else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen()) { - return Collections.singletonList("xdg-open"); - } - else { - return null; - } - } +final class BrowserLauncherImpl extends BrowserLauncherAppless { @Override - public void open(@NotNull String url) { - openOrBrowse(url, false); - } - - @Override - public void browse(@NotNull File file) { - browse(VfsUtil.toUri(file)); - } - - @Override - public void browse(@NotNull URI uri) { - LOG.debug("Launch browser: [" + uri + "]"); - - GeneralSettings settings = getGeneralSettingsInstance(); - if (settings.isUseDefaultBrowser()) { - if (isDesktopActionSupported(Desktop.Action.BROWSE)) { - try { - Desktop.getDesktop().browse(uri); - LOG.debug("Browser launched using JDK 1.6 API"); - return; - } - catch (Exception e) { - LOG.warn("Error while using Desktop API, fallback to CLI", e); - } - } - - List command = getDefaultBrowserCommand(); - if (command != null) { - doLaunch(uri.toString(), command, null, null, ArrayUtil.EMPTY_STRING_ARRAY); - return; - } - } - - browseUsingPath(uri.toString(), settings.getBrowserPath(), null, null); - } - - private void openOrBrowse(@NotNull String url, boolean browse) { - url = url.trim(); - - if (url.startsWith("jar:")) { - String files = extractFiles(url); - if (files == null) { - return; - } - url = files; - } - - URI uri; - if (BrowserUtil.isAbsoluteURL(url)) { - uri = VfsUtil.toUri(url); - } - else { - File file = new File(url); - if (!browse && isDesktopActionSupported(Desktop.Action.OPEN)) { - try { - Desktop.getDesktop().open(file); - return; - } - catch (IOException e) { - LOG.debug(e); - } - } - - browse(file); - return; - } - - if (uri == null) { - showError(IdeBundle.message("error.malformed.url", url), null, null, null); - } - else { - browse(uri); - } - } - - @Nullable - private static String extractFiles(String url) { - try { - int sharpPos = url.indexOf('#'); - String anchor = ""; - if (sharpPos != -1) { - anchor = url.substring(sharpPos); - url = url.substring(0, sharpPos); - } - - VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url); - if (file == null || !(file.getFileSystem() instanceof JarFileSystem)) return null; - - JarFileSystem jarFileSystem = (JarFileSystem)file.getFileSystem(); - VirtualFile jarVirtualFile = jarFileSystem.getVirtualFileForJar(file); - if (jarVirtualFile == null) return null; - - String targetFilePath = file.getPath(); - String targetFileRelativePath = StringUtil.substringAfter(targetFilePath, JarFileSystem.JAR_SEPARATOR); - LOG.assertTrue(targetFileRelativePath != null); - - String jarVirtualFileLocationHash = jarVirtualFile.getName() + Integer.toHexString(jarVirtualFile.getUrl().hashCode()); - final File outputDir = new File(getExtractedFilesDir(), jarVirtualFileLocationHash); - - final String currentTimestamp = String.valueOf(new File(jarVirtualFile.getPath()).lastModified()); - final File timestampFile = new File(outputDir, ".idea.timestamp"); - - String previousTimestamp = null; - if (timestampFile.exists()) { - previousTimestamp = FileUtilRt.loadFile(timestampFile); - } - - if (!currentTimestamp.equals(previousTimestamp)) { - final Ref extract = new Ref(); - Runnable r = new Runnable() { - @Override - public void run() { - final ConfirmExtractDialog dialog = new ConfirmExtractDialog(); - if (dialog.isToBeShown()) { - dialog.show(); - extract.set(dialog.isOK()); - } - else { - dialog.close(DialogWrapper.OK_EXIT_CODE); - extract.set(true); - } - } - }; - - try { - GuiUtils.runOrInvokeAndWait(r); - } - catch (InvocationTargetException ignored) { - extract.set(false); - } - catch (InterruptedException ignored) { - extract.set(false); - } - - if (!extract.get()) { - return null; - } - - @SuppressWarnings("ConstantConditions") - final ZipFile zipFile = jarFileSystem.getJarFile(file).getZipFile(); - if (zipFile == null) { - return null; - } - ZipEntry entry = zipFile.getEntry(targetFileRelativePath); - if (entry == null) { - return null; - } - InputStream is = zipFile.getInputStream(entry); - try { - ZipUtil.extractEntry(entry, is, outputDir); - } - finally { - is.close(); - } - - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - new Task.Backgroundable(null, "Extracting files...", true) { - @Override - public void run(@NotNull final ProgressIndicator indicator) { - final int size = zipFile.size(); - final int[] counter = new int[]{0}; - - class MyFilter implements FilenameFilter { - private final Set myImportantDirs = new HashSet( - Arrays.asList(outputDir, new File(outputDir, "resources"))); - private final boolean myImportantOnly; - - private MyFilter(boolean importantOnly) { - myImportantOnly = importantOnly; - } - - @Override - public boolean accept(@NotNull File dir, @NotNull String name) { - indicator.checkCanceled(); - boolean result = myImportantOnly == myImportantDirs.contains(dir); - if (result) { - indicator.setFraction(((double)counter[0]) / size); - counter[0]++; - } - return result; - } - } - - try { - ZipUtil.extract(zipFile, outputDir, new MyFilter(true)); - ZipUtil.extract(zipFile, outputDir, new MyFilter(false)); - FileUtil.writeToFile(timestampFile, currentTimestamp.getBytes()); - } - catch (IOException ignore) { - } - } - }.queue(); - } - }); - } - - return VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(new File(outputDir, targetFileRelativePath).getPath())) + anchor; - } - catch (IOException e) { - LOG.warn(e); - Messages.showErrorDialog("Cannot extract files: " + e.getMessage(), "Error"); - return null; - } - } - - private static File getExtractedFilesDir() { - return new File(PathManager.getSystemPath(), "ExtractedFiles"); - } - - public static void clearExtractedFiles() { - FileUtil.delete(getExtractedFilesDir()); - } - - private static class ConfirmExtractDialog extends OptionsDialog { - private ConfirmExtractDialog() { - super(null); - setTitle("Confirmation"); - init(); - } - - @Override - protected boolean isToBeShown() { - return getGeneralSettingsInstance().isConfirmExtractFiles(); - } - - @Override - protected void setToBeShown(boolean value, boolean onOk) { - getGeneralSettingsInstance().setConfirmExtractFiles(value); - } - - @Override - protected boolean shouldSaveOptionsOnCancel() { - return true; - } - - @Override - @NotNull - protected Action[] createActions() { - setOKButtonText(CommonBundle.getYesButtonText()); - return new Action[]{getOKAction(), getCancelAction()}; - } - - @Override - protected JComponent createCenterPanel() { - JPanel panel = new JPanel(new BorderLayout()); - String message = "The files are inside an archive, do you want them to be extracted?"; - JLabel label = new JLabel(message); - - label.setIconTextGap(10); - label.setIcon(Messages.getQuestionIcon()); - - panel.add(label, BorderLayout.CENTER); - panel.add(Box.createVerticalStrut(10), BorderLayout.SOUTH); - - return panel; - } - } - - @Override - public void browse(@NotNull String url, @Nullable WebBrowser browser) { - browse(url, browser, null); - } - - @Override - public void browse(@NotNull String url, @Nullable WebBrowser browser, @Nullable Project project) { - if (browser == null) { - openOrBrowse(url, true); - } - else { - for (UrlOpener urlOpener : UrlOpener.EP_NAME.getExtensions()) { - if (urlOpener.openUrl(browser, url, project)) { - return; - } - } - } - } - - @Override - public boolean browseUsingPath(@Nullable String url, - @Nullable String browserPath, - @Nullable WebBrowser browser, - @Nullable Project project, - @NotNull String... additionalParameters) { - return doLaunch(url, browserPath == null && browser != null ? PathUtil.toSystemDependentName(browser.getPath()) : browserPath, browser, project, additionalParameters); - } - - private static boolean doLaunch(@Nullable String url, - @Nullable String browserPath, - @Nullable WebBrowser browser, - @Nullable Project project, - @NotNull String[] additionalParameters) { - if (StringUtil.isEmptyOrSpaces(browserPath)) { - showError(browser == null ? IdeBundle.message("error.please.specify.path.to.web.browser", CommonBundle.settingsActionPath()) : browser - .getBrowserNotFoundMessage(), browser, project, IdeBundle.message("title.browser.not.found")); - return false; - } - - return doLaunch(url, BrowserUtil.getOpenBrowserCommand(browserPath, false), browser, project, additionalParameters); - } - - private static boolean doLaunch(@Nullable String url, - @NotNull List command, - @Nullable final WebBrowser browser, - @Nullable final Project project, - String[] additionalParameters) { - GeneralCommandLine commandLine = new GeneralCommandLine(command); - if (url != null) { - commandLine.addParameter(url); - } - - addArgs(commandLine, browser == null ? null : browser.getSpecificSettings(), additionalParameters); - - try { - final Process process = commandLine.createProcess(); - if (isOpenCommandUsed(commandLine)) { - final Future future = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { - @Override - public void run() { - try { - if (process.waitFor() == 1) { - showError(ExecUtil.readFirstLine(process.getErrorStream(), null), browser, project, null); - } - } - catch (InterruptedException ignored) { - } - } - }); - // 30 seconds is enough to start - JobScheduler.getScheduler().schedule(new Runnable() { - @Override - public void run() { - future.cancel(true); - } - }, 30, TimeUnit.MILLISECONDS); - } - return true; - } - catch (ExecutionException e) { - showError(e.getMessage(), browser, project, null); - return false; - } - } - - public static void showError(@Nullable final String error, @Nullable final WebBrowser browser, @Nullable final Project project, @Nullable final String title) { - if (ApplicationManager.getApplication() == null) { - LOG.warn(error); - // Not started yet. Not able to show message up. (Could happen in License panel under Linux). - return; - } - + protected void doShowError(final String error, final WebBrowser browser, final Project project, final String title) { AppUIUtil.invokeOnEdt(new Runnable() { @Override public void run() { @@ -475,26 +50,28 @@ final class BrowserLauncherImpl extends BrowserLauncher { }); } - private static void addArgs(@NotNull GeneralCommandLine command, @Nullable BrowserSpecificSettings settings, @NotNull String[] additional) { - List specific = settings == null ? Collections.emptyList() : settings.getAdditionalParameters(); - if (specific.size() + additional.length > 0) { - if (isOpenCommandUsed(command)) { - if (BrowserUtil.isOpenCommandSupportArgs()) { - command.addParameter("--args"); + @Override + protected void checkCreatedProcess(final WebBrowser browser, final Project project, GeneralCommandLine commandLine, final Process process) { + if (isOpenCommandUsed(commandLine)) { + final Future future = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + try { + if (process.waitFor() == 1) { + doShowError(ExecUtil.readFirstLine(process.getErrorStream(), null), browser, project, null); + } + } + catch (InterruptedException ignored) { + } } - else { - LOG.warn("'open' command doesn't allow to pass command line arguments so they will be ignored: " + - StringUtil.join(specific, ", ") + " " + Arrays.toString(additional)); - return; + }); + // 30 seconds is enough to start + JobScheduler.getScheduler().schedule(new Runnable() { + @Override + public void run() { + future.cancel(true); } - } - - command.addParameters(specific); - command.addParameters(additional); + }, 30, TimeUnit.MILLISECONDS); } } - - private static boolean isOpenCommandUsed(@NotNull GeneralCommandLine command) { - return SystemInfo.isMac && ExecUtil.getOpenCommandPath().equals(command.getExePath()); - } } \ No newline at end of file diff --git a/xml/impl/src/com/intellij/ide/browsers/StartBrowserPanel.java b/xml/impl/src/com/intellij/ide/browsers/StartBrowserPanel.java index fe2163e2feb3..da9898207e9a 100644 --- a/xml/impl/src/com/intellij/ide/browsers/StartBrowserPanel.java +++ b/xml/impl/src/com/intellij/ide/browsers/StartBrowserPanel.java @@ -8,6 +8,7 @@ import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.ui.TextBrowseFolderListener; import com.intellij.openapi.ui.TextFieldWithBrowseButton; @@ -53,7 +54,10 @@ public class StartBrowserPanel { @Override public void consume(DataContext context) { Project project = CommonDataKeys.PROJECT.getData(context); - assert project != null; + if (project == null) { + // IDEA-118202 + project = ProjectManager.getInstance().getDefaultProject(); + } setupUrlField(myUrlField, project); } });