diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/QuickEvaluateActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/QuickEvaluateActionHandler.java index d67b2bf45572..6eedff4136ea 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/QuickEvaluateActionHandler.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/QuickEvaluateActionHandler.java @@ -21,34 +21,37 @@ package com.intellij.debugger.actions; import com.intellij.debugger.DebuggerManagerEx; -import com.intellij.debugger.settings.DebuggerSettings; import com.intellij.debugger.impl.DebuggerSession; +import com.intellij.debugger.settings.DebuggerSettings; import com.intellij.debugger.ui.ValueHint; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler; import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint; +import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler; import com.intellij.xdebugger.impl.evaluate.quick.common.ValueHintType; import org.jetbrains.annotations.NotNull; import java.awt.*; public class QuickEvaluateActionHandler extends QuickEvaluateHandler { - + @Override public boolean isEnabled(@NotNull final Project project) { DebuggerSession debuggerSession = DebuggerManagerEx.getInstanceEx(project).getContext().getDebuggerSession(); return debuggerSession != null && debuggerSession.isPaused(); } + @Override public AbstractValueHint createValueHint(@NotNull final Project project, @NotNull final Editor editor, @NotNull final Point point, final ValueHintType type) { return ValueHint.createValueHint(project, editor, point, type); } + @Override public boolean canShowHint(@NotNull final Project project) { DebuggerSession debuggerSession = DebuggerManagerEx.getInstanceEx(project).getContext().getDebuggerSession(); return debuggerSession != null && debuggerSession.isAttached(); } + @Override public int getValueLookupDelay(final Project project) { return DebuggerSettings.getInstance().VALUE_LOOKUP_DELAY; } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java index af5202ccd260..46f1515f1ea5 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java @@ -71,61 +71,73 @@ public class JavaDebuggerSupport extends DebuggerSupport { private final DebuggerActionHandler myAddToWatchedActionHandler = new AddToWatchActionHandler(); private final JavaMarkObjectActionHandler myMarkObjectActionHandler = new JavaMarkObjectActionHandler(); + @Override @NotNull public BreakpointPanelProvider getBreakpointPanelProvider() { return myBreakpointPanelProvider; } + @Override @NotNull public DebuggerActionHandler getStepOverHandler() { return myStepOverActionHandler; } + @Override @NotNull public DebuggerActionHandler getStepIntoHandler() { return myStepIntoActionHandler; } + @Override @NotNull public DebuggerActionHandler getSmartStepIntoHandler() { return mySmartStepIntoHandler; } + @Override @NotNull public DebuggerActionHandler getStepOutHandler() { return myStepOutActionHandler; } + @Override @NotNull public DebuggerActionHandler getForceStepOverHandler() { return myForceStepOverActionHandler; } + @Override @NotNull public DebuggerActionHandler getForceStepIntoHandler() { return myForceStepIntoActionHandler; } + @Override @NotNull public DebuggerActionHandler getRunToCursorHandler() { return myRunToCursorActionHandler; } + @Override @NotNull public DebuggerActionHandler getForceRunToCursorHandler() { return myForceRunToCursorActionHandler; } + @Override @NotNull public DebuggerActionHandler getResumeActionHandler() { return myResumeActionHandler; } + @Override @NotNull public DebuggerActionHandler getPauseHandler() { return myPauseActionHandler; } + @Override @NotNull public DebuggerActionHandler getToggleLineBreakpointHandler() { return DISABLED; @@ -137,16 +149,19 @@ public class JavaDebuggerSupport extends DebuggerSupport { return DISABLED; } + @Override @NotNull public DebuggerActionHandler getShowExecutionPointHandler() { return myShowExecutionPointActionHandler; } + @Override @NotNull public DebuggerActionHandler getEvaluateHandler() { return myEvaluateActionHandler; } + @Override @NotNull public QuickEvaluateHandler getQuickEvaluateHandler() { return myQuickEvaluateHandler; @@ -158,6 +173,7 @@ public class JavaDebuggerSupport extends DebuggerSupport { return myAddToWatchedActionHandler; } + @Override @NotNull public DebuggerToggleActionHandler getMuteBreakpointsHandler() { return myMuteBreakpointsHandler; @@ -181,6 +197,7 @@ public class JavaDebuggerSupport extends DebuggerSupport { return DISABLED_EDIT; } + @Override @NotNull public DebuggerSettingsPanelProvider getSettingsPanelProvider() { return myDebuggerSettingsPanelProvider; @@ -233,10 +250,12 @@ public class JavaDebuggerSupport extends DebuggerSupport { //} } + @Override public int getPriority() { return 100; } + @Override public Breakpoint findBreakpoint(@NotNull final Project project, @NotNull final Document document, final int offset) { return null; //return DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().findBreakpoint(document, offset, null); @@ -253,6 +272,7 @@ public class JavaDebuggerSupport extends DebuggerSupport { return null; } + @Override public void onDialogClosed(final Project project) { //DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().updateAllRequests(); } @@ -308,6 +328,7 @@ public class JavaDebuggerSupport extends DebuggerSupport { } public static class JavaDebuggerSettingsPanelProvider extends DebuggerSettingsPanelProvider { + @Override public int getPriority() { return 1; } @@ -317,6 +338,7 @@ public class JavaDebuggerSupport extends DebuggerSupport { return new DebuggerLaunchingConfigurable(); } + @Override public Collection getConfigurables() { final ArrayList configurables = new ArrayList(); configurables.add(new DebuggerDataViewsConfigurable(null)); @@ -326,6 +348,7 @@ public class JavaDebuggerSupport extends DebuggerSupport { return configurables; } + @Override public void apply() { NodeRendererSettings.getInstance().fireRenderersChanged(); } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java index 1b9aef229e41..8cd1bfbe8151 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java @@ -42,13 +42,12 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; import com.intellij.psi.jsp.JspFile; import com.intellij.ui.classFilter.ClassFilter; import com.intellij.util.StringBuilderSpinAllocator; import com.intellij.xdebugger.XDebuggerManager; -import com.intellij.xdebugger.XDebuggerUtil; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.breakpoints.XBreakpoint; import com.intellij.xdebugger.breakpoints.XBreakpointManager; @@ -296,8 +295,8 @@ public abstract class BreakpointWithHighlighter

public final XDebuggerEditorsProvider getEditorsProvider(@NotNull XBreakpoint breakpoint, @NotNull Project project) { return new JavaDebuggerEditorsProvider(); } + + @Nullable + @Override + public XSourcePosition getSourcePosition(@NotNull XBreakpoint breakpoint) { + BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(JavaDebuggerSupport.getCurrentProject()).getBreakpointManager(); + Breakpoint javaBreakpoint = breakpointManager.findBreakpoint(breakpoint); + if (javaBreakpoint != null) { + PsiClass aClass = javaBreakpoint.getPsiClass(); + if (aClass != null && aClass.getContainingFile() != null) { + return XDebuggerUtil.getInstance().createPositionByOffset(aClass.getContainingFile().getVirtualFile(), aClass.getTextOffset()); + } + } + return null; + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java index fb529f6534a2..e773b53f5ee5 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java @@ -23,13 +23,17 @@ import com.intellij.debugger.engine.DebuggerManagerThreadImpl; import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; import com.intellij.debugger.engine.requests.RequestManagerImpl; +import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.icons.AllIcons; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.StringBuilderSpinAllocator; import com.intellij.xdebugger.breakpoints.XBreakpoint; import com.sun.jdi.AbsentInformationException; @@ -83,7 +87,11 @@ public class WildcardMethodBreakpoint extends Breakpoint() { + public PsiClass compute() { + return getClassName() != null ? DebuggerUtilsEx.findClass(getClassName(), myProject, GlobalSearchScope.allScope(myProject)) : null; + } + }); } public String getDisplayName() { 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 b9c5d21bcd5e..a5104f1deb51 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 @@ -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. @@ -33,10 +33,11 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; -import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import static com.intellij.util.ObjectUtils.assertNotNull; + public class AddTypeCastFix extends LocalQuickFixAndIntentionActionOnPsiElement { private final PsiType myType; @@ -75,28 +76,26 @@ public class AddTypeCastFix extends LocalQuickFixAndIntentionActionOnPsiElement addTypeCast(project, (PsiExpression)startElement, myType); } - private static void addTypeCast(Project project, PsiExpression originalExpression, PsiType type) throws IncorrectOperationException { + private static void addTypeCast(Project project, PsiExpression originalExpression, PsiType type) { PsiExpression typeCast = createCastExpression(originalExpression, project, type); originalExpression.replace(typeCast); } - static PsiExpression createCastExpression(PsiExpression originalExpression, Project project, PsiType type) throws IncorrectOperationException { + static PsiExpression createCastExpression(PsiExpression originalExpression, Project project, PsiType type) { // remove nested casts - PsiElement element = PsiUtil.deparenthesizeExpression(originalExpression); - if (element == null){ - return null; - } + PsiElement expression = PsiUtil.deparenthesizeExpression(originalExpression); + if (expression == null) return null; + PsiElementFactory factory = JavaPsiFacade.getInstance(originalExpression.getProject()).getElementFactory(); - PsiTypeCastExpression typeCast = (PsiTypeCastExpression)factory.createExpressionFromText("(Type)value", null); + assertNotNull(typeCast.getCastType()).replace(factory.createTypeElement(type)); typeCast = (PsiTypeCastExpression)CodeStyleManager.getInstance(project).reformat(typeCast); - typeCast.getCastType().replace(factory.createTypeElement(type)); - if (element instanceof PsiConditionalExpression) { - // we'd better cast one branch of ternary expression if we could - PsiConditionalExpression expression = (PsiConditionalExpression)element.copy(); - PsiExpression thenE = expression.getThenExpression(); - PsiExpression elseE = expression.getElseExpression(); + if (expression instanceof PsiConditionalExpression) { + // we'd better cast one branch of ternary expression if we can + PsiConditionalExpression conditional = (PsiConditionalExpression)expression.copy(); + PsiExpression thenE = conditional.getThenExpression(); + PsiExpression elseE = conditional.getElseExpression(); PsiType thenType = thenE == null ? null : thenE.getType(); PsiType elseType = elseE == null ? null : elseE.getType(); if (elseType != null && thenType != null) { @@ -104,18 +103,20 @@ public class AddTypeCastFix extends LocalQuickFixAndIntentionActionOnPsiElement boolean replaceElse = !TypeConversionUtil.isAssignable(type, elseType); if (replaceThen != replaceElse) { if (replaceThen) { - typeCast.getOperand().replace(thenE); + assertNotNull(typeCast.getOperand()).replace(thenE); thenE.replace(typeCast); } else { - typeCast.getOperand().replace(elseE); + assertNotNull(typeCast.getOperand()).replace(elseE); elseE.replace(typeCast); } - return expression; + return conditional; } } } - typeCast.getOperand().replace(element); + + assertNotNull(typeCast.getOperand()).replace(expression); + return typeCast; } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java index db020ad58b8b..42d3098b7b07 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java @@ -60,6 +60,12 @@ public class JavaReferenceAdjuster implements ReferenceAdjuster { } if (rightKind) { + // annotations may jump out of reference (see PsiJavaCodeReferenceImpl#setAnnotations()) so they should be processed first + List annotations = PsiTreeUtil.getChildrenOfTypeAsList(ref, PsiAnnotation.class); + for (PsiAnnotation annotation : annotations) { + process(annotation.getNode(), addImports, incompleteCode, useFqInJavadoc, useFqInCode); + } + boolean isInsideDocComment = TreeUtil.findParent(element, JavaDocElementType.DOC_COMMENT) != null; boolean isShort = !ref.isQualified(); if (isInsideDocComment ? !useFqInJavadoc : !useFqInCode) { diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java index f6cdabacedad..0004ff456cb6 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ package com.intellij.refactoring.typeMigration; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.impl.PsiDiamondTypeUtil; import com.intellij.psi.impl.source.tree.ChildRole; import com.intellij.psi.impl.source.tree.CompositeElement; @@ -109,18 +110,19 @@ public class TypeMigrationReplacementUtil { if (!migratedType.isValid()) { migratedType = JavaPsiFacade.getElementFactory(project).createTypeByFQClassName(migratedType.getCanonicalText()); } - final PsiTypeElement typeElement = - JavaPsiFacade.getInstance(project).getElementFactory().createTypeElement(migratedType); + final PsiTypeElement typeElement = JavaPsiFacade.getInstance(project).getElementFactory().createTypeElement(migratedType); if (element instanceof PsiMethod) { final PsiTypeElement returnTypeElement = ((PsiMethod)element).getReturnTypeElement(); if (returnTypeElement != null) { - returnTypeElement.replace(typeElement); + final PsiElement replaced = returnTypeElement.replace(typeElement); + JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced); } } else if (element instanceof PsiVariable) { final PsiTypeElement varTypeElement = ((PsiVariable)element).getTypeElement(); if (varTypeElement != null) { - varTypeElement.replace(typeElement); + final PsiElement replaced = varTypeElement.replace(typeElement); + JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced); } } else { diff --git a/java/java-psi-api/src/com/intellij/psi/PsiArrayType.java b/java/java-psi-api/src/com/intellij/psi/PsiArrayType.java index bc61565bdc6c..47bd7be64c65 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiArrayType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiArrayType.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. @@ -16,7 +16,6 @@ package com.intellij.psi; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; /** @@ -24,7 +23,7 @@ import org.jetbrains.annotations.NotNull; * * @author max */ -public class PsiArrayType extends PsiType { +public class PsiArrayType extends PsiType.Stub { private final PsiType myComponentType; /** @@ -44,19 +43,33 @@ public class PsiArrayType extends PsiType { @NotNull @Override public String getPresentableText() { - return StringUtil.join(myComponentType.getPresentableText(), getAnnotationsTextPrefix(false, true, true), "[]"); + return getText(myComponentType.getPresentableText(), "[]", false, true); } @NotNull @Override - public String getCanonicalText() { - return StringUtil.join(myComponentType.getCanonicalText(), "[]"); + public String getCanonicalText(boolean annotated) { + return getText(myComponentType.getCanonicalText(annotated), "[]", true, annotated); } @NotNull @Override public String getInternalCanonicalText() { - return StringUtil.join(myComponentType.getInternalCanonicalText(), getAnnotationsTextPrefix(true, true, true), "[]"); + return getText(myComponentType.getInternalCanonicalText(), "[]", true, true); + } + + protected String getText(@NotNull String prefix, @NotNull String suffix, boolean qualified, boolean annotated) { + StringBuilder sb = new StringBuilder(prefix.length() + suffix.length()); + sb.append(prefix); + if (annotated) { + PsiAnnotation[] annotations = getAnnotations(); + if (annotations.length != 0) { + sb.append(' '); + PsiNameHelper.appendAnnotations(sb, annotations, qualified); + } + } + sb.append(suffix); + return sb.toString(); } @Override diff --git a/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java b/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java index 6de8d0202bef..8130b864ad9a 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java @@ -23,7 +23,7 @@ import org.jetbrains.annotations.Nullable; /** * @author ven */ -public class PsiCapturedWildcardType extends PsiType { +public class PsiCapturedWildcardType extends PsiType.Stub { @NotNull private final PsiWildcardType myExistential; @NotNull private final PsiElement myContext; @Nullable private final PsiTypeParameter myParameter; @@ -78,8 +78,8 @@ public class PsiCapturedWildcardType extends PsiType { @NotNull @Override - public String getCanonicalText() { - return myExistential.getCanonicalText(); + public String getCanonicalText(boolean annotated) { + return myExistential.getCanonicalText(annotated); } @NotNull diff --git a/java/java-psi-api/src/com/intellij/psi/PsiClassType.java b/java/java-psi-api/src/com/intellij/psi/PsiClassType.java index 30d9570048a7..722b9e2816a2 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiClassType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiClassType.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. @@ -280,4 +280,23 @@ public abstract class PsiClassType extends PsiType { } }; } + + /** + * Temporary class to facilitate transition to {@link #getCanonicalText(boolean)}. + */ + public static abstract class Stub extends PsiClassType { + protected Stub(LanguageLevel languageLevel, @NotNull PsiAnnotation[] annotations) { + super(languageLevel, annotations); + } + + @NotNull + @Override + public final String getCanonicalText() { + return getCanonicalText(false); + } + + @NotNull + @Override + public abstract String getCanonicalText(boolean annotated); + } } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiDisjunctionType.java b/java/java-psi-api/src/com/intellij/psi/PsiDisjunctionType.java index e9e0cf3116c4..1a4062e294fe 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiDisjunctionType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiDisjunctionType.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. @@ -33,7 +33,7 @@ import java.util.List; * Composite type resulting from Project Coin's multi-catch statements, i.e. FileNotFoundException | EOFException. * In most cases should be threatened via its least upper bound (IOException in the example above). */ -public class PsiDisjunctionType extends PsiType { +public class PsiDisjunctionType extends PsiType.Stub { private final PsiManager myManager; private final List myTypes; private final CachedValue myLubCache; @@ -85,15 +85,21 @@ public class PsiDisjunctionType extends PsiType { @Override public String getPresentableText() { return StringUtil.join(myTypes, new Function() { - @Override public String fun(PsiType psiType) { return psiType.getPresentableText(); } + @Override + public String fun(PsiType psiType) { + return psiType.getPresentableText(); + } }, " | "); } @NotNull @Override - public String getCanonicalText() { + public String getCanonicalText(final boolean annotated) { return StringUtil.join(myTypes, new Function() { - @Override public String fun(PsiType psiType) { return psiType.getCanonicalText(); } + @Override + public String fun(PsiType psiType) { + return psiType.getCanonicalText(annotated); + } }, " | "); } @@ -101,7 +107,10 @@ public class PsiDisjunctionType extends PsiType { @Override public String getInternalCanonicalText() { return StringUtil.join(myTypes, new Function() { - @Override public String fun(PsiType psiType) { return psiType.getInternalCanonicalText(); } + @Override + public String fun(PsiType psiType) { + return psiType.getInternalCanonicalText(); + } }, " | "); } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiEllipsisType.java b/java/java-psi-api/src/com/intellij/psi/PsiEllipsisType.java index 0d1447924d83..085854f51a65 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiEllipsisType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiEllipsisType.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,7 +15,6 @@ */ package com.intellij.psi; -import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; /** @@ -45,19 +44,19 @@ public class PsiEllipsisType extends PsiArrayType { @NotNull @Override public String getPresentableText() { - return StringUtil.join(getComponentType().getPresentableText(), getAnnotationsTextPrefix(false, true, true), "..."); + return getText(getComponentType().getPresentableText(), "...", false, true); } @NotNull @Override - public String getCanonicalText() { - return StringUtil.join(getComponentType().getCanonicalText(), "..."); + public String getCanonicalText(boolean annotated) { + return getText(getComponentType().getCanonicalText(annotated), "...", true, annotated); } @NotNull @Override public String getInternalCanonicalText() { - return StringUtil.join(getComponentType().getInternalCanonicalText(), getAnnotationsTextPrefix(true, true, true), "..."); + return getText(getComponentType().getInternalCanonicalText(), "...", true, true); } @Override diff --git a/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java b/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java index 5f5d6d7ef8dc..55a5e9d55260 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.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. @@ -29,7 +29,7 @@ import java.util.*; * * @author ven */ -public class PsiIntersectionType extends PsiType { +public class PsiIntersectionType extends PsiType.Stub { private final PsiType[] myConjuncts; private PsiIntersectionType(@NotNull PsiType[] conjuncts) { @@ -111,19 +111,19 @@ public class PsiIntersectionType extends PsiType { @NotNull @Override - public String getCanonicalText() { - return myConjuncts[0].getCanonicalText(); + public String getCanonicalText(boolean annotated) { + return myConjuncts[0].getCanonicalText(annotated); } @NotNull @Override public String getInternalCanonicalText() { - StringBuilder buffer = new StringBuilder(); - for (int i = 0; i < myConjuncts.length; i++) { - buffer.append(myConjuncts[i].getInternalCanonicalText()); - if (i < myConjuncts.length - 1) buffer.append(" & "); - } - return buffer.toString(); + return StringUtil.join(myConjuncts, new Function() { + @Override + public String fun(PsiType psiType) { + return psiType.getInternalCanonicalText(); + } + }, " & "); } @Override diff --git a/java/java-psi-api/src/com/intellij/psi/PsiNameHelper.java b/java/java-psi-api/src/com/intellij/psi/PsiNameHelper.java index 6ae0fa6a081f..6e5e6563dc3b 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiNameHelper.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiNameHelper.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. @@ -23,8 +23,11 @@ import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Arrays; +import java.util.List; import java.util.regex.Pattern; +import static com.intellij.util.ObjectUtils.assertNotNull; import static com.intellij.util.ObjectUtils.notNull; /** @@ -37,7 +40,7 @@ public abstract class PsiNameHelper { public static PsiNameHelper getInstance(Project project) { return ServiceManager.getService(project, PsiNameHelper.class); } - + /** * Checks if the specified text is a Java identifier, using the language level of the project * with which the name helper is associated to filter out keywords. @@ -121,30 +124,15 @@ public abstract class PsiNameHelper { } @NotNull - public static String getPresentableText(@Nullable String refName, @NotNull PsiAnnotation[] annotations, @NotNull PsiType[] typeParameters) { - if (typeParameters.length == 0 && annotations.length == 0) { + public static String getPresentableText(@Nullable String refName, @NotNull PsiAnnotation[] annotations, @NotNull PsiType[] types) { + if (types.length == 0 && annotations.length == 0) { return refName != null ? refName : ""; } StringBuilder buffer = new StringBuilder(); - - if (annotations.length > 0) { - for (PsiAnnotation annotation : annotations) { - buffer.append(annotation.getText()).append(' '); - } - } - + appendAnnotations(buffer, annotations, false); buffer.append(refName); - - if (typeParameters.length > 0) { - buffer.append("<"); - for (int i = 0; i < typeParameters.length; i++) { - buffer.append(typeParameters[i].getPresentableText()); - if (i < typeParameters.length - 1) buffer.append(", "); - } - buffer.append(">"); - } - + appendTypeArgs(buffer, types, false, true); return buffer.toString(); } @@ -262,4 +250,43 @@ public abstract class PsiNameHelper { return subpackageName.equals(packageName) || subpackageName.startsWith(packageName) && subpackageName.charAt(packageName.length()) == '.'; } + + public static void appendTypeArgs(@NotNull StringBuilder sb, @NotNull PsiType[] types, boolean canonical, boolean annotated) { + if (types.length == 0) return; + + sb.append('<'); + for (int i = 0; i < types.length; i++) { + if (i > 0) { + sb.append(canonical ? "," : ", "); + } + + PsiType type = types[i]; + if (canonical) { + sb.append(type.getCanonicalText(annotated)); + } + else { + sb.append(type.getPresentableText()); + } + } + sb.append('>'); + } + + public static boolean appendAnnotations(@NotNull StringBuilder sb, @NotNull PsiAnnotation[] annotations, boolean canonical) { + return appendAnnotations(sb, Arrays.asList(annotations), canonical); + } + + public static boolean appendAnnotations(@NotNull StringBuilder sb, @NotNull List annotations, boolean canonical) { + for (PsiAnnotation annotation : annotations) { + sb.append('@'); + if (canonical) { + sb.append(annotation.getQualifiedName()); + sb.append(annotation.getParameterList().getText()); + } + else { + sb.append(assertNotNull(annotation.getNameReferenceElement()).getText()); + } + sb.append(' '); + } + return annotations.size() > 0; + } } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiPrimitiveType.java b/java/java-psi-api/src/com/intellij/psi/PsiPrimitiveType.java index dd6b0d4d6ef9..cad6cfda7234 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiPrimitiveType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiPrimitiveType.java @@ -30,7 +30,7 @@ import java.util.Map; /** * Represents primitive types of Java language. */ -public class PsiPrimitiveType extends PsiType { +public class PsiPrimitiveType extends PsiType.Stub { private static final Map ourQNameToUnboxed = new THashMap(); private static final Map ourUnboxedToQName = new THashMap(); @@ -52,19 +52,29 @@ public class PsiPrimitiveType extends PsiType { @NotNull @Override public String getPresentableText() { - return getAnnotationsTextPrefix(false, false, true) + myName; + return getText(false, true); } @NotNull @Override - public String getCanonicalText() { - return myName; + public String getCanonicalText(boolean annotated) { + return getText(true, annotated); } @NotNull @Override public String getInternalCanonicalText() { - return getAnnotationsTextPrefix(true, false, true) + myName; + return getText(true, true); + } + + private String getText(boolean qualified, boolean annotated) { + PsiAnnotation[] annotations = getAnnotations(); + if (!annotated || annotations.length == 0) return myName; + + StringBuilder sb = new StringBuilder(); + PsiNameHelper.appendAnnotations(sb, annotations, qualified); + sb.append(myName); + return sb.toString(); } /** diff --git a/java/java-psi-api/src/com/intellij/psi/PsiType.java b/java/java-psi-api/src/com/intellij/psi/PsiType.java index cfbf026067bc..1dd67fb31a7f 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiType.java @@ -84,6 +84,15 @@ public abstract class PsiType implements PsiAnnotationOwner { */ @NonNls @NotNull + public String getCanonicalText(boolean annotated) { + return getCanonicalText(); + } + + /** + * Same as {@code getCanonicalText(false)}. + */ + @NonNls + @NotNull public abstract String getCanonicalText(); /** @@ -284,24 +293,15 @@ public abstract class PsiType implements PsiAnnotationOwner { return getAnnotations(); } - @NotNull + /** @deprecated use {@link PsiNameHelper#appendAnnotations(StringBuilder, PsiAnnotation[], boolean)} (to remove in IDEA 14) */ + @SuppressWarnings("UnusedDeclaration") protected String getAnnotationsTextPrefix(boolean qualified, boolean leadingSpace, boolean trailingSpace) { PsiAnnotation[] annotations = getAnnotations(); if (annotations.length == 0) return ""; StringBuilder sb = new StringBuilder(); if (leadingSpace) sb.append(' '); - for (int i = 0; i < annotations.length; i++) { - if (i > 0) sb.append(' '); - PsiAnnotation annotation = annotations[i]; - if (qualified) { - sb.append('@').append(annotation.getQualifiedName()).append(annotation.getParameterList().getText()); - } - else { - sb.append(annotation.getText()); - } - } - if (trailingSpace) sb.append(' '); + if (PsiNameHelper.appendAnnotations(sb, annotations, qualified) &&!trailingSpace) sb.setLength(sb.length() - 1); return sb.toString(); } @@ -310,4 +310,23 @@ public abstract class PsiType implements PsiAnnotationOwner { //noinspection HardCodedStringLiteral return "PsiType:" + getPresentableText(); } + + /** + * Temporary class to facilitate transition to {@link #getCanonicalText(boolean)}. + */ + protected static abstract class Stub extends PsiType { + protected Stub(@NotNull PsiAnnotation[] annotations) { + super(annotations); + } + + @NotNull + @Override + public final String getCanonicalText() { + return getCanonicalText(false); + } + + @NotNull + @Override + public abstract String getCanonicalText(boolean annotated); + } } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiWildcardType.java b/java/java-psi-api/src/com/intellij/psi/PsiWildcardType.java index a3dd77aae361..d6518104b014 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiWildcardType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiWildcardType.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. @@ -28,7 +28,7 @@ import org.jetbrains.annotations.Nullable; * * @author dsl */ -public class PsiWildcardType extends PsiType { +public class PsiWildcardType extends PsiType.Stub { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.PsiWildcardType"); private static final Key UNBOUNDED_WILDCARD = new Key("UNBOUNDED_WILDCARD"); @@ -83,21 +83,37 @@ public class PsiWildcardType extends PsiType { @NotNull @Override public String getPresentableText() { - return getAnnotationsTextPrefix(false, false, true) + - (myBound == null ? "?" : (myIsExtending ? EXTENDS_PREFIX : SUPER_PREFIX) + myBound.getPresentableText()); + return getText(false, true, myBound == null ? null : myBound.getPresentableText()); } @Override @NotNull - public String getCanonicalText() { - return myBound == null ? "?" : (myIsExtending ? EXTENDS_PREFIX : SUPER_PREFIX) + myBound.getCanonicalText(); + public String getCanonicalText(boolean annotated) { + return getText(true, annotated, myBound == null ? null : myBound.getCanonicalText(annotated)); } @NotNull @Override public String getInternalCanonicalText() { - return getAnnotationsTextPrefix(true, false, true) + - (myBound == null ? "?" : (myIsExtending ? EXTENDS_PREFIX : SUPER_PREFIX) + myBound.getInternalCanonicalText()); + return getText(true, true, myBound == null ? null : myBound.getInternalCanonicalText()); + } + + private String getText(boolean qualified, boolean annotated, @Nullable String suffix) { + PsiAnnotation[] annotations = getAnnotations(); + if ((!annotated || annotations.length == 0) && suffix == null) return "?"; + + StringBuilder sb = new StringBuilder(); + if (annotated) { + PsiNameHelper.appendAnnotations(sb, annotations, qualified); + } + if (suffix == null) { + sb.append('?'); + } + else { + sb.append(myIsExtending ? EXTENDS_PREFIX : SUPER_PREFIX); + sb.append(suffix); + } + return sb.toString(); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java index a43c02d8a7a4..f304fe250bae 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.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. @@ -30,16 +30,16 @@ import java.util.List; /** * @author max */ -public class PsiClassReferenceType extends PsiClassType { +public class PsiClassReferenceType extends PsiClassType.Stub { @NotNull private final PsiJavaCodeReferenceElement myReference; - public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel langLevel) { - this(reference, langLevel, collectAnnotations(reference)); + public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel level) { + this(reference, level, collectAnnotations(reference)); } - public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel langLevel, @NotNull PsiAnnotation[] annotations) { - super(langLevel, annotations); + public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel level, @NotNull PsiAnnotation[] annotations) { + super(level, annotations); myReference = reference; } @@ -89,7 +89,7 @@ public class PsiClassReferenceType extends PsiClassType { return resolveGenerics().getElement(); } - private static class DelegatingClassResolveResult implements ClassResolveResult { + private static class DelegatingClassResolveResult implements PsiClassType.ClassResolveResult { private final JavaResolveResult myDelegate; private DelegatingClassResolveResult(@NotNull JavaResolveResult delegate) { @@ -182,19 +182,37 @@ public class PsiClassReferenceType extends PsiClassType { @NotNull @Override public String getPresentableText() { - return getAnnotationsTextPrefix(false, false, true) + PsiNameHelper.getPresentableText(myReference); + String presentableText = PsiNameHelper.getPresentableText(myReference); + PsiAnnotation[] annotations = getAnnotations(); + if (annotations.length == 0) return presentableText; + + StringBuilder sb = new StringBuilder(); + PsiNameHelper.appendAnnotations(sb, annotations, false); + sb.append(presentableText); + return sb.toString(); } @NotNull @Override - public String getCanonicalText() { - return myReference.getCanonicalText(); + public String getCanonicalText(boolean annotated) { + return getText(annotated); } @NotNull @Override public String getInternalCanonicalText() { - return getAnnotationsTextPrefix(true, false, true) + getCanonicalText(); + return getText(true); + } + + private String getText(boolean annotated) { + if (myReference instanceof PsiJavaCodeReferenceElementImpl) { + PsiAnnotation[] annotations = getAnnotations(); + if (!annotated || annotations.length == 0) annotations = null; + return ((PsiJavaCodeReferenceElementImpl)myReference).getCanonicalText(annotated, annotations); + } + else { + return myReference.getCanonicalText(); + } } @NotNull diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java index 9456c29f6ceb..77a45011144d 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.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.psi.impl.source; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; @@ -30,11 +31,12 @@ import java.util.List; /** * @author dsl */ -public class PsiImmediateClassType extends PsiClassType { +public class PsiImmediateClassType extends PsiClassType.Stub { private final PsiClass myClass; private final PsiSubstitutor mySubstitutor; private final PsiManager myManager; private String myCanonicalText; + private String myCanonicalTextAnnotated; private String myPresentableText; private String myInternalCanonicalText; @@ -80,15 +82,15 @@ public class PsiImmediateClassType extends PsiClassType { this(aClass, substitutor, null, PsiAnnotation.EMPTY_ARRAY); } - public PsiImmediateClassType(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel languageLevel) { - this(aClass, substitutor, languageLevel, PsiAnnotation.EMPTY_ARRAY); + public PsiImmediateClassType(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel level) { + this(aClass, substitutor, level, PsiAnnotation.EMPTY_ARRAY); } public PsiImmediateClassType(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor, - @Nullable LanguageLevel languageLevel, - @NotNull PsiAnnotation[] annotations) { - super(languageLevel, annotations); + @Nullable LanguageLevel level, + @NotNull PsiAnnotation... annotations) { + super(level, annotations); myClass = aClass; myManager = aClass.getManager(); mySubstitutor = substitutor; @@ -138,112 +140,119 @@ public class PsiImmediateClassType extends PsiClassType { @Override public String getPresentableText() { if (myPresentableText == null) { - StringBuilder buffer = new StringBuilder(); - buildText(myClass, mySubstitutor, buffer, false, false); - myPresentableText = buffer.toString(); + myPresentableText = getText(TextType.PRESENTABLE, true); } return myPresentableText; } @NotNull @Override - public String getCanonicalText() { - if (myCanonicalText == null) { - assert mySubstitutor.isValid(); - StringBuilder buffer = new StringBuilder(); - buildText(myClass, mySubstitutor, buffer, true, false); - myCanonicalText = buffer.toString(); + public String getCanonicalText(boolean annotated) { + String cached = annotated ? myCanonicalTextAnnotated : myCanonicalText; + if (cached == null) { + cached = getText(TextType.CANONICAL, annotated); + if (annotated) myCanonicalTextAnnotated = cached; + else myCanonicalText = cached; } - return myCanonicalText; + return cached; } @NotNull @Override public String getInternalCanonicalText() { if (myInternalCanonicalText == null) { - StringBuilder buffer = new StringBuilder(); - buildText(myClass, mySubstitutor, buffer, true, true); - myInternalCanonicalText = buffer.toString(); + myInternalCanonicalText = getText(TextType.INT_CANONICAL, true); } return myInternalCanonicalText; } + private enum TextType { PRESENTABLE, CANONICAL, INT_CANONICAL } + + private String getText(@NotNull TextType textType, boolean annotated) { + assert mySubstitutor.isValid(); + StringBuilder buffer = new StringBuilder(); + buildText(myClass, mySubstitutor, buffer, textType, annotated); + return buffer.toString(); + } + private void buildText(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor, @NotNull StringBuilder buffer, - boolean canonical, - boolean internal) { + @NotNull TextType textType, + boolean annotated) { if (aClass instanceof PsiAnonymousClass) { - ClassResolveResult baseResolveResult = ((PsiAnonymousClass) aClass).getBaseClassType().resolveGenerics(); + ClassResolveResult baseResolveResult = ((PsiAnonymousClass)aClass).getBaseClassType().resolveGenerics(); PsiClass baseClass = baseResolveResult.getElement(); - PsiSubstitutor baseSub = baseResolveResult.getSubstitutor(); if (baseClass != null) { - buildText(baseClass, baseSub, buffer, canonical, internal); + buildText(baseClass, baseResolveResult.getSubstitutor(), buffer, textType, false); } return; } - if (canonical == internal) { - buffer.append(getAnnotationsTextPrefix(internal, false, true)); - } + boolean qualified = textType != TextType.PRESENTABLE; PsiClass enclosingClass = null; if (!aClass.hasModifierProperty(PsiModifier.STATIC)) { - final PsiElement parent = aClass.getParent(); + PsiElement parent = aClass.getParent(); if (parent instanceof PsiClass && !(parent instanceof PsiAnonymousClass)) { enclosingClass = (PsiClass)parent; } } if (enclosingClass != null) { - buildText(enclosingClass, substitutor, buffer, canonical, false); + buildText(enclosingClass, substitutor, buffer, textType, false); buffer.append('.'); - buffer.append(aClass.getName()); } - else { - final String name; - if (!canonical) { - name = aClass.getName(); - } - else { - final String qualifiedName = aClass.getQualifiedName(); - if (qualifiedName == null) { - name = aClass.getName(); - } - else { - name = qualifiedName; + else if (qualified) { + String fqn = aClass.getQualifiedName(); + if (fqn != null) { + String prefix = StringUtil.getPackageName(fqn); + if (!StringUtil.isEmpty(prefix)) { + buffer.append(prefix); + buffer.append('.'); } } - buffer.append(name); } + if (annotated) { + PsiNameHelper.appendAnnotations(buffer, getAnnotations(), qualified); + } + + buffer.append(aClass.getName()); + PsiTypeParameter[] typeParameters = aClass.getTypeParameters(); if (typeParameters.length > 0) { - StringBuilder pineBuffer = new StringBuilder(); - pineBuffer.append('<'); + int pos = buffer.length(); + buffer.append('<'); + for (int i = 0; i < typeParameters.length; i++) { PsiTypeParameter typeParameter = typeParameters[i]; PsiUtilCore.ensureValid(typeParameter); - if (i > 0) pineBuffer.append(','); - final PsiType substitutionResult = substitutor.substitute(typeParameter); + + if (i > 0) { + buffer.append(','); + if (textType == TextType.PRESENTABLE) buffer.append(' '); + } + + PsiType substitutionResult = substitutor.substitute(typeParameter); if (substitutionResult == null) { - pineBuffer = null; + buffer.setLength(pos); + pos = -1; break; } PsiUtil.ensureValidType(substitutionResult); - if (canonical) { - if (internal) { - pineBuffer.append(substitutionResult.getInternalCanonicalText()); - } - else { - pineBuffer.append(substitutionResult.getCanonicalText()); - } + + if (textType == TextType.PRESENTABLE) { + buffer.append(substitutionResult.getPresentableText()); + } + else if (textType == TextType.CANONICAL) { + buffer.append(substitutionResult.getCanonicalText(annotated)); } else { - pineBuffer.append(substitutionResult.getPresentableText()); + buffer.append(substitutionResult.getInternalCanonicalText()); } } - if (pineBuffer != null) { - buffer.append(pineBuffer); + + if (pos >= 0) { buffer.append('>'); } } @@ -265,7 +274,6 @@ public class PsiImmediateClassType extends PsiClassType { return false; } return equals(patternType); - } @Override @@ -277,14 +285,12 @@ public class PsiImmediateClassType extends PsiClassType { @Override @NotNull public LanguageLevel getLanguageLevel() { - if (myLanguageLevel != null) return myLanguageLevel; - return PsiUtil.getLanguageLevel(myClass); + return myLanguageLevel != null ? myLanguageLevel : PsiUtil.getLanguageLevel(myClass); } @NotNull @Override - public PsiClassType setLanguageLevel(@NotNull final LanguageLevel languageLevel) { - if (languageLevel.equals(myLanguageLevel)) return this; - return new PsiImmediateClassType(myClass, mySubstitutor, languageLevel,getAnnotations()); + public PsiClassType setLanguageLevel(@NotNull LanguageLevel level) { + return level.equals(myLanguageLevel) ? this : new PsiImmediateClassType(myClass, mySubstitutor, level, getAnnotations()); } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java index 396b750c8c2a..5ee1243b09ce 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,6 +49,7 @@ import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Arrays; import java.util.List; public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement implements PsiJavaCodeReferenceElement, SourceJavaCodeReference { @@ -255,36 +256,47 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme @Override @NotNull public String getCanonicalText() { + return getCanonicalText(false, null); + } + + @NotNull + public String getCanonicalText(boolean annotated, @Nullable PsiAnnotation[] annotations) { switch (getKind()) { case CLASS_NAME_KIND: case CLASS_OR_PACKAGE_NAME_KIND: case CLASS_IN_QUALIFIED_NEW_KIND: final PsiElement target = resolve(); if (target instanceof PsiClass) { - final PsiClass aClass = (PsiClass)target; - String name = aClass.getQualifiedName(); - if (name == null) { - name = aClass.getName(); //? + PsiClass aClass = (PsiClass)target; + StringBuilder buffer = new StringBuilder(); + + PsiElement qualifier = getQualifier(); + String prefix = null; + if (qualifier instanceof PsiJavaCodeReferenceElementImpl) { + prefix = ((PsiJavaCodeReferenceElementImpl)qualifier).getCanonicalText(annotated, null); } - final PsiType[] types = getTypeParameters(); - if (types.length == 0) { - final PsiElement qualifier = getQualifier(); - if (qualifier instanceof PsiJavaCodeReferenceElement) { - return StringUtil.getQualifiedName(((PsiJavaCodeReferenceElement)qualifier).getCanonicalText(), aClass.getName()); + else { + String fqn = aClass.getQualifiedName(); + if (fqn != null) { + prefix = StringUtil.getPackageName(fqn); } - return name; } - final StringBuilder buf = new StringBuilder(); - buf.append(name); - buf.append('<'); - for (int i = 0; i < types.length; i++) { - if (i > 0) buf.append(','); - buf.append(types[i].getCanonicalText()); + if (!StringUtil.isEmpty(prefix)) { + buffer.append(prefix); + buffer.append('.'); } - buf.append('>'); - return buf.toString(); + if (annotated) { + List list = annotations != null ? Arrays.asList(annotations) : getAnnotations(); + PsiNameHelper.appendAnnotations(buffer, list, true); + } + + buffer.append(aClass.getName()); + + PsiNameHelper.appendTypeArgs(buffer, getTypeParameters(), true, annotated); + + return buffer.toString(); } else if (target instanceof PsiPackage) { return ((PsiPackage)target).getQualifiedName(); @@ -293,6 +305,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme LOG.assertTrue(target == null, target); return getNormalizedText(); } + case PACKAGE_NAME_KIND: case CLASS_FQ_NAME_KIND: case CLASS_FQ_OR_PACKAGE_NAME_KIND: @@ -327,7 +340,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme if (incompleteCode && result.length == 0 && kind != CLASS_FQ_NAME_KIND && kind != CLASS_FQ_OR_PACKAGE_NAME_KIND) { VariableResolverProcessor processor = new VariableResolverProcessor(referenceElement, containingFile); - PsiScopesUtil.resolveAndWalk(processor, referenceElement, null, incompleteCode); + PsiScopesUtil.resolveAndWalk(processor, referenceElement, null, true); result = processor.getResult(); if (result.length == 0 && kind == CLASS_NAME_KIND) { result = referenceElement.resolve(PACKAGE_NAME_KIND, containingFile); @@ -457,16 +470,16 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme case CLASS_FQ_OR_PACKAGE_NAME_KIND: case CLASS_OR_PACKAGE_NAME_KIND: { int classKind = kind == CLASS_OR_PACKAGE_NAME_KIND ? CLASS_NAME_KIND : CLASS_FQ_NAME_KIND; - JavaResolveResult[] result = resolve(classKind,containingFile); + JavaResolveResult[] result = resolve(classKind, containingFile); if (result.length == 1 && !result[0].isAccessible()) { - JavaResolveResult[] packageResult = resolve(PACKAGE_NAME_KIND,containingFile); + JavaResolveResult[] packageResult = resolve(PACKAGE_NAME_KIND, containingFile); if (packageResult.length != 0) { result = packageResult; } } else if (result.length == 0) { - result = resolve(PACKAGE_NAME_KIND,containingFile); + result = resolve(PACKAGE_NAME_KIND, containingFile); } return result; @@ -607,7 +620,12 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme for (PsiAnnotation annotation : annotations) { if (annotation.getParent() != newParent) { - newParent.addAfter(annotation, anchor); + if (anchor != null) { + newParent.addAfter(annotation, anchor); + } + else { + newParent.add(annotation); + } annotation.delete(); } } @@ -935,7 +953,6 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme final PsiReferenceParameterList parameterList = getParameterList(); if (parameterList == null) return PsiType.EMPTY_ARRAY; return parameterList.getTypeArguments(); - } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java index f6ba9fdf5af4..918d7fed7237 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.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. @@ -131,7 +131,7 @@ public class JavaTreeGenerator implements TreeGenerator { type = PsiType.getJavaLangObject(manager, GlobalSearchScope.projectScope(manager.getProject())); } - String text = type.getPresentableText(); + String text = type.getCanonicalText(true); PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(original.getProject()).getParserFacade(); PsiTypeElement element = parserFacade.createTypeElementFromText(text, original); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java index e097988ff116..fbbe91649ddb 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java @@ -157,14 +157,14 @@ class ParenthTest { class TestWildcardInference { interface A { } - + class B implements A { B(C v) { } } - + class C {} - + class U { void foo() { C x = null; @@ -202,13 +202,13 @@ class Another { System.out.println(i); - Outer2.Inner2 i5 = new Outer2<>().new Inner2<>(); + Outer2.Inner2 i5 = new Outer2<>().new Inner2<>(); } static Outer m() {return null;} static T m1() {return null;} static T m2() {return null;} - + } class TypeParamsExtendsList { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeAmbiguity.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeAmbiguity.java index 8ee9852f366f..70a6e70c310c 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeAmbiguity.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeAmbiguity.java @@ -40,6 +40,6 @@ class AAmbiguous { } public static void main(Promise helloWorld) { - helloWorld.then(AAmbiguous::calculateLength); + helloWorld.then(AAmbiguous::calculateLength); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility1.java index 84e929697a92..d62afb3fdfcd 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility1.java @@ -21,9 +21,9 @@ class Test { } void foo(Foo as, final Foo ac) { - boolean b1 = as.forAll(s -> ac.forAll(c -> false)); - String s1 = as.forAll(s -> ac.forAll(c -> "")); - boolean b2 = as.forAll(s -> ac.forAll(c -> "")); + boolean b1 = as.forAll(s -> ac.forAll(c -> false)); + String s1 = as.forAll(s -> ac.forAll(c -> "")); + boolean b2 = as.forAll(s -> ac.forAll(c -> "")); String s2 = as.forAll2(s -> ac.forAll2(c -> false)); boolean b3 = as.forAll((I)s -> ac.forAll((I)c -> "")); String s3 = as.forAll((II)s -> ac.forAll((II)c -> false)); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialApplicability.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialApplicability.java index ab7614c23c55..18f5026255c6 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialApplicability.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialApplicability.java @@ -53,7 +53,7 @@ class Test { Test s1 = staticCall(Test::n0); Test s2 = staticCall(Test::n1); Test s3 = staticCall(Test::n2); - Test s4 = staticCall(Test::n01); - Test s5 = staticCall(Test::n012); + Test s4 = staticCall(Test::n01); + Test s5 = staticCall(Test::n012); } } \ No newline at end of file diff --git a/java/java-tests/testData/fileEditorManager/src/Bar.java b/java/java-tests/testData/fileEditorManager/src/Bar.java new file mode 100644 index 000000000000..4843c680a616 --- /dev/null +++ b/java/java-tests/testData/fileEditorManager/src/Bar.java @@ -0,0 +1,5 @@ +public class Bar { + public String doIt() { + return ""; + } +} diff --git a/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef.java b/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef.java index b06887668d65..ded427d4aef0 100644 --- a/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef.java +++ b/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef.java @@ -1,15 +1,12 @@ -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.*; - -@Target({TYPE_USE}) @interface TA { } +import pkg.TA; class Outer { class Middle { class Inner { void m1(Outer.Middle.Inner p) { } - void m2(@TA Outer.Middle.Inner p) { } - void m3(Outer.@TA Middle.Inner p) { } - void m4(Outer.Middle.@TA @TA Inner p) { } + void m2(@pkg.TA Outer.Middle.Inner p) { } + void m3(Outer.@pkg.TA Middle.Inner p) { } + void m4(Outer.Middle.@pkg.TA @pkg.TA Inner p) { } } } } diff --git a/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef_after.java b/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef_after.java index 1c4c8d4a3ec5..fab10a32c52f 100644 --- a/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef_after.java +++ b/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef_after.java @@ -1,7 +1,4 @@ -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.*; - -@Target({TYPE_USE}) @interface TA { } +import pkg.TA; class Outer { class Middle { diff --git a/java/java-tests/testData/psi/shortenClassRefs/pkg/TA.java b/java/java-tests/testData/psi/shortenClassRefs/pkg/TA.java new file mode 100644 index 000000000000..abe2aca8d7ac --- /dev/null +++ b/java/java-tests/testData/psi/shortenClassRefs/pkg/TA.java @@ -0,0 +1,6 @@ +package pkg; + +import java.lang.annotation.*; + +@Target({ElementType.TYPE_USE}) +@interface TA { } diff --git a/java/java-tests/testData/refactoring/introduceVariable/genericWithTwoParameters/after/Client.java b/java/java-tests/testData/refactoring/introduceVariable/genericWithTwoParameters/after/Client.java index 38d94b3a880b..c98b7fa857fc 100644 --- a/java/java-tests/testData/refactoring/introduceVariable/genericWithTwoParameters/after/Client.java +++ b/java/java-tests/testData/refactoring/introduceVariable/genericWithTwoParameters/after/Client.java @@ -2,6 +2,6 @@ import util.Pair; class Client { void method() { - Pair> p = PairProvider.getPair(); + Pair> p = PairProvider.getPair(); } } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy index f186f9e8f5c8..6373bc3ce307 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,15 +15,22 @@ */ package com.intellij.codeInsight.psi -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile +import com.intellij.pom.java.LanguageLevel +import com.intellij.psi.* +import com.intellij.psi.impl.source.PsiImmediateClassType import com.intellij.testFramework.LightIdeaTestCase -@SuppressWarnings(["GrUnresolvedAccess", "GroovyAssignabilityCheck"]) +@SuppressWarnings("GroovyAssignabilityCheck") class AnnotatedTypeTest extends LightIdeaTestCase { + private PsiFile context + private PsiElementFactory factory + + public void setUp() throws Exception { + super.setUp() + factory = javaFacade.elementFactory + context = createFile("typeCompositionTest.java", """ +package pkg; - public void testTypeComposition() { - PsiFile context = createFile("typeCompositionTest.java", """ import java.lang.annotation.*; import static java.lang.annotation.ElementType.*; @@ -33,31 +40,55 @@ import static java.lang.annotation.ElementType.*; class E1 extends Exception { } class E2 extends Exception { } """) - PsiElement psi - - psi = javaFacade.elementFactory.createStatementFromText("@A @TA(1) int @TA(2) [] a", context) - assertEquals("@TA(1) int @TA(2) []", psi.declaredElements[0].type.presentableText) - - psi = javaFacade.elementFactory.createStatementFromText("try { } catch (@A @TA(1) E1 | @TA(2) E2 e) { }", context) - assertEquals("@TA(1) E1 | @TA(2) E2", psi.catchBlockParameters[0].type.presentableText) - - psi = javaFacade.elementFactory.createStatementFromText("@A @TA(1) String @TA(2) [] f @TA(3) []", context) - assertEquals("@TA(1) String @TA(2) [] @TA(3) []", psi.declaredElements[0].type.presentableText) - - psi = javaFacade.elementFactory.createStatementFromText("Class<@TA(1) ?> c", context) - assertEquals("Class<@TA(1) ?>", psi.declaredElements[0].type.presentableText) - - psi = javaFacade.elementFactory.createStatementFromText("Class<@TA String> cs = new Class<>()", context) - assertEquals("Class<@TA String>", psi.declaredElements[0].initializer.type.presentableText) - - psi = javaFacade.elementFactory.createStatementFromText("@A @TA(1) String s", context) - assertEquals("@TA(1) String", psi.declaredElements[0].type.presentableText) - - psi = javaFacade.elementFactory.createStatementFromText("@A java.lang.@TA(1) String s", context) - assertEquals("@TA(1) String", psi.declaredElements[0].type.presentableText) - - psi = javaFacade.elementFactory.createStatementFromText("Collection s", context) - assertEquals("Collection", psi.declaredElements[0].type.presentableText) } + public void testPrimitiveArrayType() { + doTest("@A @TA(1) int @TA(2) [] a", "@pkg.TA(1) int @pkg.TA(2) []", "int[]") + } + + public void testEllipsisType() { + def psi = factory.createParameterFromText("@TA int @TA ... p", context) + assertTypeText(psi.type, "@pkg.TA int @pkg.TA ...", "int...") + } + + public void testClassReferenceType() { + doTest("@A @TA(1) String s", "java.lang.@pkg.TA(1) String", "java.lang.String") + doTest("@A java.lang.@TA(1) String s", "java.lang.@pkg.TA(1) String", "java.lang.String") + } + + public void testCStyleArrayType() { + doTest("@A @TA(1) String @TA(2) [] f @TA(3) []", "java.lang.@pkg.TA(1) String @pkg.TA(2) [] @pkg.TA(3) []", "java.lang.String[][]") + } + + public void testWildcardType() { + doTest("Class<@TA(1) ?> c", "java.lang.Class<@pkg.TA(1) ?>", "java.lang.Class") + } + + public void testDisjunctionType() { + def psi = factory.createStatementFromText("try { } catch (@A @TA(1) E1 | @TA(2) E2 e) { }", context) + assertTypeText(psi.catchBlockParameters[0].type, "pkg.@pkg.TA(1) E1 | pkg.@pkg.TA(2) E2", "pkg.E1 | pkg.E2") + } + + public void testDiamondType() { + def psi = factory.createStatementFromText("Class<@TA String> cs = new Class<>()", context) + assertTypeText(psi.declaredElements[0].initializer.type, "java.lang.Class", "java.lang.Class") + } + + public void testImmediateClassType() { + def aClass = javaFacade.findClass(CommonClassNames.JAVA_LANG_OBJECT) + def statement = factory.createStatementFromText("@TA int x", context) + def annotations = statement.declaredElements[0].modifierList.annotations + def type = new PsiImmediateClassType(aClass, PsiSubstitutor.EMPTY, LanguageLevel.JDK_1_8, annotations) + assertTypeText(type, "java.lang.@pkg.TA Object", CommonClassNames.JAVA_LANG_OBJECT) + } + + private void doTest(String text, String annotated, String canonical) { + def psi = factory.createStatementFromText(text, context) + assertTypeText(psi.declaredElements[0].type, annotated, canonical) + } + + private static void assertTypeText(PsiType type, String annotated, String canonical) { + assert type.getCanonicalText(true) == annotated + assert type.getCanonicalText(false) == canonical + } } diff --git a/java/java-tests/testSrc/com/intellij/openapi/editor/impl/JavaFileEditorManagerTest.java b/java/java-tests/testSrc/com/intellij/openapi/editor/impl/JavaFileEditorManagerTest.java new file mode 100644 index 000000000000..2a985b873ee3 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/openapi/editor/impl/JavaFileEditorManagerTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.editor.impl; + +import com.intellij.openapi.fileEditor.FileEditorManagerTestCase; +import com.intellij.testFramework.PlatformTestUtil; +import org.jdom.JDOMException; + +import java.io.File; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +/** + * @author Dmitry Avdeev + */ +public class JavaFileEditorManagerTest extends FileEditorManagerTestCase { + + public void testAsyncOpening() throws JDOMException, ExecutionException, InterruptedException, IOException { + openFiles("\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " "); + } + + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/java/java-tests/testData/fileEditorManager"; + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ShortenClassReferencesTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ShortenClassReferencesTest.java index e21c18022e1e..4554f93fb20d 100644 --- a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ShortenClassReferencesTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ShortenClassReferencesTest.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. @@ -61,6 +61,7 @@ public class ShortenClassReferencesTest extends LightCodeInsightFixtureTestCase public void testSCR37254() { doTest(); } public void testTypeAnnotatedRef() { + myFixture.configureByFile("pkg/TA.java"); doTest(); for (PsiParameter parameter : PsiTreeUtil.findChildrenOfType(myFixture.getFile(), PsiParameter.class)) { PsiTypeElement typeElement = parameter.getTypeElement(); diff --git a/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.builders.java.JavaCompilingTool b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.builders.java.JavaCompilingTool new file mode 100644 index 000000000000..f26b04843daf --- /dev/null +++ b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.builders.java.JavaCompilingTool @@ -0,0 +1,2 @@ +org.jetbrains.jps.builders.impl.java.JavacCompilerTool +org.jetbrains.jps.builders.impl.java.EclipseCompilerTool \ No newline at end of file diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/EclipseCompilerTool.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/EclipseCompilerTool.java new file mode 100644 index 000000000000..a223fcb40b41 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/EclipseCompilerTool.java @@ -0,0 +1,89 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.jps.builders.impl.java; + +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.builders.java.CannotCreateJavaCompilerException; +import org.jetbrains.jps.builders.java.JavaCompilingTool; +import org.jetbrains.jps.cmdline.ClasspathBootstrap; +import org.jetbrains.jps.incremental.CompileContext; +import org.jetbrains.jps.incremental.Utils; +import org.jetbrains.jps.model.java.compiler.JavaCompilers; + +import javax.tools.*; +import java.io.File; +import java.util.Collections; +import java.util.List; +import java.util.ServiceLoader; + +/** + * @author nik + */ +public class EclipseCompilerTool extends JavaCompilingTool { + @NotNull + @Override + public String getId() { + return JavaCompilers.ECLIPSE_ID; + } + + @Nullable + @Override + public String getAlternativeId() { + return JavaCompilers.ECLIPSE_EMBEDDED_ID; + } + + @NotNull + @Override + public String getDescription() { + return "Eclipse compiler"; + } + + @NotNull + @Override + public JavaCompiler createCompiler() throws CannotCreateJavaCompilerException { + for (JavaCompiler javaCompiler : ServiceLoader.load(JavaCompiler.class)) { + if ("EclipseCompiler".equals(StringUtil.getShortName(javaCompiler.getClass()))) { + return javaCompiler; + } + } + throw new CannotCreateJavaCompilerException("Eclipse Batch Compiler was not found in classpath"); + } + + @NotNull + @Override + public List getAdditionalClasspath() { + for (JavaCompiler javaCompiler : ServiceLoader.load(JavaCompiler.class)) { // Eclipse compiler + final File compilerResource = ClasspathBootstrap.getResourceFile(javaCompiler.getClass()); + final String name = compilerResource.getName(); + if (name.startsWith("ecj-") && name.endsWith(".jar")) { + return Collections.singletonList(compilerResource); + } + } + return Collections.emptyList(); + } + + @Override + public void processCompilerOptions(@NotNull CompileContext context, @NotNull List options) { + for (String option : options) { + if (option.startsWith("-proceedOnError")) { + Utils.PROCEED_ON_ERROR_KEY.set(context, Boolean.TRUE); + break; + } + } + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/JavacCompilerTool.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/JavacCompilerTool.java new file mode 100644 index 000000000000..0db6933e8976 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/JavacCompilerTool.java @@ -0,0 +1,77 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.jps.builders.impl.java; + +import com.intellij.util.ExceptionUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.builders.java.CannotCreateJavaCompilerException; +import org.jetbrains.jps.builders.java.JavaCompilingTool; +import org.jetbrains.jps.javac.JavacMain; +import org.jetbrains.jps.model.java.compiler.JavaCompilers; + +import javax.tools.*; +import java.io.File; +import java.util.Collections; +import java.util.List; + +/** + * @author nik + */ +public class JavacCompilerTool extends JavaCompilingTool { + @NotNull + @Override + public String getId() { + return JavaCompilers.JAVAC_ID; + } + + @Nullable + @Override + public String getAlternativeId() { + return JavaCompilers.JAVAC_API_ID; + } + + @NotNull + @Override + public String getDescription() { + return "javac " + System.getProperty("java.version"); + } + + @NotNull + @Override + public JavaCompiler createCompiler() throws CannotCreateJavaCompilerException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler != null) { + return compiler; + } + + String message = "System Java Compiler was not found in classpath"; + // trying to obtain additional diagnostic for the case when compiler.jar is present, but there were problems with compiler class loading: + try { + Class.forName("com.sun.tools.javac.api.JavacTool", false, JavacMain.class.getClassLoader()); + } + catch (Throwable ex) { + message = message + ":\n" + ExceptionUtil.getThrowableText(ex); + } + throw new CannotCreateJavaCompilerException(message); + } + + @NotNull + @Override + public List getAdditionalClasspath() { + return Collections.emptyList(); + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/CannotCreateJavaCompilerException.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/CannotCreateJavaCompilerException.java new file mode 100644 index 000000000000..4901a970f3a7 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/CannotCreateJavaCompilerException.java @@ -0,0 +1,25 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.jps.builders.java; + +/** + * @author nik + */ +public class CannotCreateJavaCompilerException extends Exception { + public CannotCreateJavaCompilerException(String message) { + super(message); + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java index 1f4bcfc09f8f..1f0cd41c7ffa 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java @@ -21,6 +21,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.ModuleChunk; import org.jetbrains.jps.ProjectPaths; import org.jetbrains.jps.builders.BuildRootIndex; @@ -38,6 +39,7 @@ import org.jetbrains.jps.model.library.JpsTypedLibrary; import org.jetbrains.jps.model.library.sdk.JpsSdk; import org.jetbrains.jps.model.library.sdk.JpsSdkReference; import org.jetbrains.jps.model.module.JpsModule; +import org.jetbrains.jps.service.JpsServiceManager; import java.io.File; import java.io.IOException; @@ -281,6 +283,16 @@ public class JavaBuilderUtil { return sdkLibrary.getProperties(); } + @Nullable + public static JavaCompilingTool findCompilingTool(@NotNull String compilerId) { + for (JavaCompilingTool tool : JpsServiceManager.getInstance().getExtensions(JavaCompilingTool.class)) { + if (compilerId.equals(tool.getId()) || compilerId.equals(tool.getAlternativeId())) { + return tool; + } + } + return null; + } + private static class ModulesBasedFileFilter implements Mappings.DependentFilesFilter { private final CompileContext myContext; private final Set myChunkModules; diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaCompilingTool.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaCompilingTool.java new file mode 100644 index 000000000000..0afb45bda93b --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaCompilingTool.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.jps.builders.java; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.incremental.CompileContext; + +import javax.tools.*; +import java.io.File; +import java.util.List; + +/** + * @author nik + */ +public abstract class JavaCompilingTool { + @NotNull + public abstract String getId(); + + @Nullable + public String getAlternativeId() { + return null; + } + + @NotNull + public abstract String getDescription(); + + @NotNull + public abstract JavaCompiler createCompiler() throws CannotCreateJavaCompilerException; + + @NotNull + public abstract List getAdditionalClasspath(); + + public void processCompilerOptions(@NotNull CompileContext context, @NotNull List options) { + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java index d2b4c7f3210b..c89cb50397fb 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java @@ -32,15 +32,14 @@ import net.n3.nanoxml.IXMLBuilder; import org.jetbrains.annotations.Nullable; import org.jetbrains.asm4.ClassVisitor; import org.jetbrains.asm4.ClassWriter; +import org.jetbrains.jps.builders.java.JavaCompilingTool; import org.jetbrains.jps.builders.java.JavaSourceTransformer; import org.jetbrains.jps.javac.JavacServer; import org.jetbrains.jps.model.JpsModel; import org.jetbrains.jps.model.impl.JpsModelImpl; import org.jetbrains.jps.model.serialization.JpsProjectLoader; -import javax.tools.JavaCompiler; -import javax.tools.StandardJavaFileManager; -import javax.tools.ToolProvider; +import javax.tools.*; import java.io.File; import java.lang.reflect.Method; import java.util.*; @@ -177,7 +176,7 @@ public class ClasspathBootstrap { } } - public static List getJavacServerClasspath(String sdkHome, boolean useEclipseCompiler) { + public static List getJavacServerClasspath(String sdkHome, JavaCompilingTool compilingTool) { final Set cp = new LinkedHashSet(); cp.add(getResourceFile(JavacServer.class)); // self // util @@ -236,16 +235,7 @@ public class ClasspathBootstrap { } } - if (useEclipseCompiler) { - // eclipse compiler - for (JavaCompiler javaCompiler : ServiceLoader.load(JavaCompiler.class)) { // Eclipse compiler - final File compilerResource = getResourceFile(javaCompiler.getClass()); - final String name = compilerResource.getName(); - if (name.startsWith("ecj-") && name.endsWith(".jar")) { - cp.add(compilerResource); - } - } - } + cp.addAll(compilingTool.getAdditionalClasspath()); final Class transformerClass = JavaSourceTransformer.class; final ServiceLoader loader = ServiceLoader.load(transformerClass, transformerClass.getClassLoader()); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index aa10534dd4a4..db1700c47cbd 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -39,6 +39,7 @@ import org.jetbrains.jps.builders.DirtyFilesHolder; import org.jetbrains.jps.builders.FileProcessor; import org.jetbrains.jps.builders.java.JavaBuilderExtension; import org.jetbrains.jps.builders.java.JavaBuilderUtil; +import org.jetbrains.jps.builders.java.JavaCompilingTool; import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor; import org.jetbrains.jps.builders.java.dependencyView.Callbacks; import org.jetbrains.jps.builders.java.dependencyView.Mappings; @@ -81,7 +82,7 @@ public class JavaBuilder extends ModuleLevelBuilder { public static final boolean USE_EMBEDDED_JAVAC = System.getProperty(GlobalOptions.USE_EXTERNAL_JAVAC_OPTION) == null; private static final Key JAVA_COMPILER_VERSION_KEY = Key.create("_java_compiler_version_"); public static final Key IS_ENABLED = Key.create("_java_compiler_enabled_"); - private static final Key IS_COMPILER_API_SUPPORTED = Key.create("_java_compiler_api_supported_"); + private static final Key COMPILING_TOOL = Key.create("_java_compiling_tool_"); private static final Key> COMPILER_VERSION_INFO = Key.create("_java_compiler_version_info_"); private static final Set FILTERED_OPTIONS = new HashSet(Arrays.asList( @@ -137,16 +138,9 @@ public class JavaBuilder extends ModuleLevelBuilder { if (LOG.isDebugEnabled()) { LOG.debug("Java compiler ID: " + compilerId); } - final boolean isJavac = JavaCompilers.JAVAC_ID.equalsIgnoreCase(compilerId) || JavaCompilers.JAVAC_API_ID.equalsIgnoreCase(compilerId); - final boolean isEclipse = JavaCompilers.ECLIPSE_ID.equalsIgnoreCase(compilerId) || JavaCompilers.ECLIPSE_EMBEDDED_ID.equalsIgnoreCase(compilerId); - IS_COMPILER_API_SUPPORTED.set(context, isJavac || isEclipse); - String messageText = null; - if (isJavac) { - messageText = "Using javac " + System.getProperty("java.version") + " to compile java sources"; - } - else if (isEclipse) { - messageText = "Using eclipse compiler to compile java sources"; - } + JavaCompilingTool compilingTool = JavaBuilderUtil.findCompilingTool(compilerId); + COMPILING_TOOL.set(context, compilingTool); + String messageText = compilingTool != null ? "Using " + compilingTool.getDescription() + " to compile java sources" : null; COMPILER_VERSION_INFO.set(context, new AtomicReference(messageText)); } @@ -159,16 +153,17 @@ public class JavaBuilder extends ModuleLevelBuilder { @NotNull ModuleChunk chunk, @NotNull DirtyFilesHolder dirtyFilesHolder, @NotNull OutputConsumer outputConsumer) throws ProjectBuildException, IOException { - if (!IS_ENABLED.get(context, Boolean.TRUE) || !IS_COMPILER_API_SUPPORTED.get(context, Boolean.TRUE)) { + JavaCompilingTool compilingTool = COMPILING_TOOL.get(context); + if (!IS_ENABLED.get(context, Boolean.TRUE) || compilingTool == null) { return ExitCode.NOTHING_DONE; } - return doBuild(context, chunk, dirtyFilesHolder, outputConsumer); + return doBuild(context, chunk, dirtyFilesHolder, outputConsumer, compilingTool); } public ExitCode doBuild(@NotNull CompileContext context, @NotNull ModuleChunk chunk, @NotNull DirtyFilesHolder dirtyFilesHolder, - @NotNull OutputConsumer outputConsumer) throws ProjectBuildException, IOException { + @NotNull OutputConsumer outputConsumer, JavaCompilingTool compilingTool) throws ProjectBuildException, IOException { try { final Set filesToCompile = new THashSet(FileUtil.FILE_HASHING_STRATEGY); @@ -190,7 +185,7 @@ public class JavaBuilder extends ModuleLevelBuilder { } } - return compile(context, chunk, dirtyFilesHolder, filesToCompile, outputConsumer); + return compile(context, chunk, dirtyFilesHolder, filesToCompile, outputConsumer, compilingTool); } catch (BuildDataCorruptedException e) { throw e; @@ -224,7 +219,7 @@ public class JavaBuilder extends ModuleLevelBuilder { ModuleChunk chunk, DirtyFilesHolder dirtyFilesHolder, Collection files, - OutputConsumer outputConsumer) + OutputConsumer outputConsumer, @NotNull JavaCompilingTool compilingTool) throws Exception { ExitCode exitCode = ExitCode.NOTHING_DONE; @@ -284,7 +279,7 @@ public class JavaBuilder extends ModuleLevelBuilder { } } try { - compiledOk = compileJava(context, chunk, files, classpath, platformCp, srcPath, diagnosticSink, outputSink); + compiledOk = compileJava(context, chunk, files, classpath, platformCp, srcPath, diagnosticSink, outputSink, compilingTool); } finally { // heuristic: incorrect paths data recovery, so that the next make should not contain non-existing sources in 'recompile' list @@ -328,7 +323,7 @@ public class JavaBuilder extends ModuleLevelBuilder { Collection platformCp, Collection sourcePath, DiagnosticOutputConsumer diagnosticSink, - final OutputFileConsumer outputSink) throws Exception { + final OutputFileConsumer outputSink, JavaCompilingTool compilingTool) throws Exception { final TasksCounter counter = new TasksCounter(); COUNTER_KEY.set(context, counter); @@ -372,7 +367,7 @@ public class JavaBuilder extends ModuleLevelBuilder { } final Map> outs = buildOutputDirectoriesMap(context, chunk); - final List options = getCompilationOptions(context, chunk, profile); + final List options = getCompilationOptions(context, chunk, profile, compilingTool); final ClassProcessingConsumer classesConsumer = new ClassProcessingConsumer(context, outputSink); if (LOG.isDebugEnabled()) { LOG.debug("Compiling chunk [" + chunk.getName() + "] with options: \"" + StringUtil.join(options, " ") + "\""); @@ -380,13 +375,11 @@ public class JavaBuilder extends ModuleLevelBuilder { try { final boolean rc; if (USE_EMBEDDED_JAVAC) { - final boolean useEclipse = useEclipseCompiler(context); - rc = JavacMain.compile( - options, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer, context.getCancelStatus(), useEclipse - ); + rc = JavacMain.compile(options, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer, + context.getCancelStatus(), compilingTool); } else { - final JavacServerClient client = ensureJavacServerLaunched(context); + final JavacServerClient client = ensureJavacServerLaunched(context, compilingTool); final RequestFuture future = client.sendCompileRequest( options, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer ); @@ -404,13 +397,6 @@ public class JavaBuilder extends ModuleLevelBuilder { } } - private static boolean useEclipseCompiler(CompileContext context) { - JpsProject project = context.getProjectDescriptor().getProject(); - final JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getCompilerConfiguration(project); - final String compilerId = configuration != null? configuration.getJavaCompilerId() : null; - return JavaCompilers.ECLIPSE_ID.equalsIgnoreCase(compilerId) || JavaCompilers.ECLIPSE_EMBEDDED_ID.equalsIgnoreCase(compilerId); - } - private void submitAsyncTask(final CompileContext context, final Runnable taskRunnable) { final TasksCounter counter = COUNTER_KEY.get(context); @@ -432,7 +418,7 @@ public class JavaBuilder extends ModuleLevelBuilder { }); } - private static synchronized JavacServerClient ensureJavacServerLaunched(CompileContext context) throws Exception { + private static synchronized JavacServerClient ensureJavacServerLaunched(@NotNull CompileContext context, @NotNull JavaCompilingTool compilingTool) throws Exception { final ExternalJavacDescriptor descriptor = ExternalJavacDescriptor.KEY.get(context); if (descriptor != null) { return descriptor.client; @@ -445,7 +431,7 @@ public class JavaBuilder extends ModuleLevelBuilder { final String javaHome = SystemProperties.getJavaHome(); final BaseOSProcessHandler processHandler = JavacServerBootstrap.launchJavacServer( - javaHome, heapSize, port, Utils.getSystemRoot(), getCompilationVMOptions(context), useEclipseCompiler(context) + javaHome, heapSize, port, Utils.getSystemRoot(), getCompilationVMOptions(context, compilingTool), compilingTool ); final JavacServerClient client = new JavacServerClient(); try { @@ -529,19 +515,22 @@ public class JavaBuilder extends ModuleLevelBuilder { private static final Key> JAVAC_VM_OPTIONS = Key.create("_javac_vm_options_"); private static final Key USER_DEFINED_BYTECODE_TARGET = Key.create("_user_defined_bytecode_target_"); - private static List getCompilationVMOptions(CompileContext context) { + private static List getCompilationVMOptions(CompileContext context, JavaCompilingTool compilingTool) { List cached = JAVAC_VM_OPTIONS.get(context); if (cached == null) { - loadCommonJavacOptions(context); + loadCommonJavacOptions(context, compilingTool); cached = JAVAC_VM_OPTIONS.get(context); } return cached; } - private static List getCompilationOptions(CompileContext context, ModuleChunk chunk, @Nullable ProcessorConfigProfile profile) { + private static List getCompilationOptions(CompileContext context, + ModuleChunk chunk, + @Nullable ProcessorConfigProfile profile, + @NotNull JavaCompilingTool compilingTool) { List cached = JAVAC_OPTIONS.get(context); if (cached == null) { - loadCommonJavacOptions(context); + loadCommonJavacOptions(context, compilingTool); cached = JAVAC_OPTIONS.get(context); assert cached != null : context; } @@ -701,7 +690,7 @@ public class JavaBuilder extends ModuleLevelBuilder { return javaVersion; } - private static void loadCommonJavacOptions(CompileContext context) { + private static void loadCommonJavacOptions(@NotNull CompileContext context, @NotNull JavaCompilingTool compilingTool) { final List options = new ArrayList(); final List vmOptions = new ArrayList(); @@ -755,14 +744,7 @@ public class JavaBuilder extends ModuleLevelBuilder { } } - if (useEclipseCompiler(context)) { - for (String option : options) { - if (option.startsWith("-proceedOnError")) { - Utils.PROCEED_ON_ERROR_KEY.set(context, Boolean.TRUE); - break; - } - } - } + compilingTool.processCompilerOptions(context, options); JAVAC_OPTIONS.set(context, options); JAVAC_VM_OPTIONS.set(context, vmOptions); diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java index d9c58323804b..610a51d2d775 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java @@ -16,11 +16,13 @@ package org.jetbrains.jps.javac; import com.intellij.openapi.util.SystemInfo; -import com.intellij.util.ExceptionUtil; import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.api.CanceledStatus; +import org.jetbrains.jps.builders.impl.java.JavacCompilerTool; +import org.jetbrains.jps.builders.java.CannotCreateJavaCompilerException; +import org.jetbrains.jps.builders.java.JavaCompilingTool; import org.jetbrains.jps.builders.java.JavaSourceTransformer; import org.jetbrains.jps.cmdline.ClasspathBootstrap; import org.jetbrains.jps.incremental.LineOutputWriter; @@ -57,52 +59,29 @@ public class JavacMain { Map> outputDirToRoots, final DiagnosticOutputConsumer diagnosticConsumer, final OutputFileConsumer outputSink, - CanceledStatus canceledStatus, boolean useEclipseCompiler) { - JavaCompiler compiler = null; - if (useEclipseCompiler) { - for (JavaCompiler javaCompiler : ServiceLoader.load(JavaCompiler.class)) { - compiler = javaCompiler; - break; - } - if (compiler == null) { - diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, "Eclipse Batch Compiler was not found in classpath")); - return false; - } + CanceledStatus canceledStatus, @NotNull JavaCompilingTool compilingTool) { + JavaCompiler compiler; + try { + compiler = compilingTool.createCompiler(); } - - final boolean nowUsingJavac; - if (compiler == null) { - compiler = ToolProvider.getSystemJavaCompiler(); - if (compiler == null) { - String message = "System Java Compiler was not found in classpath"; - // trying to obtain additional diagnostic for the case when compiler.jar is present, but there were problems with compiler class loading: - try { - Class.forName("com.sun.tools.javac.api.JavacTool", false, JavacMain.class.getClassLoader()); - } - catch (Throwable ex) { - message = message + ":\n" + ExceptionUtil.getThrowableText(ex); - } - diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, message)); - return false; - } - nowUsingJavac = true; - } - else { - nowUsingJavac = false; + catch (CannotCreateJavaCompilerException e) { + diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, e.getMessage())); + return false; } for (File outputDir : outputDirToRoots.keySet()) { outputDir.mkdirs(); } - + final List transformers = getSourceTransformers(); - final JavacFileManager fileManager = new JavacFileManager(new ContextImpl(compiler, diagnosticConsumer, outputSink, canceledStatus, nowUsingJavac), transformers); + final boolean usingJavac = compilingTool instanceof JavacCompilerTool; + final JavacFileManager fileManager = new JavacFileManager(new ContextImpl(compiler, diagnosticConsumer, outputSink, canceledStatus, usingJavac), transformers); fileManager.handleOption("-bootclasspath", Collections.singleton("").iterator()); // this will clear cached stuff fileManager.handleOption("-extdirs", Collections.singleton("").iterator()); // this will clear cached stuff fileManager.handleOption("-endorseddirs", Collections.singleton("").iterator()); // this will clear cached stuff - final Collection _options = prepareOptions(options, nowUsingJavac); + final Collection _options = prepareOptions(options, usingJavac); try { fileManager.setOutputDirectories(outputDirToRoots); @@ -115,7 +94,7 @@ public class JavacMain { if (!classpath.isEmpty()) { try { fileManager.setLocation(StandardLocation.CLASS_PATH, classpath); - if (!nowUsingJavac && !isOptionSet(options, "-processorpath")) { + if (!usingJavac && !isOptionSet(options, "-processorpath")) { // for non-javac file manager ensure annotation processor path defaults to classpath fileManager.setLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH, classpath); } @@ -148,7 +127,7 @@ public class JavacMain { //noinspection IOResourceOpenedButNotSafelyClosed final LineOutputWriter out = new LineOutputWriter() { protected void lineAvailable(String line) { - if (nowUsingJavac) { + if (usingJavac) { diagnosticConsumer.outputLineAvailable(line); } else { @@ -186,7 +165,7 @@ public class JavacMain { } finally { fileManager.close(); - if (nowUsingJavac) { + if (usingJavac) { cleanupJavacNameTable(); } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java index b5dc9bad44fb..65c92e2ae76f 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java @@ -29,6 +29,9 @@ import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; import io.netty.util.concurrent.ImmediateEventExecutor; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.api.CanceledStatus; +import org.jetbrains.jps.builders.impl.java.JavacCompilerTool; +import org.jetbrains.jps.builders.java.JavaBuilderUtil; +import org.jetbrains.jps.builders.java.JavaCompilingTool; import org.jetbrains.jps.service.SharedThreadPool; import javax.tools.*; @@ -44,7 +47,7 @@ public class JavacServer { public static final int DEFAULT_SERVER_PORT = 7878; public static final String SERVER_SUCCESS_START_MESSAGE = "Javac server started successfully. Listening on port: "; public static final String SERVER_ERROR_START_MESSAGE = "Error starting Javac Server: "; - public static final String USE_ECLIPSE_COMPILER_PROPERTY = "use.eclipse.compiler"; + public static final String JPS_JAVA_COMPILING_TOOL_PROPERTY = "jps.java.compiling.tool"; private ChannelRegistrar myChannelRegistrar; @@ -153,7 +156,8 @@ public class JavacServer { }; try { - final boolean rc = JavacMain.compile(options, files, classpath, platformCp, sourcePath, outs, diagnostic, outputSink, canceledStatus, System.getProperty(USE_ECLIPSE_COMPILER_PROPERTY) != null); + JavaCompilingTool tool = getCompilingTool(); + final boolean rc = JavacMain.compile(options, files, classpath, platformCp, sourcePath, outs, diagnostic, outputSink, canceledStatus, tool); return JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createBuildCompletedResponse(rc)); } catch (Throwable e) { @@ -163,6 +167,17 @@ public class JavacServer { } } + private static JavaCompilingTool getCompilingTool() { + String property = System.getProperty(JPS_JAVA_COMPILING_TOOL_PROPERTY); + if (property != null) { + JavaCompilingTool tool = JavaBuilderUtil.findCompilingTool(property); + if (tool != null) { + return tool; + } + } + return new JavacCompilerTool(); + } + private final Set myCancelHandlers = Collections.synchronizedSet(new HashSet()); public void cancelBuilds() { diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java index 40b646e9a8dc..bb66e9c6b09f 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java @@ -25,6 +25,7 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.concurrency.Semaphore; +import org.jetbrains.jps.builders.java.JavaCompilingTool; import org.jetbrains.jps.cmdline.ClasspathBootstrap; import org.jetbrains.jps.service.SharedThreadPool; @@ -44,7 +45,7 @@ public class JavacServerBootstrap { int port, File workingDir, List vmOptions, - boolean useEclipseCompiler) throws Exception { + JavaCompilingTool compilingTool) throws Exception { final List cmdLine = new ArrayList(); appendParam(cmdLine, getVMExecutablePath(sdkHomePath)); appendParam(cmdLine, "-XX:MaxPermSize=150m"); @@ -82,9 +83,7 @@ public class JavacServerBootstrap { appendParam(cmdLine, "-Duser.region=" + region); } - if (useEclipseCompiler) { - appendParam(cmdLine, "-D" + JavacServer.USE_ECLIPSE_COMPILER_PROPERTY); - } + appendParam(cmdLine, "-D" + JavacServer.JPS_JAVA_COMPILING_TOOL_PROPERTY + "=" + compilingTool.getId()); // this will disable standard extensions to ensure javac is loaded from the right tools.jar appendParam(cmdLine, "-Djava.ext.dirs="); @@ -95,7 +94,7 @@ public class JavacServerBootstrap { appendParam(cmdLine, "-classpath"); - final List cp = ClasspathBootstrap.getJavacServerClasspath(sdkHomePath, useEclipseCompiler); + final List cp = ClasspathBootstrap.getJavacServerClasspath(sdkHomePath, compilingTool); final StringBuilder classpath = new StringBuilder(); for (File file : cp) { if (classpath.length() > 0) { @@ -156,17 +155,15 @@ public class JavacServerBootstrap { public void onTextAvailable(ProcessEvent event, Key outputType) { if (outputType == ProcessOutputTypes.STDERR) { - try { - final String text = event.getText(); - if (text != null) { - if (text.contains(JavacServer.SERVER_SUCCESS_START_MESSAGE) || text.contains(JavacServer.SERVER_ERROR_START_MESSAGE)) { - processHandler.removeProcessListener(this); - serverStartMessage.set(text); - } + final String text = event.getText(); + if (text != null && (text.contains(JavacServer.SERVER_SUCCESS_START_MESSAGE) || text.contains(JavacServer.SERVER_ERROR_START_MESSAGE))) { + try { + processHandler.removeProcessListener(this); + serverStartMessage.set(text); + } + finally { + semaphore.up(); } - } - finally { - semaphore.up(); } } } diff --git a/platform/core-impl/src/com/intellij/openapi/editor/ex/util/SegmentArray.java b/platform/core-impl/src/com/intellij/openapi/editor/ex/util/SegmentArray.java index b3e91d67ad05..2918656a952b 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/ex/util/SegmentArray.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/ex/util/SegmentArray.java @@ -27,8 +27,8 @@ import org.jetbrains.annotations.NotNull; */ public class SegmentArray { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.ex.util.SegmentArray"); - private int[] myStarts; - private int[] myEnds; + protected int[] myStarts; + protected int[] myEnds; protected int mySegmentCount = 0; protected static final int INITIAL_SIZE = 64; @@ -84,26 +84,32 @@ public class SegmentArray { return newArray; } + protected int noSegmentsAvailable(int offset) { + throw new IllegalStateException("no segments available. offset = " + offset); + } + + protected int offsetOutOfRange(int offset, int lastValidOffset) { + throw new IndexOutOfBoundsException("Wrong offset: " + offset + ". Should be in range: [0, " + lastValidOffset + "]"); + } + public final int findSegmentIndex(int offset) { if (mySegmentCount <= 0) { - if (offset == 0) return 0; - throw new IllegalStateException("no segments available. offset = "+offset); + return offset == 0 ? 0 : noSegmentsAvailable(offset); } final int lastValidOffset = getLastValidOffset(); - if (offset > lastValidOffset || offset < 0) { - throw new IndexOutOfBoundsException("Wrong offset: " + offset + ". Should be in range: [0, " + lastValidOffset + "]"); + return offsetOutOfRange(offset, lastValidOffset); } - final int lastValidIndex = mySegmentCount - 1; - if (offset == lastValidOffset) return lastValidIndex; + int end = mySegmentCount - 1; + if (offset == lastValidOffset) { + return end; + } int start = 0; - int end = lastValidIndex; - - while (start < end) { - int i = (start + end) / 2; + while (start <= end) { + int i = (start + end) >>> 1; if (offset < myStarts[i]) { end = i - 1; } @@ -115,9 +121,12 @@ public class SegmentArray { } } + return segmentNotFound(offset, start); + } + + protected int segmentNotFound(int offset, int start) { // This means that there is a gap at given offset assert myStarts[start] <= offset && offset < myEnds[start] : start; - return start; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java index d20e48149b1c..51e1686104dc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java @@ -184,17 +184,17 @@ public class DaemonListeners implements Disposable { !worthBothering(editor.getDocument(), editor.getProject())) { return; //no need to stop daemon if something happened in the console } - - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - if (!editor.getComponent().isShowing() && !application.isUnitTestMode() || - myProject.isDisposed()) { - return; + if (!application.isUnitTestMode()) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + if (!editor.getComponent().isShowing() || myProject.isDisposed()) { + return; + } + myDaemonCodeAnalyzer.hideLastIntentionHint(); } - myDaemonCodeAnalyzer.hideLastIntentionHint(); - } - }, ModalityState.current()); + }, ModalityState.current()); + } } }, this); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java index 026564d7d2a0..a965a850b2fa 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java @@ -39,7 +39,6 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.ui.LightweightHint; import com.intellij.util.containers.WeakList; -import com.intellij.util.ui.UIUtil; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -184,7 +183,7 @@ public class CodeFoldingManagerImpl extends CodeFoldingManager implements Projec @Override public void releaseFoldings(@NotNull Editor editor) { - ApplicationManager.getApplication().assertIsDispatchThread(); + ApplicationManagerEx.getApplicationEx().assertIsDispatchThread(editor.getComponent()); final Project project = editor.getProject(); if (project != null && (!project.equals(myProject) || !project.isOpen())) return; @@ -217,32 +216,26 @@ public class CodeFoldingManagerImpl extends CodeFoldingManager implements Projec PsiDocumentManager.getInstance(myProject).commitDocument(document); - Runnable operation = new Runnable() { + Runnable runnable = updateFoldRegions(editor, true, true); + if (runnable != null) { + runnable.run(); + } + if (myProject.isDisposed() || editor.isDisposed()) return; + foldingModel.runBatchFoldingOperation(new Runnable() { @Override public void run() { - Runnable runnable = updateFoldRegions(editor, true, true); - if (runnable != null) { - runnable.run(); + DocumentFoldingInfo documentFoldingInfo = getDocumentFoldingInfo(document); + Editor[] editors = EditorFactory.getInstance().getEditors(document, myProject); + for (Editor otherEditor : editors) { + if (otherEditor == editor) continue; + documentFoldingInfo.loadFromEditor(otherEditor); + break; } - if (myProject.isDisposed() || editor.isDisposed()) return; - foldingModel.runBatchFoldingOperation(new Runnable() { - @Override - public void run() { - DocumentFoldingInfo documentFoldingInfo = getDocumentFoldingInfo(document); - Editor[] editors = EditorFactory.getInstance().getEditors(document, myProject); - for (Editor otherEditor : editors) { - if (otherEditor == editor) continue; - documentFoldingInfo.loadFromEditor(otherEditor); - break; - } - documentFoldingInfo.setToEditor(editor); + documentFoldingInfo.setToEditor(editor); - documentFoldingInfo.clear(); - } - }); + documentFoldingInfo.clear(); } - }; - UIUtil.invokeLaterIfNeeded(operation); + }); } @Override diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/DocumentFoldingInfo.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/DocumentFoldingInfo.java index 0e420b04de2d..9294f108eb75 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/DocumentFoldingInfo.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/DocumentFoldingInfo.java @@ -21,6 +21,7 @@ import com.intellij.lang.folding.FoldingBuilder; import com.intellij.lang.folding.FoldingDescriptor; import com.intellij.lang.folding.LanguageFolding; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -38,7 +39,6 @@ import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import javax.swing.*; import java.util.*; class DocumentFoldingInfo implements JDOMExternalizable, CodeFoldingState { @@ -64,7 +64,7 @@ class DocumentFoldingInfo implements JDOMExternalizable, CodeFoldingState { } void loadFromEditor(@NotNull Editor editor) { - assertDispatchThread(); + assertDispatchThread(editor); LOG.assertTrue(!editor.isDisposed()); clear(); @@ -95,12 +95,12 @@ class DocumentFoldingInfo implements JDOMExternalizable, CodeFoldingState { } } - private static void assertDispatchThread() { - assert SwingUtilities.isEventDispatchThread() : Thread.currentThread(); + private static void assertDispatchThread(@NotNull Editor editor) { + ApplicationManagerEx.getApplicationEx().assertIsDispatchThread(editor.getComponent()); } void setToEditor(@NotNull final Editor editor) { - assertDispatchThread(); + assertDispatchThread(editor); final PsiManager psiManager = PsiManager.getInstance(myProject); if (psiManager.isDisposed()) return; diff --git a/platform/platform-api/src/com/intellij/openapi/wm/IdeGlassPaneUtil.java b/platform/platform-api/src/com/intellij/openapi/wm/IdeGlassPaneUtil.java index 0c76911b6821..67375287e7b2 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/IdeGlassPaneUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/IdeGlassPaneUtil.java @@ -16,11 +16,12 @@ package com.intellij.openapi.wm; -import com.intellij.openapi.ui.Painter; import com.intellij.openapi.Disposable; +import com.intellij.openapi.ui.Painter; +import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Disposer; -import com.intellij.util.ui.update.UiNotifyConnector; import com.intellij.util.ui.update.Activatable; +import com.intellij.util.ui.update.UiNotifyConnector; import javax.swing.*; import java.awt.*; @@ -69,6 +70,9 @@ public class IdeGlassPaneUtil { public static boolean canBePreprocessed(MouseEvent e) { Component c = SwingUtilities.getDeepestComponentAt(e.getComponent(), e.getX(), e.getY()); + if (JBPopupFactory.getInstance().getParentBalloonFor(c) != null) { + return false; + } if (c instanceof IdeGlassPane.TopComponent) { return ((IdeGlassPane.TopComponent)c).canBePreprocessed(e); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java index f858002f0743..818466ba3153 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java @@ -273,6 +273,10 @@ public class DarculaLaf extends BasicLookAndFeel { } protected Object parseValue(String key, @NotNull String value) { + if ("null".equals(value)) { + return null; + } + if (key.endsWith("Insets")) { final List numbers = StringUtil.split(value, ","); return new InsetsUIResource(Integer.parseInt(numbers.get(0)), diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java index 1bbf9aae650c..8349aac12497 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java @@ -45,7 +45,6 @@ import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; import java.awt.*; import java.util.Arrays; import java.util.List; @@ -201,7 +200,6 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList } private void runBatchFoldingOperation(final Runnable operation, final boolean dontCollapseCaret, final boolean moveCaret) { - LOG.assertTrue(SwingUtilities.isEventDispatchThread(), Thread.currentThread().toString()); assertIsDispatchThreadForEditor(); boolean oldDontCollapseCaret = myDoNotCollapseCaret; myDoNotCollapseCaret |= dontCollapseCaret; diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java index 978c26068655..32169662ba2a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java @@ -41,6 +41,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; @@ -141,7 +142,7 @@ public final class EditorHistoryManager extends AbstractProjectComponent impleme } LOG.assertTrue(selectedEditor != null); final int selectedProviderIndex = ArrayUtilRt.find(editors, selectedEditor); - LOG.assertTrue(selectedProviderIndex != -1); + LOG.assertTrue(selectedProviderIndex != -1, "Can't find " + selectedEditor + " among " + Arrays.asList(editors)); final HistoryEntry entry = getEntry(file); if(entry != null){ diff --git a/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java b/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java index a4201ea37022..d81ea5846148 100644 --- a/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java @@ -83,7 +83,13 @@ public class SystemNotificationsImpl extends SystemNotifications implements Pers } } catch (Throwable t) { - Logger.getInstance(SystemNotifications.class).warn(t); + Logger logger = Logger.getInstance(SystemNotifications.class); + if (logger.isDebugEnabled()) { + logger.debug(t); + } + else { + logger.info(t.getMessage()); + } } return null; diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/SelectUnselectOccurrenceActionsTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/SelectUnselectOccurrenceActionsTest.java index 92496966a0df..42faeaa86e85 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/SelectUnselectOccurrenceActionsTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/SelectUnselectOccurrenceActionsTest.java @@ -67,9 +67,9 @@ public class SelectUnselectOccurrenceActionsTest extends LightPlatformCodeInsigh "another text here"); executeSelectAllAction(); checkResult("some text\n" + - "some texts\n" + - "some texts\n" + - "another text here"); + "some texts\n" + + "some texts\n" + + "another text here"); assertEquals(0, hintCount); } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTest.java index cf53f977c813..09debec55b6b 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTest.java @@ -17,29 +17,20 @@ package com.intellij.openapi.fileEditor; import com.intellij.ide.ui.UISettings; import com.intellij.mock.Mock; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.ExpandMacroToPathMap; import com.intellij.openapi.fileEditor.impl.EditorWithProviderComposite; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.PlatformTestCase; import com.intellij.testFramework.PlatformTestUtil; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import org.jdom.Document; import org.jdom.Element; -import org.jdom.JDOMException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.model.serialization.PathMacroUtil; import javax.swing.*; import java.io.File; -import java.io.IOException; import java.util.Arrays; import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; /** * @author Dmitry Avdeev @@ -77,17 +68,18 @@ public class FileEditorManagerTest extends FileEditorManagerTestCase { openFiles(" \n" + " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + " \n" + " \n" + " \n" + - " \n" + " \n"); FileEditor[] selectedEditors = myManager.getSelectedEditors(); assertEquals(1, selectedEditors.length); @@ -157,24 +149,6 @@ public class FileEditorManagerTest extends FileEditorManagerTestCase { assertEquals(Arrays.asList(fileNames), names); } - private void openFiles(String s) throws IOException, JDOMException, InterruptedException, ExecutionException { - Document document = JDOMUtil.loadDocument(s); - Element rootElement = document.getRootElement(); - ExpandMacroToPathMap map = new ExpandMacroToPathMap(); - map.addMacroExpand(PathMacroUtil.PROJECT_DIR_MACRO_NAME, getTestDataPath()); - map.substitute(rootElement, true, true); - - myManager.readExternal(rootElement); - - Future future = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { - @Override - public void run() { - myManager.getMainSplitters().openFiles(); - } - }); - future.get(); - } - @Override protected String getTestDataPath() { return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/platform/platform-tests/testData/fileEditorManager"; diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTestCase.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTestCase.java index aa528681114b..28d5def0a218 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTestCase.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTestCase.java @@ -1,13 +1,27 @@ package com.intellij.openapi.fileEditor; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.ExpandMacroToPathMap; import com.intellij.openapi.components.impl.ComponentManagerImpl; import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager; import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl; import com.intellij.openapi.fileEditor.impl.FileEditorProviderManagerImpl; +import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; import com.intellij.ui.docking.DockManager; +import com.intellij.util.ui.UIUtil; +import org.jdom.Document; +import org.jdom.Element; +import org.jdom.JDOMException; +import org.jetbrains.jps.model.serialization.PathMacroUtil; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; /** * @author Dmitry Avdeev @@ -40,4 +54,30 @@ public abstract class FileEditorManagerTestCase extends LightPlatformCodeInsight protected VirtualFile getFile(String path) { return LocalFileSystem.getInstance().refreshAndFindFileByPath(getTestDataPath() + path); } + + protected void openFiles(String s) throws IOException, JDOMException, InterruptedException, ExecutionException { + Document document = JDOMUtil.loadDocument(s); + Element rootElement = document.getRootElement(); + ExpandMacroToPathMap map = new ExpandMacroToPathMap(); + map.addMacroExpand(PathMacroUtil.PROJECT_DIR_MACRO_NAME, getTestDataPath()); + map.substitute(rootElement, true, true); + + myManager.readExternal(rootElement); + + Future future = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + myManager.getMainSplitters().openFiles(); + } + }); + while (true) { + try { + future.get(100, TimeUnit.MILLISECONDS); + return; + } + catch (TimeoutException e) { + UIUtil.dispatchAllInvocationEvents(); + } + } + } } diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 477d6e267c28..6903c6bcca14 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -1585,6 +1585,7 @@ public class UIUtil { g.setComposite(X_RENDER_ACTIVE.getValue() ? AlphaComposite.SrcOver : AlphaComposite.Src); } + /** @see #pump() */ @TestOnly public static void dispatchAllInvocationEvents() { assert SwingUtilities.isEventDispatchThread() : Thread.currentThread(); @@ -1604,6 +1605,7 @@ public class UIUtil { } } + /** @see #dispatchAllInvocationEvents() */ @TestOnly public static void pump() { assert !SwingUtilities.isEventDispatchThread(); diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java index 1cf23c566d0b..7130b7747c25 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java @@ -115,7 +115,7 @@ public abstract class XDebuggerEvaluator { * @param offset offset * @param sideEffectsAllowed if this parameter is false, the expression should not have any side effects when evaluated * (such expressions are evaluated in quick popups) - * @return pair of text range of expression (to display as link) and actual expression to evaluate (optional, could be null) + * @return pair of text range of expression (to highlight as link) and actual expression to evaluate (optional, could be null) */ @Nullable public Pair getExpressionAtOffset(@NotNull Project project, @NotNull Document document, int offset, boolean sideEffectsAllowed) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java index 2fd665496ba6..def016c080fd 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java @@ -15,6 +15,7 @@ */ package com.intellij.xdebugger.impl; +import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; @@ -35,6 +36,19 @@ import org.jetbrains.annotations.Nullable; public abstract class DebuggerSupport { private static final ExtensionPointName EXTENSION_POINT = ExtensionPointName.create("com.intellij.xdebugger.debuggerSupport"); + protected static final class DisabledActionHandler extends DebuggerActionHandler { + public static final DisabledActionHandler INSTANCE = new DisabledActionHandler(); + + @Override + public void perform(@NotNull Project project, AnActionEvent event) { + } + + @Override + public boolean isEnabled(@NotNull Project project, AnActionEvent event) { + return false; + } + } + @NotNull public static DebuggerSupport[] getDebuggerSupports() { return Extensions.getExtensions(EXTENSION_POINT); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AddToWatchesAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AddToWatchesAction.java index 33bfc5a33e02..6f779e5a91d2 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AddToWatchesAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AddToWatchesAction.java @@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull; /** * @author nik */ -public class AddToWatchesAction extends XDebuggerActionBase { +final class AddToWatchesAction extends XDebuggerActionBase { public AddToWatchesAction() { super(true); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EvaluateAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EvaluateAction.java index 39e594902ef8..ea17644e53f0 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EvaluateAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EvaluateAction.java @@ -15,17 +15,18 @@ */ package com.intellij.xdebugger.impl.actions; -import org.jetbrains.annotations.NotNull; import com.intellij.xdebugger.impl.DebuggerSupport; +import org.jetbrains.annotations.NotNull; /** * @author nik */ -public class EvaluateAction extends XDebuggerActionBase { +final class EvaluateAction extends XDebuggerActionBase { public EvaluateAction() { super(true); } + @Override @NotNull protected DebuggerActionHandler getHandler(@NotNull final DebuggerSupport debuggerSupport) { return debuggerSupport.getEvaluateHandler(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/QuickEvaluateAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/QuickEvaluateAction.java index cf26dcce81eb..be54d591d378 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/QuickEvaluateAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/QuickEvaluateAction.java @@ -65,10 +65,14 @@ public class QuickEvaluateAction extends XDebuggerActionBase { @Override public boolean isEnabled(@NotNull final Project project, final AnActionEvent event) { - if (!myHandler.isEnabled(project)) return false; + if (!myHandler.isEnabled(project)) { + return false; + } Editor editor = event.getData(CommonDataKeys.EDITOR); - if (editor == null) return false; + if (editor == null) { + return false; + } InputEvent inputEvent = event.getInputEvent(); if (inputEvent instanceof MouseEvent && inputEvent.isAltDown()) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XAddToWatchesFromEditorActionHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XAddToWatchesFromEditorActionHandler.java index 3b52fa58bf7b..0a261501fa95 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XAddToWatchesFromEditorActionHandler.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XAddToWatchesFromEditorActionHandler.java @@ -20,7 +20,7 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.text.StringUtil; import com.intellij.xdebugger.XDebugSession; -import com.intellij.xdebugger.frame.XStackFrame; +import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; import com.intellij.xdebugger.impl.XDebugSessionImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -42,10 +42,10 @@ public class XAddToWatchesFromEditorActionHandler extends XDebuggerActionHandler } String text = editor.getSelectionModel().getSelectedText(); - if (text == null && session.isSuspended()) { - final XStackFrame stackFrame = session.getCurrentStackFrame(); - if (stackFrame != null) { - text = XDebuggerEvaluateActionHandler.getExpressionText(stackFrame.getEvaluator(), editor.getProject(), editor); + if (text == null) { + XDebuggerEvaluator evaluator = session.getDebugProcess().getEvaluator(); + if (evaluator != null) { + text = XDebuggerEvaluateActionHandler.getExpressionText(evaluator, editor.getProject(), editor); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java index d892acaf0f44..1a24b3074216 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java @@ -28,7 +28,6 @@ import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; import com.intellij.xdebugger.frame.XStackFrame; import com.intellij.xdebugger.frame.XValue; -import com.intellij.xdebugger.impl.actions.XDebuggerSuspendedActionHandler; import com.intellij.xdebugger.impl.evaluate.XDebuggerEvaluationDialog; import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase; import org.jetbrains.annotations.NotNull; @@ -37,14 +36,15 @@ import org.jetbrains.annotations.Nullable; /** * @author nik */ -public class XDebuggerEvaluateActionHandler extends XDebuggerSuspendedActionHandler { +public class XDebuggerEvaluateActionHandler extends XDebuggerActionHandler { @Override protected void perform(@NotNull final XDebugSession session, final DataContext dataContext) { XDebuggerEditorsProvider editorsProvider = session.getDebugProcess().getEditorsProvider(); XStackFrame stackFrame = session.getCurrentStackFrame(); - if (stackFrame == null) return; - final XDebuggerEvaluator evaluator = stackFrame.getEvaluator(); - if (evaluator == null) return; + final XDebuggerEvaluator evaluator = session.getDebugProcess().getEvaluator(); + if (evaluator == null) { + return; + } @Nullable Editor editor = CommonDataKeys.EDITOR.getData(dataContext); @@ -64,7 +64,7 @@ public class XDebuggerEvaluateActionHandler extends XDebuggerSuspendedActionHand text = value.getEvaluationExpression(); } } - new XDebuggerEvaluationDialog(session, editorsProvider, evaluator, StringUtil.notNullize(text), stackFrame.getSourcePosition()).show(); + new XDebuggerEvaluationDialog(session, editorsProvider, evaluator, StringUtil.notNullize(text), stackFrame == null ? null : stackFrame.getSourcePosition()).show(); } @Nullable @@ -86,11 +86,6 @@ public class XDebuggerEvaluateActionHandler extends XDebuggerSuspendedActionHand @Override protected boolean isEnabled(final @NotNull XDebugSession session, final DataContext dataContext) { - if (!super.isEnabled(session, dataContext)) { - return false; - } - - XStackFrame stackFrame = session.getCurrentStackFrame(); - return stackFrame != null && stackFrame.getEvaluator() != null; + return session.getDebugProcess().getEvaluator() != null; } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java index 741b2878e8b2..4abf17312585 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java @@ -29,7 +29,6 @@ import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.evaluation.EvaluationMode; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; -import com.intellij.xdebugger.frame.XStackFrame; import com.intellij.xdebugger.impl.XDebugSessionImpl; import com.intellij.xdebugger.impl.actions.XDebuggerActions; import com.intellij.xdebugger.impl.ui.XDebuggerEditorBase; @@ -38,6 +37,7 @@ import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel; import com.intellij.xdebugger.impl.ui.tree.nodes.EvaluatingExpressionRootNode; import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -61,10 +61,10 @@ public class XDebuggerEvaluationDialog extends DialogWrapper { private final boolean myIsCodeFragmentEvaluationSupported; public XDebuggerEvaluationDialog(@NotNull XDebugSession session, - final @NotNull XDebuggerEditorsProvider editorsProvider, + @NotNull XDebuggerEditorsProvider editorsProvider, @NotNull XDebuggerEvaluator evaluator, @NotNull String text, - final XSourcePosition sourcePosition) { + @Nullable XSourcePosition sourcePosition) { super(session.getProject(), true); mySession = session; myEditorsProvider = editorsProvider; @@ -212,8 +212,7 @@ public class XDebuggerEvaluationDialog extends DialogWrapper { inputEditor.saveTextInHistory(); String expression = inputEditor.getText(); - XStackFrame frame = mySession.getCurrentStackFrame(); - XDebuggerEvaluator evaluator = frame == null ? null : frame.getEvaluator(); + XDebuggerEvaluator evaluator = mySession.getDebugProcess().getEvaluator(); if (evaluator == null) { evaluationCallback.errorOccurred(XDebuggerBundle.message("xdebugger.evaluate.stack.frame.has.not.evaluator")); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java index bdb34a155a2f..81e94ff7a851 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java @@ -26,7 +26,6 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; -import com.intellij.xdebugger.frame.XStackFrame; import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint; import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler; import com.intellij.xdebugger.impl.evaluate.quick.common.ValueHintType; @@ -103,12 +102,9 @@ public class XQuickEvaluateHandler extends QuickEvaluateHandler { public int getValueLookupDelay(final Project project) { XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession(); if (session != null) { - XStackFrame stackFrame = session.getCurrentStackFrame(); - if (stackFrame != null) { - XDebuggerEvaluator evaluator = stackFrame.getEvaluator(); - if (evaluator != null) { - return evaluator.getValuePopupDelay(); - } + XDebuggerEvaluator evaluator = session.getDebugProcess().getEvaluator(); + if (evaluator != null) { + return evaluator.getValuePopupDelay(); } } return 700; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java index 415742b6a700..ebf5d69a166e 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java @@ -16,6 +16,10 @@ package com.intellij.xdebugger.impl.evaluate.quick; import com.intellij.codeInsight.hint.HintUtil; +import com.intellij.execution.console.LanguageConsoleImpl; +import com.intellij.execution.console.LanguageConsoleView; +import com.intellij.execution.impl.ConsoleViewImpl; +import com.intellij.execution.ui.ConsoleView; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileDocumentManager; @@ -72,7 +76,17 @@ public class XValueHint extends AbstractValueHint { myEvaluator = evaluator; myDebugSession = session; myExpression = XDebuggerEvaluateActionHandler.getExpressionText(expressionData, editor.getDocument()); - final VirtualFile file = FileDocumentManager.getInstance().getFile(editor.getDocument()); + + VirtualFile file; + ConsoleView consoleView = ConsoleViewImpl.CONSOLE_VIEW_IN_EDITOR_VIEW.get(editor); + if (consoleView instanceof LanguageConsoleView) { + LanguageConsoleImpl console = ((LanguageConsoleView)consoleView).getConsole(); + file = console.getHistoryViewer() == editor ? console.getVirtualFile() : null; + } + else { + file = FileDocumentManager.getInstance().getFile(editor.getDocument()); + } + myExpressionPosition = file != null ? XDebuggerUtil.getInstance().createPositionByOffset(file, expressionData.first.getStartOffset()) : null; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java index 48defd3a08e9..088b4004798b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java @@ -123,8 +123,7 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi @Override public void addWatchExpression(@NotNull String expression, int index, final boolean navigateToWatchNode) { - XStackFrame stackFrame = mySession.getCurrentStackFrame(); - myRootNode.addWatchExpression(stackFrame == null ? null : stackFrame.getEvaluator(), expression, index, navigateToWatchNode); + myRootNode.addWatchExpression(mySession.getDebugProcess().getEvaluator(), expression, index, navigateToWatchNode); updateSessionData(); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/EvaluatingExpressionRootNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/EvaluatingExpressionRootNode.java index 379b07c5426a..1833ae34d1e5 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/EvaluatingExpressionRootNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/EvaluatingExpressionRootNode.java @@ -44,7 +44,7 @@ public class EvaluatingExpressionRootNode extends XValueContainerNode disjunctions = PsiTreeUtil.getChildrenOfTypeAsList(parameter.getTypeElement(), PsiTypeElement.class); + for (int i = 0; i < disjunctions.size(); i++) { + final PsiCatchSection copy = (PsiCatchSection)catchSection.copy(); + + final PsiTypeElement typeElement = assertNotNull(assertNotNull(copy.getParameter()).getTypeElement()); + final PsiTypeElement newTypeElement = factory.createTypeElementFromText(disjunctions.get(i).getText(), catchSection); + typeElement.replace(newTypeElement); + + grandParent.addBefore(copy, catchSection); + + if (i == 0) { + // clear the original from type annotations: they belong to the first disjunction and should not appear in others + final PsiModifierList modifierList = parameter.getModifierList(); + if (modifierList != null) { + for (PsiAnnotation annotation : modifierList.getAnnotations()) { + if (PsiImplUtil.findApplicableTarget(annotation, PsiAnnotation.TargetType.TYPE_USE) == PsiAnnotation.TargetType.TYPE_USE) { + annotation.delete(); + } + } } } } - final PsiElementFactory factory = JavaPsiFacade.getElementFactory(element.getProject()); - for (PsiType disjunction : ((PsiDisjunctionType)type).getDisjunctions()) { - final PsiCatchSection copy = (PsiCatchSection)catchSection.copy(); - final PsiParameter copyParameter = copy.getParameter(); - assert copyParameter != null : copy.getText(); - final PsiTypeElement typeElement = copyParameter.getTypeElement(); - assert typeElement != null : copyParameter.getText(); - final PsiTypeElement newTypeElement = factory.createTypeElement(disjunction); - typeElement.replace(newTypeElement); - grandParent.addBefore(copy, catchSection); - } - catchSection.delete(); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index dee417b1a58a..4f7ebf4bbcd4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -168,9 +168,12 @@ public class GroovyAnnotator extends GroovyElementVisitor { @Override public void visitNamedArgument(GrNamedArgument argument) { - final PsiElement parent = argument.getParent().getParent(); - if (parent instanceof GrIndexProperty) { - myHolder.createErrorAnnotation(argument, GroovyBundle.message("named.arguments.are.not.allowed.inside.index.operations")); + PsiElement parent = argument.getParent(); + if (parent instanceof GrArgumentList) { + final PsiElement pparent = parent.getParent(); + if (pparent instanceof GrIndexProperty) { + myHolder.createErrorAnnotation(argument, GroovyBundle.message("named.arguments.are.not.allowed.inside.index.operations")); + } } } diff --git a/spellchecker/src/com/intellij/spellchecker/english.dic b/spellchecker/src/com/intellij/spellchecker/english.dic index 169e4c20e7ab..0047044678a5 100644 --- a/spellchecker/src/com/intellij/spellchecker/english.dic +++ b/spellchecker/src/com/intellij/spellchecker/english.dic @@ -68545,6 +68545,7 @@ funding fundraiser fundraisers funds +fundraising funeral funeral's funerals diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java index 36ae151d5964..5d35f0f4ae69 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java @@ -325,7 +325,11 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator value = CachedValuesManager.getManager(includedDocument.getProject()).createCachedValue( new CachedValueProvider(){ public Result compute() { - return new Result(attributeDescriptor, attributeDescriptor.getDependences()); + Object[] deps = attributeDescriptor.getDependences(); + if (deps.length == 0) { + LOG.error(attributeDescriptor + " returned no dependencies"); + } + return new Result(attributeDescriptor, deps); } }, false