blob: eca21e14ffbe99a2bc5d9ae8c385746916276a54 [file] [log] [blame]
/*
* 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.
* 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.dsl
import com.intellij.codeInsight.documentation.DocumentationManager
import com.intellij.openapi.module.Module
import com.intellij.openapi.roots.ContentEntry
import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiFile
import com.intellij.testFramework.LightProjectDescriptor
import com.intellij.testFramework.PsiTestUtil
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.lang.documentation.GroovyDocumentationProvider
import org.jetbrains.plugins.groovy.util.TestUtils
/**
* @author peter
*/
public class GroovyDslTest extends LightCodeInsightFixtureTestCase {
private static descriptor = new DefaultLightProjectDescriptor() {
@Override
void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
PsiTestUtil.addLibrary(module, model, "GROOVY", TestUtils.getMockGroovyLibraryHome(), TestUtils.GROOVY_JAR);
}
}
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
descriptor
}
@Override
protected String getBasePath() {
TestUtils.testDataPath + "groovy/dsl"
}
private def doCustomTest(String s) {
addGdsl(s)
myFixture.testCompletion(getTestName(false) + ".groovy", getTestName(false) + "_after.groovy")
}
private def addGdsl(String text) {
final PsiFile file = myFixture.addFileToProject(getTestName(false) + "Enhancer.gdsl", text);
GroovyDslFileIndex.activateUntilModification(file.virtualFile)
}
public void doTest() throws Throwable {
myFixture.testCompletion(getTestName(false) + ".gdsl", getTestName(false) + "_after.gdsl")
}
public void testCompleteTopLevel() throws Throwable {
myFixture.configureByText 'a.gdsl', '<caret>'
myFixture.completeBasic()
def expected = ['contributor', 'contribute', 'currentType', 'assertVersion']
if (!myFixture.lookupElementStrings.containsAll(expected)) {
assertSameElements(expected, myFixture.lookupElementStrings)
}
}
public void testCompleteInContributor() throws Throwable {
myFixture.configureByText 'a.gdsl', 'contribute { <caret> }'
myFixture.completeBasic()
def expected = ['method', 'property', 'parameter']
if (!myFixture.lookupElementStrings.containsAll(expected)) {
assertSameElements(expected, myFixture.lookupElementStrings)
}
}
public void testCompleteClassMethod() throws Throwable {
doCustomTest("""
def ctx = context(ctype: "java.lang.String")
contributor ([ctx], {
method name:"zzz", type:"void", params:[:]
})
""")
}
public void "test on anonymous class"() {
addGdsl '''
import com.intellij.patterns.PsiJavaPatterns
contribute(ctype:PsiJavaPatterns.psiClass()) {
method name:'foo' + psiClass.name, type:void, params:[:]
}'''
myFixture.configureByText 'a.groovy', '''
class Foo<T> {
def foo(T t) {
t.f<caret>
}
}
'''
myFixture.completeBasic()
myFixture.assertPreferredCompletionItems 0, 'finalize', 'fooT'
}
public void testDelegateToThrowable() throws Throwable {
doCustomTest("""
def ctx = context(ctype: "java.lang.String")
contributor ctx, {
findClass("java.lang.Throwable")?.methods?.each{add it}
}
""")
}
public void testDelegateToArgument() throws Throwable {
doCustomTest("""
def ctx = context(scope: closureScope(isArgument: true))
contributor(ctx, {
def call = enclosingCall("boo")
if (call) {
def method = call.bind()
if ("Runner".equals(method?.containingClass?.qualifiedName)) {
delegatesTo(call.arguments[0]?.classType)
}
}
})
""")
}
public void testDelegateToArgument2() throws Throwable {
doCustomTest("""
def ctx = context(scope: closureScope(isArgument: true))
contributor(ctx, {
def call = enclosingCall("boo")
if (call) {
delegatesTo(call.arguments[0]?.classType)
}
})
""")
}
public void testClassContext() throws Throwable {
addGdsl("""
def ctx = context(scope: classScope(name: /.*WsSecurityConfig/))
contributor ctx, {
property name: "auxWsProperty", type: "java.lang.String"
}
""")
myFixture.testCompletionTyping(getTestName(false) + ".groovy", '\n', getTestName(false) + "_after.groovy")
}
public void testCategoryWhenMethodRenamed() {
PsiClass category = myFixture.addClass("""
public class MyCategory {
public void foo(String s) {}
}""")
def foo = category.getMethods()[0]
addGdsl("""
contributor([:]){category 'MyCategory'}""")
myFixture.renameElement foo, "bar", false, false
myFixture.testCompletion(getTestName(false) + ".groovy", getTestName(false) + "_after.groovy")
}
public void testPathRegexp() {
addGdsl "contributor(pathRegexp: '.*aaa.*') { property name:'fffooo', type:'int' }"
myFixture.configureFromExistingVirtualFile myFixture.addFileToProject("aaa/foo.groovy", "fff<caret>x").virtualFile
myFixture.completeBasic()
assert 'fffooo' in myFixture.lookupElementStrings
myFixture.configureFromExistingVirtualFile myFixture.addFileToProject("bbb/foo.groovy", "fff<caret>x").virtualFile
myFixture.completeBasic()
assertEmpty myFixture.lookupElementStrings
}
public void testNamedParameters() {
addGdsl '''contribute(currentType(String.name)) {
method name:'foo', type:void, params:[:], namedParams:[
parameter(name:'param1', type:String),
parameter(name:'param2', type:Integer),
]
}'''
myFixture.configureByText 'a.groovy', '"".foo(par<caret>)'
myFixture.completeBasic()
myFixture.assertPreferredCompletionItems 0, 'param1', 'param2'
}
public void testNamedParametersGroovyConvention() {
addGdsl '''contribute(currentType(String.name)) {
method name:'foo', type:void, params:[args:[
parameter(name:'param1', type:String, doc:'My doc'),
parameter(name:'param2', type:Integer),
]]
}'''
myFixture.configureByText 'a.groovy', '"".foo(par<caret>)'
myFixture.completeBasic()
myFixture.assertPreferredCompletionItems 0, 'param1', 'param2'
assert '<pre><b>param1</b>: java.lang.String</pre><p>My doc' == generateDoc()
}
private String generateDoc() {
def element = DocumentationManager.getInstance(project).findTargetElement(myFixture.editor, myFixture.file)
return new GroovyDocumentationProvider().generateDoc(element, null)
}
public void testCheckNamedArgumentTypes() {
addGdsl '''contribute(currentType(String.name)) {
method name:'foo', type:void, params:[args:[
parameter(name:'param1', type:File),
parameter(name:'param2', type:Integer),
]]
}'''
myFixture.configureByText 'a.groovy', '''
"".foo(param1:<warning descr="Type of argument 'param1' can not be 'Integer'">2</warning>, param2:2)
'''
myFixture.enableInspections(new GroovyAssignabilityCheckInspection())
myFixture.checkHighlighting(true, false, false)
}
public void testMethodDoc() {
addGdsl '''contribute(currentType(String.name)) {
method name:'foo', type:void, params:[:], doc:'Some doc'
}'''
myFixture.configureByText 'a.groovy', '"".fo<caret>o'
myFixture.completeBasic()
assert generateDoc().contains('Some doc')
assert generateDoc().contains('foo')
assert generateDoc().contains('()')
}
public void testPropertyDoc() {
addGdsl '''contribute(currentType(String.name)) {
property name:'foo', type:int, doc:'Some doc2'
}'''
myFixture.configureByText 'a.groovy', '"".fo<caret>o'
myFixture.completeBasic()
assert generateDoc().contains('Some doc2')
assert generateDoc().contains('getFoo')
}
public void testVariableInAnnotationClosureContext() {
addGdsl '''
contributor(scope: closureScope(annotationName:'Ensures')) {
variable(name: 'result', type:'java.lang.Object')
}
'''
myFixture.configureByText('a.groovy', '''\
@interface Ensures {}
@Ensures({re<caret>sult == 2})
def foo() {}
''')
assertNotNull(myFixture.getReferenceAtCaretPosition().resolve())
}
public void testVariableInMethodCallClosureContext() {
addGdsl '''
contributor(scope: closureScope(methodName:'ensures')) {
variable(name: 'result', type:'java.lang.Object')
}
'''
myFixture.configureByText('a.groovy', '''\
ensures{re<caret>sult == 2}
''')
assertNotNull(myFixture.getReferenceAtCaretPosition().resolve())
}
void testScriptSuperClass() {
myFixture.addClass('''\
public class Abc {
public void foo() {}
}
''')
addGdsl('''
scriptSuperClass(pattern: 'a.groovy', superClass: 'Abc')
''')
myFixture.configureByText('a.groovy', '''\
fo<caret>o()
''')
assertNotNull(myFixture.getReferenceAtCaretPosition().resolve())
}
void testEnumConstructor() {
myFixture.configureByText('a.groovy', '''\
enum Myenum {
a<caret>b(1, 2, 4)
}
''')
addGdsl('''
contribute(currentType("Myenum")) {
constructor params:[foo:Integer, bar:Integer, goo:Integer]
}''')
assertNotNull(myFixture.getReferenceAtCaretPosition().resolve())
}
}