mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[groovy] support constant values via field references (IDEA-186646)
This commit is contained in:
+18
-31
@@ -1,21 +1,7 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -27,6 +13,9 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrRefere
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.plugins.groovy.lang.psi.impl.GrAnnotationUtilKt.findDeclaredDetachedValue;
|
||||
import static org.jetbrains.plugins.groovy.lang.psi.impl.GrAnnotationUtilKt.getArrayValue;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
@@ -146,20 +135,18 @@ public class GrAnnotationUtil {
|
||||
}
|
||||
|
||||
public static List<String> getStringArrayValue(@NotNull PsiAnnotation annotation, @NotNull String attributeName, boolean declared) {
|
||||
PsiAnnotationMemberValue value =
|
||||
declared ? annotation.findDeclaredAttributeValue(attributeName) : annotation.findAttributeValue(attributeName);
|
||||
if (value instanceof PsiArrayInitializerMemberValue) {
|
||||
return ContainerUtil.mapNotNull(((PsiArrayInitializerMemberValue)value).getInitializers(), memberValue -> {
|
||||
String string = getString(memberValue);
|
||||
return StringUtil.isEmpty(string) ? null : string;
|
||||
});
|
||||
}
|
||||
else {
|
||||
String string = getString(value);
|
||||
if (!StringUtil.isEmpty(string)) {
|
||||
return Collections.singletonList(string);
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
PsiAnnotationMemberValue value = findDetachedAttributeValue(annotation, attributeName, declared);
|
||||
if (value == null) return Collections.emptyList();
|
||||
return getArrayValue(value, AnnotationUtil::getStringAttributeValue);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiAnnotationMemberValue findDetachedAttributeValue(@NotNull PsiAnnotation annotation,
|
||||
@Nullable String attributeName,
|
||||
boolean declared) {
|
||||
PsiAnnotationMemberValue declaredValue = findDeclaredDetachedValue(annotation, attributeName);
|
||||
if (declaredValue != null) return declaredValue;
|
||||
if (declared) return null;
|
||||
return annotation.findAttributeValue(attributeName);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-15
@@ -1,23 +1,10 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil
|
||||
import com.intellij.psi.PsiAnnotation
|
||||
import com.intellij.psi.PsiAnnotationMemberValue
|
||||
import com.intellij.psi.PsiArrayInitializerMemberValue
|
||||
import com.intellij.psi.PsiLiteral
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList
|
||||
|
||||
@@ -25,6 +12,16 @@ fun PsiAnnotation.findDeclaredDetachedValue(attributeName: String?): PsiAnnotati
|
||||
return AnnotationUtil.findDeclaredAttribute(this, attributeName)?.detachedValue
|
||||
}
|
||||
|
||||
internal fun <T : Any> PsiAnnotationMemberValue.getArrayValue(computeValue: (PsiAnnotationMemberValue) -> T?): List<T> {
|
||||
if (this is PsiArrayInitializerMemberValue) {
|
||||
return initializers.mapNotNull(computeValue)
|
||||
}
|
||||
else {
|
||||
val value = computeValue(this) ?: return emptyList()
|
||||
return listOf(value)
|
||||
}
|
||||
}
|
||||
|
||||
fun PsiAnnotationMemberValue?.booleanValue() = (this as? PsiLiteral)?.value as? Boolean
|
||||
|
||||
fun PsiAnnotationMemberValue?.stringValue() = (this as? PsiLiteral)?.value as? String
|
||||
|
||||
+9
-15
@@ -1,26 +1,14 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.lang.psi.util;
|
||||
|
||||
import com.intellij.psi.PsiConstantEvaluationHelper;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.impl.ConstantExpressionEvaluator;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrParenthesizedExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
|
||||
|
||||
/**
|
||||
@@ -36,6 +24,12 @@ public class GroovyConstantExpressionEvaluator implements ConstantExpressionEval
|
||||
if (expression instanceof GrLiteral) {
|
||||
return ((GrLiteral)expression).getValue();
|
||||
}
|
||||
if (expression instanceof GrReferenceExpression) {
|
||||
PsiElement resolved = ((GrReferenceExpression)expression).resolve();
|
||||
if (resolved instanceof PsiField) {
|
||||
return ((PsiField)resolved).computeConstantValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.lang.resolve
|
||||
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import groovy.transform.CompileStatic
|
||||
import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor
|
||||
import org.jetbrains.plugins.groovy.LightGroovyTestCase
|
||||
|
||||
import static org.jetbrains.plugins.groovy.lang.psi.impl.GrAnnotationUtil.getStringArrayValue
|
||||
import static org.jetbrains.plugins.groovy.util.TestUtils.disableAstLoading
|
||||
|
||||
@CompileStatic
|
||||
class ConstantExpressionTest extends LightGroovyTestCase {
|
||||
|
||||
final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST
|
||||
|
||||
private void addJavaAnnotation() {
|
||||
fixture.addClass '''\
|
||||
package com.foo;
|
||||
|
||||
public @interface MyJavaAnnotation {
|
||||
String[] stringArrayValue() default {};
|
||||
String stringValue() default "default string";
|
||||
}
|
||||
'''
|
||||
}
|
||||
|
||||
private void addJavaConstants() {
|
||||
fixture.addClass '''\
|
||||
package com.foo;
|
||||
|
||||
public interface Constants {
|
||||
String HELLO = "java hello";
|
||||
String WORLD = "java world";
|
||||
String COMPOUND = HELLO + " " + WORLD;
|
||||
}
|
||||
'''
|
||||
}
|
||||
|
||||
void 'test annotation value from java'() {
|
||||
addJavaAnnotation()
|
||||
addJavaConstants()
|
||||
fixture.addFileToProject '_.groovy', '''\
|
||||
import com.foo.Constants
|
||||
import com.foo.MyJavaAnnotation
|
||||
|
||||
@MyJavaAnnotation(stringArrayValue = [
|
||||
Constants.HELLO,
|
||||
Constants.WORLD,
|
||||
Constants.COMPOUND,
|
||||
"literal"
|
||||
])
|
||||
class GroovyClass {}
|
||||
'''
|
||||
disableAstLoading project, testRootDisposable
|
||||
def clazz = fixture.findClass 'GroovyClass'
|
||||
def annotation = clazz.modifierList.findAnnotation 'com.foo.MyJavaAnnotation'
|
||||
def values = getStringArrayValue annotation, 'stringArrayValue', false
|
||||
assertOrderedEquals(["java hello", "java world", "java hello java world", "literal"], values)
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,26 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
package org.jetbrains.plugins.groovy.util;
|
||||
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.PluginPathManager;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFileFilter;
|
||||
import com.intellij.pom.PomDeclarationSearcher;
|
||||
import com.intellij.pom.PomTarget;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture;
|
||||
import com.intellij.util.CollectConsumer;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.LocalTimeCounter;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.extensions.NamedArgumentDescriptor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
@@ -281,4 +271,8 @@ public abstract class TestUtils {
|
||||
//workaround for IDEA-148973: Groovy static compilation fails to compile calls of overriding methods with covariant type in interfaces
|
||||
return aClass.getMethods();
|
||||
}
|
||||
|
||||
public static void disableAstLoading(@NotNull Project project, @NotNull Disposable parent) {
|
||||
PsiManagerEx.getInstanceEx(project).setAssertOnFileLoadingFilter(VirtualFileFilter.ALL, parent);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user