diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 211bcfb67774..7151855d7a4d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -1378,7 +1378,7 @@ public class HighlightUtil extends HighlightUtilBase { if (expr instanceof PsiThisExpression) { final PsiMethod psiMethod = PsiTreeUtil.getParentOfType(expr, PsiMethod.class); - if (psiMethod == null || psiMethod.getContainingClass() != aClass) { + if (psiMethod == null || psiMethod.getContainingClass() != aClass && !isInsideDefaultMethod(psiMethod, aClass)) { if (aClass.isInterface()) { return thisNotFoundInInterfaceInfo(expr); } @@ -1393,6 +1393,13 @@ public class HighlightUtil extends HighlightUtilBase { } return null; } + + private static boolean isInsideDefaultMethod(PsiMethod method, PsiClass aClass) { + while (method != null && method.getContainingClass() != aClass) { + method = PsiTreeUtil.getParentOfType(method, PsiMethod.class, true); + } + return method != null && method.hasModifierProperty(PsiModifier.DEFAULT); + } private static HighlightInfo thisNotFoundInInterfaceInfo(@NotNull PsiExpression expr) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expr).descriptionAndTooltip("Cannot find symbol variable this").create(); 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 560dcbd948dc..85fae4536e8a 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java @@ -93,7 +93,15 @@ public class PsiCapturedWildcardType extends PsiType { } public PsiType getUpperBound () { - return myExistential.isExtends() ? myExistential.getBound() : PsiType.getJavaLangObject(myContext.getManager(), getResolveScope()); + final PsiType bound = myExistential.getBound(); + if (myExistential.isExtends()) { + return bound; + } + else { + return bound instanceof PsiCapturedWildcardType + ? ((PsiCapturedWildcardType)bound).getUpperBound() + : PsiType.getJavaLangObject(myContext.getManager(), getResolveScope()); + } } public PsiWildcardType getWildcard() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA105846.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA105846.java new file mode 100644 index 000000000000..8b9c700484c9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA105846.java @@ -0,0 +1,5 @@ +class MyClass { + public static void main(Class clazz){ + clazz = (Class) clazz.getSuperclass(); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/ThisAccessibility.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/ThisAccessibility.java new file mode 100644 index 000000000000..c43ef5200b04 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/ThisAccessibility.java @@ -0,0 +1,24 @@ +interface Bazz { + Bazz foo = Bazz.this; + static void foo1() { + Bazz foo = Bazz.this; + } + + Runnable bar = new Runnable() { + @Override + public void run() { + Bazz f = Bazz.this; + } + }; + + + default void foo() { + Bazz foo = Bazz.this; + Runnable r = new Runnable() { + @Override + public void run() { + Bazz f = Bazz.this; + } + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index f2a6e3af1fa7..cf73a8cd1910 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -205,6 +205,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testIDEA99347() { doTest5(false); } public void testIDEA86875() { doTest5(false); } public void testIDEA103760(){ doTest5(false); } + public void testIDEA105846(){ doTest5(false); } public void testWildcardsOnRawTypes() { doTest5(false); } public void testDisableWithinBoundsCheckForSuperWildcards() { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java index dab1d6306e9b..e77dff317192 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java @@ -29,6 +29,7 @@ public class Interface8MethodsHighlightingTest extends LightDaemonAnalyzerTestCa public void testInheritDefaultMethodInInterface() { doTest(false, false); } public void testStaticMethodsInFunctionalInterface() { doTest(false, false); } public void testCyclicSubstitutor() { doTest(false, false); } + public void testThisAccessibility() { doTest(false, false); } private void doTest() { doTest(false, false); diff --git a/platform/lang-impl/src/com/intellij/internal/SelectionBasedPsiElementInternalAction.java b/platform/lang-impl/src/com/intellij/internal/SelectionBasedPsiElementInternalAction.java new file mode 100644 index 000000000000..4c3e8cb2ab94 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/internal/SelectionBasedPsiElementInternalAction.java @@ -0,0 +1,145 @@ +package com.intellij.internal; + +import com.intellij.codeInsight.hint.HintManager; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.ApplicationManagerEx; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.SelectionModel; +import com.intellij.openapi.util.Pass; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.refactoring.IntroduceTargetChooser; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * @author Nikolay Matveev + */ +public abstract class SelectionBasedPsiElementInternalAction extends AnAction { + @NotNull + protected final Class myClass; + @NotNull + protected final Class myFileClass; + + protected SelectionBasedPsiElementInternalAction(@NotNull Class aClass, @NotNull Class fileClass) { + myClass = aClass; + myFileClass = fileClass; + } + + @Override + public final void actionPerformed(AnActionEvent e) { + final Editor editor = getEditor(e); + final PsiFile file = getPsiFile(e); + if (editor == null || file == null) return; + + final List expressions = getElement(editor, file); + T first = ContainerUtil.getFirstItem(expressions); + + if (expressions.size() > 1) { + IntroduceTargetChooser.showChooser( + editor, expressions, + new Pass() { + @Override + public void pass(@NotNull T expression) { + performOnElement(editor, expression); + } + }, + new Function() { + public String fun(@NotNull T expression) { + return expression.getText(); + } + } + ); + } + else if (expressions.size() == 1 && first != null) { + performOnElement(editor, first); + } + else if (expressions.isEmpty()) { + showError(editor); + } + } + + protected void showError(@NotNull final Editor editor) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + final String errorHint = "Cannot find element of class " + myClass.getSimpleName() + " at selection/offset"; + HintManager.getInstance().showErrorHint(editor, errorHint); + } + }); + } + + private void performOnElement(@NotNull final Editor editor, @NotNull T first) { + final TextRange textRange = first.getTextRange(); + editor.getSelectionModel().setSelection(textRange.getStartOffset(), textRange.getEndOffset()); + final String informationHint = getInformationHint(first); + if (informationHint != null) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + HintManager.getInstance().showInformationHint(editor, informationHint); + } + }); + } + else { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + HintManager.getInstance().showErrorHint(editor, getErrorHint()); + } + }); + } + } + + @Nullable + protected abstract String getInformationHint(@NotNull T element); + + @NotNull + protected abstract String getErrorHint(); + + @NotNull + protected List getElement(@NotNull Editor editor, @NotNull PsiFile file) { + final SelectionModel selectionModel = editor.getSelectionModel(); + if (selectionModel.hasSelection()) { + return ContainerUtil.list(getElementFromSelection(file, selectionModel)); + } + return getElementAtOffset(editor, file); + } + + @NotNull + protected List getElementAtOffset(@NotNull Editor editor, @NotNull PsiFile file) { + return ContainerUtil.list(PsiTreeUtil.findElementOfClassAtOffset(file, editor.getCaretModel().getOffset(), myClass, false)); + } + + @Nullable + protected T getElementFromSelection(@NotNull PsiFile file, @NotNull SelectionModel selectionModel) { + final int selectionStart = selectionModel.getSelectionStart(); + final int selectionEnd = selectionModel.getSelectionEnd(); + return PsiTreeUtil.findElementOfClassAtRange(file, selectionStart, selectionEnd, myClass); + } + + @Override + public final void update(AnActionEvent e) { + final Presentation presentation = e.getPresentation(); + boolean enabled = ApplicationManagerEx.getApplicationEx().isInternal() && getEditor(e) != null && myFileClass.isInstance(getPsiFile(e)); + presentation.setVisible(enabled); + presentation.setEnabled(enabled); + } + + @Nullable + private static Editor getEditor(@NotNull AnActionEvent e) { + return PlatformDataKeys.EDITOR.getData(e.getDataContext()); + } + + @Nullable + private static PsiFile getPsiFile(@NotNull AnActionEvent e) { + return LangDataKeys.PSI_FILE.getData(e.getDataContext()); + } +} diff --git a/platform/platform-resources/src/META-INF/ExternalSystemExtensions.xml b/platform/platform-resources/src/META-INF/ExternalSystemExtensions.xml index fab5a6a62530..b726ef82b4ed 100644 --- a/platform/platform-resources/src/META-INF/ExternalSystemExtensions.xml +++ b/platform/platform-resources/src/META-INF/ExternalSystemExtensions.xml @@ -12,7 +12,6 @@ serviceImplementation="com.intellij.openapi.externalSystem.service.project.ExternalLibraryPathTypeMapperImpl"/> - diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java index 15c79cbaa3c5..b8dca4df4983 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java @@ -142,7 +142,7 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { boolean unparsable) { InjectorUtils.registerInjection(language, list, containingFile, registrar); InjectorUtils.registerSupport(mySupport, settingsAvailable, registrar); - if (unparsable) InjectorUtils.putInjectedFileUserData(registrar, InjectedLanguageUtil.FRANKENSTEIN_INJECTION, Boolean.TRUE); + InjectorUtils.putInjectedFileUserData(registrar, InjectedLanguageUtil.FRANKENSTEIN_INJECTION, unparsable ? Boolean.TRUE : null); } @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/noncode/MixinMemberContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/noncode/MixinMemberContributor.java index 3cce1d595535..6521f659cb9e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/noncode/MixinMemberContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/noncode/MixinMemberContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.resolve.noncode; import com.intellij.codeInsight.completion.originInfo.OriginInfoAwareElement; import com.intellij.psi.*; +import com.intellij.psi.impl.compiled.ClsClassImpl; import com.intellij.psi.impl.light.LightMethod; import com.intellij.psi.scope.DelegatingScopeProcessor; import com.intellij.psi.scope.PsiScopeProcessor; @@ -28,6 +29,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation. import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationMemberValue; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrGdkMethodImpl; import org.jetbrains.plugins.groovy.lang.psi.util.GdkMethodUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; @@ -47,8 +49,8 @@ public class MixinMemberContributor extends NonCodeMembersContributor { @NotNull ResolveState state) { if (!(qualifierType instanceof PsiClassType)) return; if (isInAnnotation(place)) return; - final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)qualifierType).resolveGenerics(); - final PsiClass aClass = resolveResult.getElement(); + + final PsiClass aClass = getClass((PsiClassType)qualifierType); if (aClass == null) return; final PsiModifierList modifierList = aClass.getModifierList(); @@ -77,6 +79,21 @@ public class MixinMemberContributor extends NonCodeMembersContributor { } } + @Nullable + private static PsiClass getClass(@NotNull PsiClassType qualifierType) { + final PsiClassType.ClassResolveResult resolveResult = qualifierType.resolveGenerics(); + + final PsiClass aClass = resolveResult.getElement(); + if (aClass instanceof ClsClassImpl) { + final PsiElement source = aClass.getNavigationElement(); + if (source instanceof GrTypeDefinition) { + return (PsiClass)source; + } + } + + return aClass; + } + public static String getOriginInfoForCategory(PsiMethod element) { PsiClass aClass = element.getContainingClass(); if (aClass != null && aClass.getName() != null) { @@ -91,7 +108,7 @@ public class MixinMemberContributor extends NonCodeMembersContributor { private static List getAllMixins(PsiModifierList modifierList) { final ArrayList result = new ArrayList(); - for (PsiAnnotation annotation : modifierList.getApplicableAnnotations()) { + for (PsiAnnotation annotation : modifierList.getAnnotations()) { if (GroovyCommonClassNames.GROOVY_LANG_MIXIN.equals(annotation.getQualifiedName())) { result.add(annotation); }