2 * Copyright 2000-2016 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.jetbrains.plugins.groovy.transformations.impl.autoClone
18 import com.intellij.psi.CommonClassNames
19 import com.intellij.psi.PsiEnumConstant
20 import com.intellij.psi.PsiModifier
21 import com.intellij.psi.PsiType
22 import com.intellij.psi.impl.light.LightMethodBuilder
23 import org.jetbrains.plugins.groovy.GroovyLanguage
24 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression
25 import org.jetbrains.plugins.groovy.lang.psi.impl.findDeclaredDetachedValue
26 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil
27 import org.jetbrains.plugins.groovy.transformations.AstTransformationSupport
28 import org.jetbrains.plugins.groovy.transformations.TransformationContext
29 import org.jetbrains.plugins.groovy.transformations.plusAssign
31 class AutoCloneTransformationSupport : AstTransformationSupport {
33 private companion object {
34 val AUTO_CLONE_FQN = "groovy.transform.AutoClone"
35 val ORIGIN_INFO = "created by @AutoClone"
36 val CNSE_FQN = "java.lang.CloneNotSupportedException"
39 override fun applyTransformation(context: TransformationContext) {
40 val annotation = context.getAnnotation(AUTO_CLONE_FQN) ?: return
42 context.addInterface(CommonClassNames.JAVA_LANG_CLONEABLE)
44 // public T clone() throws CloneNotSupportedException
45 context += LightMethodBuilder(context.manager, "clone").apply {
46 addModifier(PsiModifier.PUBLIC)
47 setMethodReturnType(TypesUtil.createType(context.codeClass))
48 addException(CNSE_FQN)
49 navigationElement = annotation
50 originInfo = ORIGIN_INFO
53 val value = annotation.findDeclaredDetachedValue("style") as? GrReferenceExpression ?: return
54 val constant = value.resolve() as? PsiEnumConstant ?: return
55 if (constant.containingClass?.qualifiedName != "groovy.transform.AutoCloneStyle") return
56 when (constant.name) {
57 "COPY_CONSTRUCTOR" -> {
58 if (context.codeClass.codeConstructors.isEmpty()) {
59 context += LightMethodBuilder(context.codeClass, GroovyLanguage).apply {
61 addModifier(PsiModifier.PUBLIC)
62 navigationElement = context.codeClass
66 // protected T(T other)
67 context += LightMethodBuilder(context.codeClass, GroovyLanguage).apply {
69 addModifier(PsiModifier.PROTECTED)
70 addParameter("other", TypesUtil.createType(context.codeClass))
71 navigationElement = context.codeClass
72 originInfo = ORIGIN_INFO
76 // protected void cloneOrCopyMembers(T other) throws CloneNotSupportedException
77 context += LightMethodBuilder(context.manager, "cloneOrCopyMembers").apply {
78 addModifier(PsiModifier.PROTECTED)
79 setMethodReturnType(PsiType.VOID)
80 addParameter("other", TypesUtil.createType(context.codeClass))
81 addException(CNSE_FQN)
82 navigationElement = annotation
83 originInfo = ORIGIN_INFO