From 8e5f004aedbd2da9a9c6df60757f1ed370603993 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Tue, 8 Nov 2016 17:31:18 +0300 Subject: [PATCH] [groovy] @Singleton support: - implement as AstTransformationSupport instead of gdsl - add proper members - support `property` parameter - support `lazy` parameter --- .../SingletonTransformationSupport.kt | 54 +++++++ .../groovy/transformations/singleton/impl.kt} | 15 +- plugins/groovy/src/META-INF/plugin.xml | 2 + .../dsl/GroovyTransformationsTest.groovy | 4 - .../SingletonTransformationSupportTest.groovy | 136 ++++++++++++++++++ .../dsl/transform/SingletonTransform.groovy | 3 - .../transform/SingletonTransform_after.groovy | 3 - 7 files changed, 198 insertions(+), 19 deletions(-) create mode 100644 plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/transformations/singleton/SingletonTransformationSupport.kt rename plugins/groovy/groovy-psi/{resources/standardDsls/singletonTransform.gdsl => src/org/jetbrains/plugins/groovy/transformations/singleton/impl.kt} (64%) create mode 100644 plugins/groovy/test/org/jetbrains/plugins/groovy/transformations/singleton/SingletonTransformationSupportTest.groovy delete mode 100644 plugins/groovy/testdata/groovy/dsl/transform/SingletonTransform.groovy delete mode 100644 plugins/groovy/testdata/groovy/dsl/transform/SingletonTransform_after.groovy diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/transformations/singleton/SingletonTransformationSupport.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/transformations/singleton/SingletonTransformationSupport.kt new file mode 100644 index 000000000000..6f2dda9e6b9a --- /dev/null +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/transformations/singleton/SingletonTransformationSupport.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2016 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.transformations.singleton + +import com.intellij.util.text.nullize +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierFlags.* +import org.jetbrains.plugins.groovy.lang.psi.impl.booleanValue +import org.jetbrains.plugins.groovy.lang.psi.impl.findDeclaredDetachedValue +import org.jetbrains.plugins.groovy.lang.psi.impl.stringValue +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightField +import org.jetbrains.plugins.groovy.transformations.AstTransformationSupport +import org.jetbrains.plugins.groovy.transformations.TransformationContext +import org.jetbrains.plugins.groovy.transformations.plusAssign + +class SingletonTransformationSupport : AstTransformationSupport { + + override fun applyTransformation(context: TransformationContext) { + val annotation = context.getAnnotation(singletonFqn) ?: return + val name = annotation.findDeclaredDetachedValue("property").stringValue().nullize(true) ?: "instance" + val lazy = annotation.findDeclaredDetachedValue("lazy").booleanValue() ?: false + + context += GrLightField(context.codeClass, name, context.classType, annotation).apply { + val modifiers = STATIC_MASK or if (lazy) PRIVATE_MASK else PUBLIC_MASK or FINAL_MASK + modifierList.setModifiers(modifiers) + navigationElement = annotation + originInfo = singletonOriginInfo + } + + context += context.memberBuilder.constructor { + setModifiers(PRIVATE_MASK) + originInfo = singletonOriginInfo + } + + context += context.memberBuilder.method("get${name.capitalize()}") { + setModifiers(PUBLIC_MASK or STATIC_MASK) + returnType = context.classType + navigationElement = annotation + originInfo = singletonOriginInfo + } + } +} \ No newline at end of file diff --git a/plugins/groovy/groovy-psi/resources/standardDsls/singletonTransform.gdsl b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/transformations/singleton/impl.kt similarity index 64% rename from plugins/groovy/groovy-psi/resources/standardDsls/singletonTransform.gdsl rename to plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/transformations/singleton/impl.kt index d4e2ad6aba45..2d68c7d443e8 100644 --- a/plugins/groovy/groovy-psi/resources/standardDsls/singletonTransform.gdsl +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/transformations/singleton/impl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -13,12 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package standardDsls +package org.jetbrains.plugins.groovy.transformations.singleton -contributor(ctype:hasAnnotation("groovy.lang.Singleton")) { - if (psiClass?.hasAnnotation("groovy.lang.Singleton")) { - property name: "instance", - type: psiClass?.getQualifiedName() ?: "java.lang.Object", - isStatic: true - } -} +import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames + +internal val singletonFqn = GroovyCommonClassNames.GROOVY_LANG_SINGLETON +internal val singletonOriginInfo = "by @Singleton" \ No newline at end of file diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 46c173d67909..1580a5d9dfba 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -145,6 +145,8 @@ + + setInstance(null) +Simple simple +simple = Simple.getInstance() +simple = Simple.instance +simple = new Simple() + +CustomName.setCoolInstance(null) +CustomName customName +customName = CustomName.getCoolInstance() +customName = CustomName.coolInstance +customName = new CustomName() + +DefaultConstructor.setInstance(null) +DefaultConstructor defaultConstructor +defaultConstructor = DefaultConstructor.getInstance() +defaultConstructor = DefaultConstructor.instance +defaultConstructor = new DefaultConstructor() + +CustomConstructor customConstructor +customConstructor = CustomConstructor.getInstance() +customConstructor = CustomConstructor.instance +customConstructor = new CustomConstructor() +customConstructor = new CustomConstructor(1, "") + +Lazy lazy +lazy = Lazy.getInstance() +lazy = Lazy.instance +lazy = new Lazy() + +LazyDefaultConstructor lazyDefaultConstructor +lazyDefaultConstructor = LazyDefaultConstructor.getInstance() +lazyDefaultConstructor = LazyDefaultConstructor.instance +lazyDefaultConstructor = new LazyDefaultConstructor() +''' + enableInspections(GrUnresolvedAccessInspection) + checkHighlighting() + + configureByText 'Main.java', '''\ +public class Main { + public static void main(String[] args) { + Simple simple; + simple = Simple.getInstance(); + simple = Simple.instance; + simple = new Simple(); + + CustomName customName; + customName = CustomName.getCoolInstance(); + customName = CustomName.coolInstance; + customName = new CustomName(); + + DefaultConstructor defaultConstructor; + defaultConstructor = DefaultConstructor.getInstance(); + defaultConstructor = DefaultConstructor.instance; + defaultConstructor = new DefaultConstructor(); + + CustomConstructor customConstructor; + customConstructor = CustomConstructor.getInstance(); + customConstructor = CustomConstructor.instance; + customConstructor = new CustomConstructor(); + customConstructor = new CustomConstructor(1, ""); + + Lazy lazy; + lazy = Lazy.getInstance(); + lazy = Lazy.instance; + lazy = new Lazy(); + + LazyDefaultConstructor lazyDefaultConstructor; + lazyDefaultConstructor = LazyDefaultConstructor.getInstance(); + lazyDefaultConstructor = LazyDefaultConstructor.instance; + lazyDefaultConstructor = new LazyDefaultConstructor(); + } +} +''' + checkHighlighting() + assert !file.contentsLoaded + } + } +} diff --git a/plugins/groovy/testdata/groovy/dsl/transform/SingletonTransform.groovy b/plugins/groovy/testdata/groovy/dsl/transform/SingletonTransform.groovy deleted file mode 100644 index ba22e17752a4..000000000000 --- a/plugins/groovy/testdata/groovy/dsl/transform/SingletonTransform.groovy +++ /dev/null @@ -1,3 +0,0 @@ -@Singleton class T {} - -T.inst \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/dsl/transform/SingletonTransform_after.groovy b/plugins/groovy/testdata/groovy/dsl/transform/SingletonTransform_after.groovy deleted file mode 100644 index 97ee38e0af32..000000000000 --- a/plugins/groovy/testdata/groovy/dsl/transform/SingletonTransform_after.groovy +++ /dev/null @@ -1,3 +0,0 @@ -@Singleton class T {} - -T.instance \ No newline at end of file