| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.jetbrains.plugins.groovy.lang.highlighting |
| |
| import com.intellij.testFramework.IdeaTestUtil |
| import com.siyeh.ig.junit.JUnitAbstractTestClassNamingConventionInspection |
| import com.siyeh.ig.junit.JUnitTestClassNamingConventionInspection |
| import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection |
| import org.jetbrains.plugins.groovy.codeInspection.confusing.GrUnusedIncDecInspection |
| import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection |
| import org.jetbrains.plugins.groovy.codeInspection.unusedDef.UnusedDefInspection |
| /** |
| * @author peter |
| */ |
| public class GroovyHighlightingTest extends GrHighlightingTestBase { |
| |
| public void testDuplicateClosurePrivateVariable() { |
| doTest(); |
| } |
| |
| public void testClosureRedefiningVariable() { |
| doTest(); |
| } |
| |
| public void testCircularInheritance() { |
| doTest(); |
| } |
| |
| public void testEmptyTupleType() { |
| doTest(); |
| } |
| |
| public void testMapDeclaration() { |
| doTest(); |
| } |
| |
| public void testShouldNotImplementGroovyObjectMethods() { |
| addGroovyObject(); |
| myFixture.addFileToProject("Foo.groovy", "class Foo {}"); |
| myFixture.testHighlighting(false, false, false, getTestName(false) + ".java"); |
| } |
| |
| public void testJavaClassImplementingGroovyInterface() { |
| addGroovyObject(); |
| myFixture.addFileToProject("Foo.groovy", "interface Foo {}"); |
| myFixture.testHighlighting(false, false, false, getTestName(false) + ".java"); |
| } |
| |
| public void testDuplicateFields() { |
| doTest(); |
| } |
| |
| public void testNoDuplicationThroughClosureBorder() { |
| myFixture.addClass("package groovy.lang; public interface Closure {}"); |
| doTest(); |
| } |
| |
| public void testRecursiveMethodTypeInference() { |
| doTest(); |
| } |
| |
| public void testSuperClassNotExists() { |
| doRefTest() |
| } |
| |
| public void testAnonymousClassConstructor() { doTest(); } |
| |
| public void testAnonymousClassAbstractMethod() { doTest(); } |
| |
| //public void _testAnonymousClassStaticMethod() { doTest(); } |
| |
| public void testAnonymousClassShouldImplementMethods() { doTest(); } |
| |
| public void testAnonymousClassShouldImplementSubstitutedMethod() { doTest(); } |
| |
| public void testUnresolvedLhsAssignment() { doRefTest() } |
| |
| public void testUnresolvedAccess() { doRefTest() } |
| |
| public void testBooleanProperties() { doRefTest() } |
| |
| public void testDuplicateInnerClass() { doTest(); } |
| |
| public void testThisInStaticContext() { doTest(); } |
| |
| public void testLocalVariableInStaticContext() { doTest(); } |
| |
| public void testModifiersInPackageAndImportStatements() { |
| myFixture.copyFileToProject(getTestName(false) + ".groovy", "x/" + getTestName(false) + ".groovy"); |
| myFixture.testHighlighting(true, false, false, "x/" + getTestName(false) + ".groovy"); |
| } |
| |
| public void testBreakOutside() { doTest(); } |
| |
| public void testUndefinedLabel() { doTest(); } |
| |
| public void testNestedMethods() { |
| doTest(); |
| } |
| |
| public void testRawOverriddenMethod() { doTest(); } |
| |
| public void testFQNJavaClassesUsages() { |
| doTest(); |
| } |
| |
| public void testGstringAssignableToString() { doTest(); } |
| |
| public void testGstringAssignableToStringInClosureParameter() { doTest(); } |
| |
| public void testEachOverRange() { doTest(); } |
| |
| public void testEllipsisParam() { |
| myFixture.configureByText('a.groovy', '''\ |
| class A { |
| def foo(int... x){} |
| def foo(int<error descr="Ellipsis type is not allowed here">...</error> x, double y) {} |
| } |
| ''') |
| myFixture.checkHighlighting(true, false, false) |
| } |
| |
| public void testStringAndGStringUpperBound() { doTest(); } |
| |
| public void testWithMethod() { doTest(); } |
| |
| public void testArrayLikeAccess() { doTest(); } |
| |
| public void testSetInitializing() { doTest(); } |
| |
| public void testEmptyTupleAssignability() { doTest(); } |
| |
| public void testGrDefFieldsArePrivateInJavaCode() { |
| myFixture.configureByText("X.groovy", "public class X{def x=5}"); |
| myFixture.testHighlighting(true, false, false, getTestName(false) + ".java"); |
| } |
| |
| public void testSuperConstructorInvocation() { doTest(); } |
| |
| public void testDuplicateMapKeys() { doTest(); } |
| |
| public void testIndexPropertyAccess() { doTest(); } |
| |
| public void testPropertyAndFieldDeclaration() { doTest(); } |
| |
| public void testGenericsMethodUsage() { doTest(); } |
| |
| public void testWildcardInExtendsList() { doTest(); } |
| |
| public void testOverrideAnnotation() { doTest(); } |
| |
| public void testClosureCallWithTupleTypeArgument() { doTest(); } |
| |
| public void testMethodDuplicates() { doTest(); } |
| |
| public void testAmbiguousCodeBlock() { doTest(); } |
| |
| public void testAmbiguousCodeBlockInMethodCall() { doTest(); } |
| |
| public void testNotAmbiguousClosableBlock() { doTest(); } |
| |
| public void testDuplicateParameterInClosableBlock() { doTest(); } |
| |
| public void testCyclicInheritance() { doTest(); } |
| |
| public void testNoDefaultConstructor() { doTest(); } |
| |
| public void testNumberDuplicatesInMaps() { doTest(); } |
| |
| public void testBuiltInTypeInstantiation() { doTest(); } |
| |
| public void testSOEInFieldDeclarations() { doTest(); } |
| |
| public void testVeryLongDfaWithComplexGenerics() { |
| IdeaTestUtil.assertTiming("", 10000, 1, new Runnable() { |
| @Override |
| public void run() { |
| doTest(new GroovyAssignabilityCheckInspection(), new UnusedDefInspection(), new GrUnusedIncDecInspection()); |
| } |
| }); |
| } |
| |
| public void testWrongAnnotation() { doTest(); } |
| |
| public void testAmbiguousMethods() { |
| myFixture.copyFileToProject(getTestName(false) + ".java"); |
| doTest(); |
| } |
| |
| public void testGroovyEnumInJavaFile() { |
| myFixture.copyFileToProject(getTestName(false) + ".groovy"); |
| myFixture.testHighlighting(true, false, false, getTestName(false) + ".java"); |
| } |
| |
| public void testSOFInDelegate() { |
| doTest(); |
| } |
| |
| public void testMethodImplementedByDelegate() { |
| doTest(); |
| } |
| |
| //public void _testTestMarkupStubs() { |
| // doRefTest() |
| //} |
| |
| public void testGdslWildcardTypes() { |
| myFixture.configureByText("a.groovy", |
| "List<? extends String> la = []; la.get(1); " + |
| "List<? super String> lb = []; lb.get(1); " + |
| "List<?> lc = []; lc.get(1); " |
| ); |
| myFixture.checkHighlighting(true, false, false); |
| } |
| |
| public void testDuplicatedNamedArgs() { doTest(); } |
| |
| public void testConstructorWithAllParametersOptional() { |
| doTest(); |
| } |
| |
| public void testTupleConstructorAttributes() { |
| doTest(new GroovyAssignabilityCheckInspection()); |
| } |
| |
| public void testDelegatedMethodIsImplemented() { |
| doTest(); |
| } |
| |
| public void testEnumImplementsAllGroovyObjectMethods() { |
| doTest(); |
| } |
| |
| //public void _testBuilderMembersAreNotUnresolved() { |
| // doRefTest(); |
| //} |
| |
| public void testRecursiveConstructors() { |
| doTest(); |
| } |
| |
| public void testImmutableConstructorFromJava() { |
| myFixture.addFileToProject "a.groovy", '''@groovy.transform.Immutable class Foo { int a; String b }''' |
| myFixture.configureByText 'a.java', ''' |
| class Bar {{ |
| new Foo<error>()</error>; |
| new Foo<error>(2)</error>; |
| new Foo(2, "3"); |
| }}''' |
| myFixture.checkHighlighting(false, false, false) |
| } |
| |
| public void testTupleConstructorFromJava() { |
| myFixture.addFileToProject "a.groovy", '''@groovy.transform.TupleConstructor class Foo { int a; String b }''' |
| myFixture.configureByText 'a.java', ''' |
| class Bar {{ |
| new Foo(); |
| new Foo(2); |
| new Foo(2, "3"); |
| new Foo<error>(2, "3", 9)</error>; |
| }}''' |
| myFixture.checkHighlighting(false, false, false) |
| } |
| |
| public void testInheritConstructorsFromJava() { |
| myFixture.addFileToProject "a.groovy", ''' |
| class Person { |
| Person(String first, String last) { } |
| Person(String first, String last, String address) { } |
| Person(String first, String last, int zip) { } |
| } |
| |
| @groovy.transform.InheritConstructors |
| class PersonAge extends Person { |
| PersonAge(String first, String last, int zip) { } |
| } |
| ''' |
| myFixture.configureByText 'a.java', ''' |
| class Bar {{ |
| new PersonAge("a", "b"); |
| new PersonAge("a", "b", "c"); |
| new PersonAge("a", "b", 239); |
| new PersonAge<error>(2, "3", 9)</error>; |
| }}''' |
| myFixture.checkHighlighting(false, false, false) |
| } |
| |
| void testDefaultInitializersAreNotAllowedInAbstractMethods() { doTest() } |
| |
| void testConstructorTypeArgs() { doTest() } |
| |
| void testIncorrectEscaping() { doTest() } |
| |
| void testExtendingOwnInner() { doTest() } |
| |
| void testRegexInCommandArg() { doTest() } |
| |
| public void testJUnitConvention() { |
| myFixture.addClass("package junit.framework; public class TestCase {}") |
| doTest(new JUnitTestClassNamingConventionInspection(), new JUnitAbstractTestClassNamingConventionInspection()) |
| } |
| |
| void testDuplicateMethods() { |
| myFixture.configureByText('a.groovy', '''\ |
| class A { |
| <error descr="Method with signature foo() is already defined in the class 'A'">def foo()</error>{} |
| <error descr="Method with signature foo() is already defined in the class 'A'">def foo(def a=null)</error>{} |
| } |
| ''') |
| myFixture.checkHighlighting(true, false, false) |
| } |
| |
| void testPrivateTopLevelClassInJava() { |
| myFixture.addFileToProject('pack/Foo.groovy', 'package pack; private class Foo{}') |
| myFixture.configureByText('Abc.java', '''\ |
| import pack.Foo; |
| |
| class Abc { |
| void foo() { |
| System.out.print(new Foo()); // top-level Groovy class can't be private |
| } |
| } |
| ''') |
| |
| myFixture.testHighlighting(false, false, false) |
| } |
| |
| void testDelegateToMethodWithItsOwnTypeParams() { |
| myFixture.configureByText('a.groovy', '''\ |
| interface I<S> { |
| def <T> void foo(List<T> a); |
| } |
| |
| class Foo { |
| @Delegate private I list |
| } |
| |
| <error descr="Method 'foo' is not implemented">class Bar implements I</error> { |
| def <T> void foo(List<T> a){} |
| } |
| |
| class Baz implements I { |
| def void foo(List a){} |
| } |
| ''') |
| |
| myFixture.testHighlighting(false, false, false) |
| } |
| |
| void testPrimitiveTypeParams() { |
| myFixture.configureByText('a.groovy', '''\ |
| List<<error descr="Primitive type parameters are not allowed in type parameter list">int</error>> list = new ArrayList<int><EOLError descr="'(' expected"></EOLError> |
| List<? extends <error descr="Primitive bound types are not allowed">double</error>> l = new ArrayList<double>() |
| List<?> list2 |
| ''') |
| myFixture.testHighlighting(true, false, false) |
| } |
| |
| public void testAliasInParameterType() { |
| myFixture.configureByText('a_.groovy', '''\ |
| import java.awt.event.ActionListener |
| import java.awt.event.ActionEvent as AE |
| |
| public class CorrectImplementor implements ActionListener { |
| public void actionPerformed (AE e) { //AE is alias to ActionEvent |
| } |
| } |
| |
| <error descr="Method 'actionPerformed' is not implemented">public class IncorrectImplementor implements ActionListener</error> { |
| public void actionPerformed (Object e) { |
| } |
| } |
| ''') |
| myFixture.testHighlighting(true, false, false) |
| } |
| |
| public void testReassignedHighlighting() { |
| myFixture.testHighlighting(true, true, true, getTestName(false) + ".groovy"); |
| } |
| |
| public void testInstanceOf() { |
| myFixture.configureByText('_a.groovy', '''\ |
| class DslPointcut {} |
| |
| private def handleImplicitBind(arg) { |
| if (arg instanceof Map && arg.size() == 1 && arg.keySet().iterator().next() instanceof String && arg.values().iterator().next() instanceof DslPointcut) { |
| return DslPointcut.bind(arg) |
| } |
| return arg |
| }''') |
| myFixture.testHighlighting(true, false, false) |
| } |
| |
| public void testIncorrectTypeArguments() { |
| myFixture.configureByText('_.groovy', '''\ |
| class C <T extends String> {} |
| C<<warning descr="Type parameter 'java.lang.Double' is not in its bound; should extend 'java.lang.String'">Double</warning>> c |
| C<String> c2 |
| C<warning descr="Wrong number of type arguments: 2; required: 1"><String, Double></warning> c3 |
| ''') |
| myFixture.testHighlighting(true, false, true) |
| } |
| |
| void testTryCatch1() { |
| testHighlighting('''\ |
| try {} |
| catch (Exception e){} |
| catch (<warning descr="Exception 'java.io.IOException' has already been caught">IOException</warning> e){} |
| ''') |
| } |
| |
| void testTryCatch2() { |
| testHighlighting('''\ |
| try {} |
| catch (e){} |
| catch (<warning descr="Exception 'java.lang.Exception' has already been caught">e</warning>){} |
| ''') |
| } |
| |
| void testTryCatch3() { |
| testHighlighting('''\ |
| try {} |
| catch (e){} |
| catch (<warning descr="Exception 'java.io.IOException' has already been caught">IOException</warning> e){} |
| ''') |
| } |
| |
| void testTryCatch4() { |
| testHighlighting('''\ |
| try {} |
| catch (Exception | <warning descr="Unnecessary exception 'java.io.IOException'. 'java.lang.Exception' is already declared">IOException</warning> e){} |
| ''') |
| } |
| |
| void testTryCatch5() { |
| testHighlighting('''\ |
| try {} |
| catch (RuntimeException | IOException e){} |
| catch (<warning descr="Exception 'java.lang.NullPointerException' has already been caught">NullPointerException</warning> e){} |
| ''') |
| } |
| |
| void testTryCatch6() { |
| testHighlighting('''\ |
| try {} |
| catch (NullPointerException | IOException e){} |
| catch (ClassNotFoundException | <warning descr="Exception 'java.lang.NullPointerException' has already been caught">NullPointerException</warning> e){} |
| ''') |
| } |
| |
| void testCompileStatic() { |
| myFixture.addClass('''\ |
| package groovy.transform; |
| public @interface CompileStatic { |
| }''') |
| |
| testHighlighting('''\ |
| import groovy.transform.CompileStatic |
| |
| class A { |
| |
| def foo() { |
| print <warning descr="Cannot resolve symbol 'abc'">abc</warning> |
| } |
| |
| @CompileStatic |
| def bar() { |
| print <error descr="Cannot resolve symbol 'abc'">abc</error> |
| } |
| } |
| ''', true, false, false, GrUnresolvedAccessInspection) |
| } |
| |
| void testUnresolvedVarInStaticMethod() { |
| testHighlighting('''\ |
| static def foo() { |
| print <error descr="Cannot resolve symbol 'abc'">abc</error> |
| |
| def cl = { |
| print <warning descr="Cannot resolve symbol 'cde'">cde</warning> |
| } |
| } |
| ''', GrUnresolvedAccessInspection) |
| } |
| |
| void testStaticOkForClassMembersWithThisQualifier() { |
| testHighlighting('''\ |
| class A { |
| def foo(){} |
| static bar() { |
| this.toString() |
| this.getFields() |
| this.<warning descr="Cannot reference non-static symbol 'foo' from static context">foo</warning>() |
| } |
| } |
| ''', GrUnresolvedAccessInspection) |
| } |
| |
| void testScriptFieldsAreAllowedOnlyInScriptBody() { |
| addGroovyTransformField() |
| testHighlighting('''\ |
| import groovy.transform.Field |
| |
| @Field |
| def foo |
| |
| def foo() { |
| <error descr="Annotation @Field can only be used within a script body">@Field</error> |
| def bar |
| } |
| |
| class X { |
| <error descr="Annotation @Field can only be used within a script">@Field</error> |
| def bar |
| |
| def b() { |
| <error descr="Annotation @Field can only be used within a script">@Field</error> |
| def x |
| } |
| } |
| ''') |
| } |
| |
| void testDuplicatedScriptField() { |
| addGroovyTransformField() |
| testHighlighting('''\ |
| import groovy.transform.Field |
| |
| while(true) { |
| @Field def <error descr="Field 'foo' already defined">foo</error> |
| } |
| |
| while(false) { |
| @Field def <error descr="Field 'foo' already defined">foo</error> |
| } |
| |
| while(i) { |
| def foo |
| } |
| |
| def foo |
| ''') |
| } |
| |
| void testReturnTypeInStaticallyCompiledMethod() { |
| addCompileStatic(); |
| testHighlighting('''\ |
| import groovy.transform.CompileStatic |
| @CompileStatic |
| int method(x, y, z) { |
| if (x) { |
| <error descr="Cannot assign 'String' to 'int'">'String'</error> |
| } else if (y) { |
| 42 |
| } |
| else if (z) { |
| <error descr="Cannot assign 'String' to 'int'">return</error> 'abc' |
| } |
| else { |
| return 43 |
| } |
| } |
| ''') |
| } |
| |
| void testReassignedVarInClosure1() { |
| addCompileStatic() |
| testHighlighting(""" |
| $IMPORT_COMPILE_STATIC |
| |
| @CompileStatic |
| def test() { |
| def var = "abc" |
| def cl = { |
| var = new Date() |
| } |
| cl() |
| var.<error descr="Cannot resolve symbol 'toUpperCase'">toUpperCase</error>() |
| } |
| """, GrUnresolvedAccessInspection) |
| } |
| |
| void testReassignedVarInClosure2() { |
| addCompileStatic() |
| testHighlighting(""" |
| $IMPORT_COMPILE_STATIC |
| |
| @CompileStatic |
| def test() { |
| def cl = { |
| def var |
| var = new Date() |
| } |
| def var = "abc" |
| |
| cl() |
| var.toUpperCase() //no errors |
| } |
| """, GrUnresolvedAccessInspection) |
| } |
| |
| void testReassignedVarInClosure3() { |
| addCompileStatic() |
| testHighlighting(""" |
| $IMPORT_COMPILE_STATIC |
| |
| @CompileStatic |
| def test() { |
| def var = "abc" |
| def cl = new Closure(this, this){ |
| def call() { |
| var = new Date() |
| } |
| } |
| cl() |
| var.toUpperCase() //no errors |
| } |
| """, GrUnresolvedAccessInspection) |
| } |
| |
| void testReassignedVarInClosure4() { |
| addCompileStatic() |
| testHighlighting(""" |
| $IMPORT_COMPILE_STATIC |
| |
| class X { |
| def var |
| } |
| |
| @CompileStatic |
| def test() { |
| def var = "abc" |
| new X().with { |
| var = new Date() |
| } |
| |
| var.<error descr="Cannot resolve symbol 'toUpperCase'">toUpperCase</error>() |
| } |
| """, GrUnresolvedAccessInspection) |
| } |
| |
| void testOverrideForVars() { |
| testHighlighting('''\ |
| class S { |
| @<error descr="'@Override' not applicable to field">Override</error> def foo; |
| |
| def bar() { |
| @<error descr="'@Override' not applicable to local variable">Override</error> def x |
| } |
| }''') |
| } |
| |
| void testUnusedImportToList() { |
| myFixture.addClass('''package java.awt; public class Component{}''') |
| testHighlighting('''\ |
| import java.awt.Component |
| <warning descr="Unused import">import java.util.List</warning> |
| |
| print Component |
| print List |
| ''') |
| } |
| |
| void testUsedImportToList() { |
| myFixture.addClass('''package java.awt; public class Component{}''') |
| myFixture.addClass('''package java.awt; public class List{}''') |
| myFixture.addClass('''package java.util.concurrent; public class ConcurrentHashMap{}''') |
| testHighlighting('''\ |
| import java.awt.* |
| import java.util.List |
| <warning descr="Unused import">import java.util.concurrent.ConcurrentHashMap</warning> |
| |
| print Component |
| print List |
| ''') |
| } |
| |
| void testIncompatibleTypeOfImplicitGetter() { |
| testHighlighting('''\ |
| abstract class Base { |
| abstract String getFoo() |
| } |
| |
| class Inheritor extends Base { |
| final <error descr="The return type of java.lang.Object getFoo() in Inheritor is incompatible with java.lang.String getFoo() in Base">foo</error> = '3' |
| }''') |
| } |
| |
| void testIncompatibleTypeOfInheritedMethod() { |
| testHighlighting('''\ |
| abstract class Base { |
| abstract String getFoo() |
| } |
| |
| class Inheritor extends Base { |
| def <error descr="The return type of java.lang.Object getFoo() in Inheritor is incompatible with java.lang.String getFoo() in Base">getFoo</error>() {''} |
| }''') |
| } |
| |
| void testIncompatibleTypeOfInheritedMethod2() { |
| testHighlighting('''\ |
| abstract class Base { |
| abstract String getFoo() |
| } |
| |
| class Inheritor extends Base { |
| <error descr="The return type of java.lang.Object getFoo() in Inheritor is incompatible with java.lang.String getFoo() in Base">Object</error> getFoo() {''} |
| }''') |
| } |
| |
| void testIncompatibleTypeOfInheritedMethodInAnonymous() { |
| testHighlighting('''\ |
| abstract class Base { |
| abstract String getFoo() |
| } |
| |
| new Base() { |
| <error descr="The return type of java.lang.Object getFoo() in anonymous class derived from Base is incompatible with java.lang.String getFoo() in Base">Object</error> getFoo() {''} |
| }''') |
| } |
| |
| void testAnnotationArgs() { |
| testHighlighting('''\ |
| @interface Int { |
| int value() |
| String s() default 'a' |
| } |
| |
| @Int(<error descr="Cannot assign 'String' to 'int'">'a'</error>) def foo(){} |
| |
| @Int(2) def bar(){} |
| |
| @Int(value = 2) def c(){} |
| |
| @Int(value = 3, s = <error descr="Cannot assign 'Integer' to 'String'">4</error>) def x(){} |
| |
| @Int(value = 3, s = '4') def y(){} |
| ''') |
| } |
| |
| void testDefaultAttributeValue() { |
| testHighlighting('''\ |
| @interface Int { |
| int value1() default 2 |
| String value2() default <error descr="Cannot assign 'Integer' to 'String'">2</error> |
| String value3() |
| } |
| ''') |
| } |
| |
| void testAnnotationAttributeTypes() { |
| testHighlighting('''\ |
| @interface Int { |
| int a() |
| String b() |
| <error descr="Unexpected attribute type: 'PsiType:Date'">Date</error> c() |
| Int d() |
| int[] e() |
| String[] f() |
| boolean[][] g() |
| <error descr="Unexpected attribute type: 'PsiType:Boolean'">Boolean</error>[] h() |
| Int[][][][] i() |
| } |
| ''') |
| } |
| |
| void testDefaultAnnotationValue() { |
| testHighlighting('''\ |
| @interface A { |
| int a() default 2 |
| String b() default <error descr="Cannot assign 'ArrayList<String>' to 'String'">['a']</error> |
| String[][] c() default <error descr="Cannot assign 'String' to 'String[][]'">'f'</error> |
| String[][] d() default [['f']] |
| String[][] e() default [[<error descr="Cannot assign 'ArrayList<String>' to 'String'">['f']</error>]] |
| } |
| ''') |
| } |
| |
| void testAbstractMethodWithBody() { |
| testHighlighting('''\ |
| interface A { |
| def foo()<error descr="Abstract methods must not have body">{}</error> |
| } |
| |
| abstract class B { |
| abstract foo()<error descr="Abstract methods must not have body">{}</error> |
| } |
| |
| class X { |
| def foo(){} |
| } |
| ''') |
| } |
| |
| void testTupleVariableDeclarationWithRecursion() { |
| testHighlighting('''def (a, b) = [a, a]''') |
| } |
| |
| public void testSwitchInLoopNoSoe() { |
| testHighlighting(''' |
| def foo(File f) { |
| while (true) { |
| switch (f.name) { |
| case 'foo': f = new File('bar') |
| } |
| if (f) { |
| return |
| } |
| } |
| }''') |
| |
| } |
| |
| void testInstanceMethodUsedInStaticClosure() { |
| testHighlighting('''\ |
| class A { |
| static staticClosure = { |
| foo() |
| } |
| |
| def staticMethod() { |
| foo() |
| } |
| |
| def foo() { } |
| } |
| ''') |
| } |
| |
| void testStaticOk() { |
| testHighlighting('''\ |
| class A { |
| class B {} |
| } |
| |
| A.B foo = new A.<warning descr="Cannot reference non-static symbol 'A.B' from static context">B</warning>() |
| ''', GrUnresolvedAccessInspection) |
| } |
| |
| void testDuplicatedVar0() { |
| testHighlighting('''\ |
| def a = 5 |
| def <error descr="Variable 'a' already defined">a</error> = 7 |
| ''') |
| } |
| |
| void testDuplicatedVarInIf() { |
| testHighlighting('''\ |
| def a = 5 |
| if (cond) |
| def <error descr="Variable 'a' already defined">a</error> = 7 |
| ''') |
| } |
| |
| |
| void testDuplicatedVarInAnonymous() { |
| testHighlighting('''\ |
| def foo() { |
| def a = 5 |
| |
| new Runnable() { |
| void run() { |
| def <error descr="Variable 'a' already defined">a</error> = 7 |
| } |
| } |
| } |
| ''') |
| } |
| |
| void testDuplicatedVarInClosure() { |
| testHighlighting('''\ |
| def foo() { |
| def a = 5 |
| |
| [1, 2, 3].each { |
| def <error descr="Variable 'a' already defined">a</error> = 7 |
| } |
| } |
| ''') |
| } |
| |
| void testDuplicatedVarInClosureParameter() { |
| testHighlighting('''\ |
| def foo() { |
| def a = 5 |
| |
| [1, 2, 3].each {<error descr="Variable 'a' already defined">a</error> -> |
| print a |
| } |
| } |
| ''') |
| } |
| |
| void testDuplicatedVarInAnonymousParameter() { |
| testHighlighting('''\ |
| def a = -1 |
| |
| def foo() { |
| def a = 5 |
| |
| new Object() { |
| void bar(int <error descr="Variable 'a' already defined">a</error>) {} |
| } |
| } |
| ''') |
| } |
| |
| |
| void testNoDuplicateErrors() { |
| testHighlighting('''\ |
| class Foo { |
| def foo |
| |
| def abr(def foo) {} |
| } |
| |
| class Test { |
| def foo |
| |
| def bar() { |
| def foo |
| } |
| } |
| |
| class X { |
| def foo |
| |
| def x = new Runnable() { |
| void run() { |
| def foo |
| } |
| } |
| } |
| ''') |
| } |
| |
| void testPropertySelectionMayBeLValue() { |
| testHighlighting('''\ |
| def methodMissing(String methodName, args) { |
| def closure = { |
| callSomeOtherMethodInstead() |
| } |
| this.metaClass."$methodName" = closure |
| <error descr="Invalid value to assign to">closure()</error> = 2 |
| } |
| ''') |
| } |
| |
| void testEnumExtendsList() { |
| testHighlighting('''\ |
| enum Ee <error descr="Enums may not have 'extends' clause">extends Enum</error> { |
| } |
| ''') |
| } |
| |
| void testVarInTupleDuplicate() { |
| testHighlighting('''\ |
| def (a, b) |
| def (<error descr="Variable 'b' already defined">b</error>, c, <error descr="Variable 'c' already defined">c</error>) |
| ''') |
| } |
| |
| void 'test create method from usage is available in static method'() { |
| myFixture.enableInspections(GrUnresolvedAccessInspection) |
| testHighlighting('''\ |
| class A { |
| static foo() { |
| <warning descr="Cannot resolve symbol 'abc'">a<caret>bc</warning>() |
| } |
| } |
| ''') |
| |
| assertNotNull(myFixture.findSingleIntention("Create Method 'abc'")) |
| } |
| |
| void testTypeParameterIsCorrect() { |
| testHighlighting('''\ |
| class Component{} |
| |
| class Window extends Component{ |
| Window(i) { |
| } |
| } |
| |
| class Super <C extends Component> { |
| |
| } |
| |
| class Sub<W extends Window> extends Super<W> { |
| } |
| ''') |
| } |
| |
| void testAnonymousBodyOnNewLine() { |
| testHighlighting('''\ |
| class Foo{} |
| print new Foo() |
| <error descr="Ambiguous code block">{ |
| String toString() {'abc'} |
| }</error> |
| ''') |
| } |
| |
| void testGenerics() { |
| addHashSet() |
| testHighlighting(''' |
| |
| class NodeInfo{} |
| |
| interface NodeEvent<T> {} |
| |
| interface TrackerEventsListener<N extends NodeInfo, E extends NodeEvent<N>> { |
| void onEvents(Collection<E> events) |
| } |
| |
| class AgentInfo extends NodeInfo {} |
| |
| print new HashSet<TrackerEventsListener<AgentInfo, NodeEvent<AgentInfo>>>() //correct |
| print new HashSet<TrackerEventsListener<AgentInfo, <warning descr="Type parameter 'NodeEvent<java.lang.Object>' is not in its bound; should extend 'NodeEvent<N>'">NodeEvent<Object></warning>>>() //incorrect |
| ''') |
| } |
| |
| void testTypeInConstructor() { |
| testHighlighting('''\ |
| class X { |
| public <error descr="Return type element is not allowed in constructor">void</error> X() {} |
| } |
| ''') |
| } |
| |
| void testFinalMethodOverriding() { |
| testHighlighting('''\ |
| class A { |
| final void foo() {} |
| } |
| |
| class B extends A{ |
| <error descr="Method 'foo()' cannot override method 'foo()' in 'A'; overridden method is final">void foo()</error> {} |
| } |
| ''') |
| } |
| |
| void testWeakerMethodAccess0() { |
| testHighlighting('''\ |
| class A { |
| void foo() {} |
| } |
| |
| class B extends A{ |
| <error descr="Method 'foo()' cannot have weaker access privileges ('protected') than 'foo()' in 'A' ('public')">protected</error> void foo() {} |
| } |
| ''') |
| } |
| |
| void testWeakerMethodAccess1() { |
| testHighlighting('''\ |
| class A { |
| void foo() {} |
| } |
| |
| class B extends A{ |
| <error descr="Method 'foo()' cannot have weaker access privileges ('private') than 'foo()' in 'A' ('public')">private</error> void foo() {} |
| } |
| ''') |
| } |
| |
| void testWeakerMethodAccess2() { |
| testHighlighting('''\ |
| class A { |
| public void foo() {} |
| } |
| |
| class B extends A{ |
| void foo() {} //don't highlight anything |
| } |
| ''') |
| } |
| |
| void testWeakerMethodAccess3() { |
| testHighlighting('''\ |
| class A { |
| protected void foo() {} |
| } |
| |
| class B extends A{ |
| <error descr="Method 'foo()' cannot have weaker access privileges ('private') than 'foo()' in 'A' ('protected')">private</error> void foo() {} |
| } |
| ''') |
| } |
| |
| void testOverriddenProperty() { |
| testHighlighting('''\ |
| class A { |
| final foo = 2 |
| } |
| |
| class B extends A { |
| <error descr="Method 'getFoo()' cannot override method 'getFoo()' in 'A'; overridden method is final">def getFoo()</error>{5} |
| } |
| ''') |
| } |
| |
| void testUnresolvedQualifierHighlighting() { |
| testHighlighting('''\ |
| <error descr="Cannot resolve symbol 'Abc'">Abc</error>.Cde abc |
| ''') |
| } |
| |
| void testVarargParameterWithoutTypeElement() { |
| testHighlighting('''\ |
| def foo(def <error descr="Ellipsis type is not allowed here">...</error> vararg, def last) {} |
| ''') |
| } |
| |
| void testTupleInstanceCreatingInDefaultConstructor() { |
| testHighlighting(''' |
| class Book { |
| String title |
| Author author |
| |
| String toString() { "$title by $author.name" } |
| } |
| |
| class Author { |
| String name |
| } |
| |
| def book = new Book(title: "Other Title", author: [name: "Other Name"]) |
| |
| assert book.toString() == 'Other Title by Other Name' |
| ''') |
| } |
| |
| void testArrayAccessForMapProperty() { |
| |
| testHighlighting('''\ |
| def bar() { |
| return [list:[1, 2, 3]] |
| } |
| |
| def testConfig = bar() |
| print testConfig.list[0] |
| print testConfig.<warning descr="Cannot resolve symbol 'foo'">foo</warning>() |
| ''', true, false, false, GrUnresolvedAccessInspection) |
| } |
| |
| void testGStringInjectionLFs() { |
| testHighlighting('''\ |
| print "<error descr="GString injection must not contain line feeds">${ |
| }</error>" |
| |
| print """${ |
| }""" |
| |
| print "<error descr="GString injection must not contain line feeds">${ """ |
| """}</error>" |
| ''') |
| } |
| |
| void testListOrMapErrors() { |
| testHighlighting('''\ |
| print([1]) |
| print([1:2]) |
| print(<error descr="Collection literal contains named and expression arguments at the same time">[1:2, 4]</error>) |
| ''') |
| } |
| |
| void _testDelegatesToApplicability() { |
| testHighlighting(''' |
| def with(@DelegatesTo.Target Object target, @DelegatesTo Closure arg) { |
| arg.delegate = target |
| arg() |
| } |
| |
| def with2(Object target, @<error descr="Missed attributes: value">DelegatesTo</error> Closure arg) { |
| arg.delegate = target |
| arg() |
| } |
| ''') |
| } |
| |
| void testClosureParameterInferenceDoesNotWorkIfComplieStatic() { |
| addCompileStatic() |
| myFixture.enableInspections(GrUnresolvedAccessInspection) |
| testHighlighting(''' |
| @groovy.transform.CompileStatic |
| def foo() { |
| final collector = [1, 2].find {a -> |
| a.<error descr="Cannot resolve symbol 'intValue'">intValue</error>() |
| } |
| } |
| ''') |
| } |
| |
| void testIllegalLiteralName() { |
| testHighlighting(''' |
| def <error descr="Illegal escape character in string literal">'a\\obc'</error>() { |
| |
| } |
| ''') |
| } |
| |
| void testExceptionParameterAlreadyDeclared() { |
| testHighlighting(''' |
| int missing() { |
| InputStream i = null |
| |
| try { |
| return 1 |
| } |
| catch(Exception <error descr="Variable 'i' already defined">i</error>) { |
| return 2 |
| } |
| } |
| ''') |
| } |
| |
| void testInnerAnnotationType() { |
| testHighlighting(''' |
| class A { |
| @interface <error descr="Annotation type cannot be inner">X</error> {} |
| } |
| ''') |
| } |
| |
| void testDuplicatingAnnotations() { |
| testHighlighting('''\ |
| @interface A { |
| String value() |
| } |
| |
| @A('a') |
| @A('a') |
| class X{} |
| |
| @A('a') |
| @A('ab') |
| class Y{} |
| |
| <error descr="Duplicate modifier 'public'">public public</error> class Z {} |
| ''') |
| } |
| |
| void testAnnotationAttribute() { |
| testHighlighting('''\ |
| @interface A { |
| String value() default 'a' |
| String[] values() default [] |
| } |
| |
| |
| @A('abc') |
| def x |
| |
| @A(<error descr="Expected ''abc' + 'cde'' to be an inline constant">'abc' + 'cde'</error>) |
| def y |
| |
| class C { |
| final static String CONST1 = 'ABC' |
| final static String CONST2 = 'ABC' + 'CDE' |
| final String CONST3 = 'ABC' |
| } |
| |
| @A(C.CONST1) |
| def z |
| |
| @A(<error descr="Expected ''ABC' + 'CDE'' to be an inline constant">C.CONST2</error>) |
| def a |
| |
| @A(C.CONST3) |
| def b |
| |
| @A(values=['a']) |
| def c |
| |
| @A(values=<error descr="Expected ''a'+'b'' to be an inline constant">['a'+'b']</error>) |
| def d |
| |
| @A(values=[C.CONST1]) |
| def e |
| |
| @A(values=<error descr="Expected ''ABC' + 'CDE'' to be an inline constant">[C.CONST1, C.CONST2]</error>) |
| def f |
| |
| @interface X { |
| Class value() |
| } |
| |
| @X(String.class) |
| def g |
| ''') |
| } |
| |
| void testDuplicateMethodsWithGenerics() { |
| testHighlighting('''\ |
| class A<T, E> { |
| <error descr="Method with signature foo(Object) is already defined in the class 'A'">def foo(T t)</error> {} |
| <error descr="Method with signature foo(Object) is already defined in the class 'A'">def foo(E e)</error> {} |
| } |
| |
| class B { |
| <error descr="Method with signature foo(Object) is already defined in the class 'B'">def <T> void foo(T t)</error> {} |
| <error descr="Method with signature foo(Object) is already defined in the class 'B'">def <E> void foo(E e)</error> {} |
| } |
| |
| class C<T, E> { |
| <error descr="Method with signature foo(Object) is already defined in the class 'C'">def foo(T t, T t2 = null)</error> {} |
| <error descr="Method with signature foo(Object) is already defined in the class 'C'">def foo(E e)</error> {} |
| } |
| |
| class D<T, E> { |
| <error descr="Method with signature foo(Object, Object) is already defined in the class 'D'">def foo(T t, E e)</error> {} |
| <error descr="Method with signature foo(Object, Object) is already defined in the class 'D'">def foo(E t, T e)</error> {} |
| def foo(E t) {} |
| }''') |
| } |
| |
| void testOverriddenReturnType0() { |
| myFixture.addClass('class Base{}') |
| myFixture.addClass('class Inh extends Base{}') |
| testHighlighting('''\ |
| class A { |
| List<Base> foo() {} |
| } |
| |
| class B extends A { |
| List<Inh> foo() {} //correct |
| } |
| ''') |
| } |
| |
| void testOverriddenReturnType1() { |
| myFixture.addClass('class Base extends SuperBase {}') |
| myFixture.addClass('class Inh extends Base{}') |
| testHighlighting('''\ |
| class A { |
| List<Base> foo() {} |
| } |
| |
| class B extends A { |
| <error>Collection<Base></error> foo() {} |
| } |
| ''') |
| } |
| |
| void testOverriddenReturnType2() { |
| myFixture.addClass('class Base extends SuperBase {}') |
| myFixture.addClass('class Inh extends Base{}') |
| testHighlighting('''\ |
| class A { |
| List<Base> foo() {} |
| } |
| |
| class B extends A { |
| <error>int</error> foo() {} |
| } |
| ''') |
| } |
| |
| void testOverriddenReturnType3() { |
| myFixture.addClass('class Base extends SuperBase {}') |
| myFixture.addClass('class Inh extends Base{}') |
| testHighlighting('''\ |
| class A { |
| Base[] foo() {} |
| } |
| |
| class B extends A { |
| <error>Inh[]</error> foo() {} |
| } |
| ''') |
| } |
| |
| void testOverriddenReturnType4() { |
| myFixture.addClass('class Base extends SuperBase {}') |
| myFixture.addClass('class Inh extends Base{}') |
| testHighlighting('''\ |
| class A { |
| Base[] foo() {} |
| } |
| |
| class B extends A { |
| Base[] foo() {} |
| } |
| ''') |
| } |
| |
| void testEnumConstantAsAnnotationAttribute() { |
| testHighlighting('''\ |
| enum A {CONST} |
| |
| @interface I { |
| A foo() |
| } |
| |
| @I(foo = A.CONST) //no error |
| def bar |
| ''') |
| } |
| |
| void testUnassignedFieldAsAnnotationAttribute() { |
| testHighlighting('''\ |
| interface A { |
| String CONST |
| } |
| |
| @interface I { |
| String foo() |
| } |
| |
| @I(foo = <error descr="Expected 'A.CONST' to be an inline constant">A.CONST</error>) |
| def bar |
| ''') |
| } |
| |
| void testFinalFieldRewrite() { |
| testHighlighting('''\ |
| class A { |
| final foo = 1 |
| |
| def A() { |
| foo = 2 //no error |
| } |
| |
| def foo() { |
| <error descr="Cannot assign a value to final field 'foo'">foo</error> = 2 |
| } |
| } |
| |
| new A().foo = 2 //no error |
| ''') |
| } |
| |
| void testStaticFinalFieldRewrite() { |
| testHighlighting('''\ |
| class A { |
| static final foo = 1 |
| |
| def A() { |
| <error descr="Cannot assign a value to final field 'foo'">foo</error> = 2 |
| } |
| |
| static { |
| foo = 2 //no error |
| } |
| |
| def foo() { |
| <error descr="Cannot assign a value to final field 'foo'">foo</error> = 2 |
| } |
| |
| static def bar() { |
| <error descr="Cannot assign a value to final field 'foo'">foo</error> = 2 |
| } |
| } |
| |
| A.foo = 3 //no error |
| ''') |
| } |
| |
| void testSOEIfExtendsItself() { |
| testHighlighting('''\ |
| <error descr="Cyclic inheritance involving 'A'"><error descr="Method 'invokeMethod' is not implemented">class A extends A</error></error> { |
| def foo |
| } |
| |
| <error descr="Cyclic inheritance involving 'B'"><error descr="Method 'invokeMethod' is not implemented">class B extends C</error></error> { |
| def foo |
| } |
| |
| <error descr="Cyclic inheritance involving 'C'"><error descr="Method 'invokeMethod' is not implemented">class C extends B</error></error> { |
| } |
| ''') |
| } |
| |
| void testFinalParameter() { |
| testHighlighting('''\ |
| def foo0(final i) { |
| <error descr="Cannot assign a value to final parameter 'i'">i</error> = 5 |
| print i |
| } |
| |
| def foo1(i) { |
| i = 5 |
| print i |
| } |
| |
| def foo2(final i = 4) { |
| <error descr="Cannot assign a value to final parameter 'i'">i</error> = 5 |
| print i |
| } |
| |
| def foo3(final i) { |
| print i |
| } |
| ''') |
| } |
| |
| void testNonStaticInnerClass1() { |
| testHighlighting('''\ |
| class MyController { |
| static def list() { |
| def myInnerClass = new MyCommand.<error descr="Cannot reference non-static symbol 'MyCommand.MyInnerClass' from static context">MyInnerClass</error>() |
| print myInnerClass |
| } |
| } |
| |
| class MyCommand { |
| class MyInnerClass { |
| } |
| } |
| ''', GrUnresolvedAccessInspection) |
| } |
| |
| void testNonStaticInnerClass2() { |
| testHighlighting('''\ |
| class MyController { |
| def list() { |
| def myInnerClass = new MyCommand.<warning descr="Cannot reference non-static symbol 'MyCommand.MyInnerClass' from static context">MyInnerClass</warning>() |
| print myInnerClass |
| } |
| } |
| |
| class MyCommand { |
| class MyInnerClass { |
| } |
| } |
| ''', GrUnresolvedAccessInspection) |
| } |
| |
| void testNonStaticInnerClass3() { |
| myFixture.configureByText('_.groovy', '''\ |
| class MyController { |
| static def list() { |
| def myInnerClass = new MyCommand.<error descr="Cannot reference non-static symbol 'MyCommand.MyInnerClass' from static context">MyInnerClass</error>() |
| print myInnerClass |
| } |
| } |
| |
| class MyCommand { |
| class MyInnerClass { |
| } |
| } |
| ''') |
| |
| myFixture.enableInspections(GrUnresolvedAccessInspection) |
| |
| GrUnresolvedAccessInspection.getInstance(myFixture.file, myFixture.project).myHighlightInnerClasses = false |
| myFixture.testHighlighting(true, false, true) |
| } |
| |
| void testNonStaticInnerClass4() { |
| myFixture.configureByText('_.groovy', '''\ |
| class MyController { |
| def list() { |
| def myInnerClass = new MyCommand.MyInnerClass() |
| print myInnerClass |
| } |
| } |
| |
| class MyCommand { |
| class MyInnerClass { |
| } |
| } |
| ''') |
| |
| myFixture.enableInspections(GrUnresolvedAccessInspection) |
| |
| GrUnresolvedAccessInspection.getInstance(myFixture.file, myFixture.project).myHighlightInnerClasses = false |
| myFixture.testHighlighting(true, false, true) |
| } |
| |
| void testInnerClassWithStaticMethod() { |
| testHighlighting('''\ |
| class A { |
| class B { |
| static foo() {} |
| |
| static bar() { |
| B.foo() //correct |
| } |
| } |
| |
| static foo() { |
| new <error descr="Cannot reference non-static symbol 'A.B' from static context">B</error>() |
| } |
| } |
| ''') |
| } |
| |
| void testUnresolvedPropertyWhenGetPropertyDeclared() { |
| myFixture.enableInspections(GrUnresolvedAccessInspection) |
| myFixture.configureByText('_.groovy', '''\ |
| class DelegatesToTest { |
| void ideSupport() { |
| define { |
| a //delegatesTo provides getProperty from DslDelegate |
| } |
| } |
| |
| private static void define(@DelegatesTo(DslDelegate) Closure dsl) { |
| } |
| } |
| |
| class DslDelegate { |
| def getProperty(String name) { |
| {->print 1} |
| } |
| |
| |
| def ab() { |
| print a //getPropertyDeclared |
| <warning descr="Cannot resolve symbol 'a'">a</warning>() //unresolved |
| } |
| } |
| |
| print new DslDelegate().foo //resolved |
| print new DslDelegate().<warning descr="Cannot resolve symbol 'foo'">foo</warning>() //unresolved |
| ''') |
| |
| GrUnresolvedAccessInspection.getInstance(myFixture.file, myFixture.project).myHighlightIfGroovyObjectOverridden = false |
| myFixture.testHighlighting(true, false, true) |
| } |
| |
| void testImplementInaccessibleAbstractMethod() { |
| myFixture.addClass('''\ |
| package p; |
| |
| public abstract class Base { |
| abstract void foo(); |
| } |
| ''') |
| testHighlighting('''\ |
| <error>class Foo extends p.Base</error> { |
| } |
| ''') |
| } |
| |
| void testInjectedLiterals() { |
| testHighlighting("""\ |
| //language=Groovy |
| def groovy1 = '''print 'abc\\' ''' |
| |
| //language=Groovy |
| def groovy2 = '''print <error descr="String end expected">'abc\\\\' </error>''' |
| |
| """) |
| } |
| |
| void testAnnotationAsAnnotationValue() { |
| testHighlighting('''\ |
| @interface A {} |
| @interface B { |
| A[] foo() |
| } |
| @interface C { |
| A foo() |
| } |
| |
| @B(foo = @A) |
| @B(foo = [@A]) |
| @C(foo = @A) |
| @C(foo = <error descr="Cannot assign 'Integer' to 'A'">2</error>) |
| def foo |
| ''') |
| } |
| |
| void testSameNameMethodWithDifferentAccessModifiers() { |
| testHighlighting(''' |
| |
| class A { |
| def foo(){} |
| def foo(int x) {} |
| } |
| |
| class B { |
| <error descr="Mixing private and public/protected methods of the same name">private def foo()</error>{} |
| <error descr="Mixing private and public/protected methods of the same name">public def foo(int x)</error> {} |
| } |
| |
| class C { |
| private foo(){} |
| private foo(int x) {} |
| } |
| |
| class D { |
| <error>private foo()</error>{} |
| <error>protected foo(int x)</error> {} |
| } |
| |
| class E { |
| <error>private foo()</error>{} |
| <error>def foo(int x)</error> {} |
| } |
| |
| class Z { |
| private Z() {} //correct |
| private Z(x) {} //correct |
| } |
| ''') |
| } |
| |
| void testImmutable() { |
| testHighlighting('''\ |
| import groovy.transform.Immutable |
| |
| @Immutable |
| class A { |
| String immutable |
| private String mutable |
| |
| def foo() { |
| <error descr="Cannot assign a value to final field 'immutable'">immutable</error> = 5 |
| mutable = 5 |
| |
| } |
| } |
| ''') |
| } |
| |
| void testConstructorInImmutable() { |
| testHighlighting('''\ |
| import groovy.transform.Immutable |
| |
| @Immutable |
| class A { |
| String immutable |
| private String mutable |
| |
| def <error descr="Explicit constructors are not allowed for @Immutable class">A</error>() {} |
| } |
| ''') |
| } |
| |
| void testGetterInImmutable() { |
| testHighlighting('''\ |
| import groovy.transform.Immutable |
| |
| @Immutable |
| class A { |
| String immutable |
| private String mutable |
| |
| String <error descr="Repetitive method name 'getImmutable'">getImmutable</error>() {immutable} |
| String getMutable() {mutable} |
| } |
| ''') |
| } |
| |
| void testGetterInImmutable2() { |
| testHighlighting('''\ |
| import groovy.transform.Immutable |
| |
| @Immutable |
| class A { |
| String immutable |
| |
| int <error descr="Repetitive method name 'getImmutable'">getImmutable</error>() {1} |
| } |
| ''') |
| } |
| |
| void testMinusInAnnotationArg() { |
| testHighlighting('''\ |
| @interface Xx { |
| int value() |
| } |
| |
| @Xx(-1) |
| public class Bar1 { } |
| |
| @Xx(+1) |
| public class Bar2 { } |
| |
| @Xx(<error descr="Expected '++1' to be an inline constant">++1</error>) |
| public class Bar3 { } |
| ''') |
| } |
| |
| void testImportStaticFix() { |
| myFixture.configureByText('a.groovy', ''' |
| class A { |
| static void foo(String s){} |
| } |
| |
| foo(<caret>) |
| ''') |
| |
| myFixture.getAvailableIntention("Static Import Method 'A.foo'") |
| } |
| |
| void testInaccessibleWithCompileStatic() { |
| addCompileStatic() |
| testHighlighting(''' |
| import groovy.transform.CompileStatic |
| |
| @CompileStatic |
| class PrivateTest { |
| void doTest() { |
| Target.<error descr="Access to 'callMe' exceeds its access rights">callMe</error>() |
| } |
| } |
| |
| class Target { |
| private static void callMe() {} |
| } |
| ''') |
| } |
| } |