Qualified this/super references are allowed only in inner/nested/anonymous classes

This commit is contained in:
Max Medvedev
2012-10-23 18:09:57 +04:00
parent cc60e660b6
commit 48aba342ad
7 changed files with 88 additions and 107 deletions
@@ -334,4 +334,6 @@ top.level.class.maynot.have.protected.modifier=Top level class may not have 'pro
property.missing=propertyMissing
attribute.name.expected=Attribute name expected
java.style.for.each.statement.requires.a.type.declaration=Java-style for-each statement requires a type declaration
enums.may.not.have.extends.clause=Enums may not have 'extends' clause
enums.may.not.have.extends.clause=Enums may not have 'extends' clause
super.cannot.be.used.in.static.context='super' cannot be used in static context
qualified.0.is.allowed.only.in.nested.or.inner.classes=Qualified {0} is allowed only in nested/inner classes
@@ -1032,6 +1032,13 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
@Override
public void visitSuperExpression(GrSuperReferenceExpression superExpression) {
final GrReferenceExpression qualifier = superExpression.getQualifier();
if (qualifier == null) {
final GrMember container = PsiTreeUtil.getParentOfType(superExpression, GrMethod.class, GrClassInitializer.class);
if (container != null && container.hasModifierProperty(STATIC)) {
myHolder.createErrorAnnotation(superExpression, GroovyBundle.message("super.cannot.be.used.in.static.context"));
}
}
checkThisOrSuperReferenceExpression(superExpression, myHolder);
}
@@ -1409,23 +1416,15 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
return PsiTreeUtil.getParentOfType(statement, GrLoopStatement.class, true, GrClosableBlock.class, GrMember.class, GroovyFile.class);
}
private static void checkThisOrSuperReferenceExpression(GrExpression expression, AnnotationHolder holder) {
if (GroovyConfigUtils.getInstance().isVersionAtLeast(expression, GroovyConfigUtils.GROOVY1_8)) return;
final GrReferenceExpression qualifier = expression instanceof GrThisReferenceExpression
? ((GrThisReferenceExpression)expression).getQualifier()
: ((GrSuperReferenceExpression)expression).getQualifier();
if (qualifier == null) {
if (expression instanceof GrSuperReferenceExpression) { //'this' refers to java.lang.Class<ThisClass> in static context
final GrMethod method = PsiTreeUtil.getParentOfType(expression, GrMethod.class);
if (method != null && method.hasModifierProperty(STATIC)) {
Annotation annotation =
holder.createInfoAnnotation(expression, GroovyBundle.message("cannot.reference.nonstatic", expression.getText()));
annotation.setTextAttributes(DefaultHighlighter.UNRESOLVED_ACCESS);
}
private static void checkThisOrSuperReferenceExpression(GrThisSuperReferenceExpression expression, AnnotationHolder holder) {
final GrReferenceExpression qualifier = expression.getQualifier();
if (qualifier != null) {
GrTypeDefinition containingClass = PsiTreeUtil.getParentOfType(expression, GrTypeDefinition.class, true, GroovyFile.class);
if (containingClass == null || containingClass.getContainingClass() == null && !containingClass.isAnonymous()) {
holder.createErrorAnnotation(expression, GroovyBundle.message("qualified.0.is.allowed.only.in.nested.or.inner.classes", expression.getReferenceName()));
return;
}
}
else {
final PsiElement resolved = qualifier.resolve();
if (resolved instanceof PsiClass) {
if (PsiTreeUtil.isAncestor(resolved, expression, true)) {
@@ -1442,7 +1441,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
}
}
else {
holder.createErrorAnnotation(qualifier, GroovyBundle.message("unknown.class", qualifier.getText()));
holder.createErrorAnnotation(qualifier, GroovyBundle.message("cannot.resolve", qualifier.getText()));
}
}
}
@@ -1,75 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection;
import org.jetbrains.plugins.groovy.util.TestUtils;
/**
* @author peter
*/
@SuppressWarnings({"JUnitTestClassNamingConvention"})
public class Groovy16HighlightingTest extends LightCodeInsightFixtureTestCase {
private static final DefaultLightProjectDescriptor DESCRIPTOR_1_6 = new DefaultLightProjectDescriptor() {
@Override
public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
final Library.ModifiableModel modifiableModel = model.getModuleLibraryTable().createLibrary("GROOVY").getModifiableModel();
final VirtualFile groovyJar =
JarFileSystem.getInstance().refreshAndFindFileByPath(TestUtils.getMockGroovy1_6LibraryName() + "!/");
modifiableModel.addRoot(groovyJar, OrderRootType.CLASSES);
modifiableModel.commit();
}
};
@Override
protected String getBasePath() {
return TestUtils.getTestDataPath() + "highlighting/";
}
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return DESCRIPTOR_1_6;
}
private void doTest(LocalInspectionTool... tools) {
myFixture.enableInspections(tools);
myFixture.testHighlighting(true, false, false, getTestName(false) + ".groovy");
}
public void testInnerEnum() throws Exception {doTest();}
public void testSuperWithNotEnclosingClass() throws Throwable {doTest();}
public void testThisWithWrongQualifier() throws Throwable {doTest();}
public void testImplicitEnumCoercion1_6() {
doTest(new GroovyAssignabilityCheckInspection());
}
public void testSlashyStrings() {doTest();}
public void testDiamonds() {doTest();}
}
@@ -0,0 +1,65 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang.highlighting
import com.intellij.codeInspection.LocalInspectionTool
import com.intellij.openapi.module.Module
import com.intellij.openapi.roots.ContentEntry
import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.vfs.JarFileSystem
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.LightProjectDescriptor
import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import org.jetbrains.annotations.NotNull
import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection
import org.jetbrains.plugins.groovy.util.TestUtils
/**
* @author peter
*/
@SuppressWarnings(["JUnitTestClassNamingConvention"])
public class Groovy16HighlightingTest extends LightCodeInsightFixtureTestCase {
@NotNull
final LightProjectDescriptor projectDescriptor = new DefaultLightProjectDescriptor() {
@Override
public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
final Library.ModifiableModel modifiableModel = model.moduleLibraryTable.createLibrary("GROOVY").modifiableModel
final VirtualFile groovyJar = JarFileSystem.instance.refreshAndFindFileByPath("$TestUtils.mockGroovy1_6LibraryName!/")
modifiableModel.addRoot(groovyJar, OrderRootType.CLASSES)
modifiableModel.commit()
}
}
final String basePath = TestUtils.testDataPath + "highlighting/"
private void doTest(LocalInspectionTool... tools) {
myFixture.enableInspections(tools)
myFixture.testHighlighting(true, false, false, getTestName(false) + ".groovy")
}
public void testInnerEnum() { doTest() }
public void testSuperWithNotEnclosingClass() { doTest() }
public void testThisWithWrongQualifier() { doTest() }
public void testImplicitEnumCoercion1_6() { doTest(new GroovyAssignabilityCheckInspection()) }
public void testSlashyStrings() { doTest() }
public void testDiamonds() { doTest() }
}
@@ -14,6 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang.highlighting
import com.intellij.testFramework.IdeaTestUtil
import com.siyeh.ig.junit.JUnitAbstractTestClassNamingConventionInspection
import com.siyeh.ig.junit.JUnitTestClassNamingConventionInspection
@@ -21,18 +22,7 @@ import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilit
import org.jetbrains.plugins.groovy.codeInspection.confusing.GrUnusedIncDecInspection
import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection
import org.jetbrains.plugins.groovy.codeInspection.unusedDef.UnusedDefInspection
//import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection
//import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyResultOfAssignmentUsedInspection
//import org.jetbrains.plugins.groovy.codeInspection.bugs.*
//import org.jetbrains.plugins.groovy.codeInspection.confusing.*
//import org.jetbrains.plugins.groovy.codeInspection.control.GroovyTrivialConditionalInspection
//import org.jetbrains.plugins.groovy.codeInspection.control.GroovyTrivialIfInspection
//import org.jetbrains.plugins.groovy.codeInspection.control.GroovyUnnecessaryReturnInspection
//import org.jetbrains.plugins.groovy.codeInspection.metrics.GroovyOverlyLongMethodInspection
//import org.jetbrains.plugins.groovy.codeInspection.noReturnMethod.MissingReturnInspection
//import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection
//import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GroovyUntypedAccessInspection
//import org.jetbrains.plugins.groovy.codeInspection.unusedDef.UnusedDefInspection
/**
* @author peter
*/
@@ -1,5 +1,5 @@
class X{
def foo() {
<error descr="'java.lang.String' is not an enclosing class">String.super</error>.toString()
<error descr="Qualified super is allowed only in nested/inner classes">String.super</error>.toString()
}
}
@@ -1,6 +1,6 @@
class X{
def foo(){
X x=new X();
<error descr="unknown class 'x'">x</error>.this.foo();
<error descr="Qualified this is allowed only in nested/inner classes">x.this</error>.foo();
}
}