Resource Bundles: Implement references on Kotlin string literals
#KT-6946 In Progress
This commit is contained in:
@@ -405,3 +405,5 @@ public fun JetDeclaration.visibilityModifier(): PsiElement? {
|
||||
|
||||
public fun JetDeclaration.visibilityModifierType(): JetModifierKeywordToken?
|
||||
= visibilityModifier()?.node?.elementType as JetModifierKeywordToken?
|
||||
|
||||
public fun JetStringTemplateExpression.isPlain() = entries.all { it is JetLiteralStringTemplateEntry }
|
||||
@@ -158,7 +158,7 @@ public final class InTextDirectivesUtils {
|
||||
List<String> resultPrefixes = Lists.newArrayList();
|
||||
|
||||
for (String prefix : prefixes) {
|
||||
if (prefix.startsWith("//")) {
|
||||
if (prefix.startsWith("//") || prefix.startsWith("##")) {
|
||||
resultPrefixes.add(StringUtil.trimLeading(prefix.substring(2)));
|
||||
}
|
||||
else {
|
||||
@@ -181,7 +181,7 @@ public final class InTextDirectivesUtils {
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
line = line.trim();
|
||||
if (line.startsWith("//")) {
|
||||
if (line.startsWith("//") || line.startsWith("##")) {
|
||||
String uncommentedLine = line.substring(2).trim();
|
||||
if (!uncommentedLine.isEmpty()) {
|
||||
result.add(uncommentedLine);
|
||||
|
||||
@@ -525,6 +525,7 @@ fun main(args: Array<String>) {
|
||||
testClass(javaClass<AbstractJetFindUsagesTest>()) {
|
||||
model("findUsages/kotlin", pattern = """^(.+)\.0\.kt$""")
|
||||
model("findUsages/java", pattern = """^(.+)\.0\.java$""")
|
||||
model("findUsages/propertyFiles", pattern = """^(.+)\.0\.properties$""")
|
||||
}
|
||||
|
||||
testClass(javaClass<AbstractKotlinFindUsagesWithLibraryTest>()) {
|
||||
|
||||
@@ -17,22 +17,17 @@
|
||||
package org.jetbrains.kotlin.idea.findUsages
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
|
||||
import com.intellij.psi.PsiPackage
|
||||
import com.intellij.psi.PsiReferenceExpression
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.idea.findUsages.UsageTypeEnum.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.findUsages.UsageTypeEnum.*
|
||||
import org.jetbrains.kotlin.idea.references.*
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
|
||||
public object UsageTypeUtils {
|
||||
@@ -41,6 +36,7 @@ public object UsageTypeUtils {
|
||||
is JetForExpression -> return IMPLICIT_ITERATION
|
||||
is JetMultiDeclaration -> return READ
|
||||
is JetPropertyDelegate -> return PROPERTY_DELEGATION
|
||||
is JetStringTemplateExpression -> return USAGE_IN_STRING_LITERAL
|
||||
}
|
||||
|
||||
val refExpr = element?.getNonStrictParentOfType<JetReferenceExpression>()
|
||||
@@ -249,5 +245,7 @@ enum class UsageTypeEnum {
|
||||
CLASS_CAST_TO,
|
||||
ANNOTATION,
|
||||
CLASS_NEW_OPERATOR,
|
||||
NAMED_ARGUMENT
|
||||
NAMED_ARGUMENT,
|
||||
|
||||
USAGE_IN_STRING_LITERAL
|
||||
}
|
||||
|
||||
@@ -361,6 +361,7 @@
|
||||
<weigher key="completion" implementationClass="org.jetbrains.kotlin.idea.completion.KotlinLookupElementProximityWeigher" id="kotlin.proximity" order="after proximity"/>
|
||||
|
||||
<psi.referenceContributor language="jet" implementation="org.jetbrains.kotlin.idea.references.JetReferenceContributor"/>
|
||||
<psi.referenceContributor language="jet" implementation="org.jetbrains.kotlin.idea.properties.KotlinPropertiesReferenceContributor"/>
|
||||
|
||||
<renamePsiElementProcessor id="KotlinClass"
|
||||
implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinClassProcessor"
|
||||
|
||||
@@ -72,6 +72,8 @@ public object JetUsageTypeProvider : UsageTypeProviderEx {
|
||||
ANNOTATION -> UsageType.ANNOTATION
|
||||
CLASS_NEW_OPERATOR -> UsageType.CLASS_NEW_OPERATOR
|
||||
NAMED_ARGUMENT -> JetUsageTypes.NAMED_ARGUMENT
|
||||
|
||||
USAGE_IN_STRING_LITERAL -> UsageType.LITERAL_USAGE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.idea.properties
|
||||
|
||||
import com.intellij.patterns.PlatformPatterns
|
||||
import com.intellij.psi.PsiReferenceContributor
|
||||
import com.intellij.psi.PsiReferenceRegistrar
|
||||
import org.jetbrains.kotlin.psi.JetLiteralStringTemplateEntry
|
||||
import org.jetbrains.kotlin.psi.JetStringTemplateExpression
|
||||
|
||||
public class KotlinPropertiesReferenceContributor : PsiReferenceContributor() {
|
||||
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
|
||||
registrar.registerReferenceProvider(
|
||||
PlatformPatterns.psiElement(JetStringTemplateExpression::class.java),
|
||||
KotlinPropertyKeyReferenceProvider
|
||||
)
|
||||
|
||||
registrar.registerReferenceProvider(
|
||||
PlatformPatterns.psiElement(JetStringTemplateExpression::class.java),
|
||||
KotlinResourceBundleNameReferenceProvider
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.idea.properties
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil
|
||||
import com.intellij.lang.properties.ResourceBundleReference
|
||||
import com.intellij.lang.properties.references.PropertyReference
|
||||
import com.intellij.psi.ElementManipulators
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.PsiReferenceProvider
|
||||
import com.intellij.psi.search.LocalSearchScope
|
||||
import com.intellij.util.ProcessingContext
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isPlain
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getParentResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
|
||||
private val PROPERTY_KEY = FqName(AnnotationUtil.PROPERTY_KEY)
|
||||
private val PROPERTY_KEY_RESOURCE_BUNDLE = Name.identifier(AnnotationUtil.PROPERTY_KEY_RESOURCE_BUNDLE_PARAMETER)
|
||||
|
||||
private fun AnnotationDescriptor.getBundleName(): String? {
|
||||
return allValueArguments.entrySet().singleOrNull { it.key.name == PROPERTY_KEY_RESOURCE_BUNDLE }?.value?.value as? String
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.getBundleNameByAnnotation(): String? {
|
||||
return (annotations.findAnnotation(PROPERTY_KEY) ?: annotations.findExternalAnnotation(PROPERTY_KEY))?.getBundleName()
|
||||
}
|
||||
|
||||
private fun JetExpression.getBundleNameByContext(): String? {
|
||||
val expression = JetPsiUtil.safeDeparenthesize(this)
|
||||
val parent = expression.parent
|
||||
|
||||
(parent as? JetProperty)?.let { return it.resolveToDescriptor().getBundleNameByAnnotation() }
|
||||
|
||||
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
|
||||
val resolvedCall =
|
||||
if (parent is JetQualifiedExpression && expression == parent.receiverExpression) {
|
||||
parent.selectorExpression.getResolvedCall(bindingContext)
|
||||
}
|
||||
else {
|
||||
expression.getParentResolvedCall(bindingContext)
|
||||
} ?: return null
|
||||
val callable = resolvedCall.resultingDescriptor
|
||||
|
||||
if ((resolvedCall.extensionReceiver as? ExpressionReceiver)?.expression == expression) {
|
||||
val returnTypeAnnotations = callable.returnType?.annotations ?: return null
|
||||
return Annotations
|
||||
.findUseSiteTargetedAnnotation(returnTypeAnnotations, AnnotationUseSiteTarget.RECEIVER, PROPERTY_KEY)
|
||||
?.getBundleName()
|
||||
}
|
||||
|
||||
return resolvedCall.valueArguments.entrySet()
|
||||
.singleOrNull { it.value.arguments.any { it.getArgumentExpression() == expression } }
|
||||
?.key
|
||||
?.getBundleNameByAnnotation()
|
||||
}
|
||||
|
||||
private fun JetAnnotationEntry.getPropertyKeyResolvedCall(): ResolvedCall<*>? {
|
||||
val resolvedCall = getResolvedCall(analyze(BodyResolveMode.PARTIAL)) ?: return null
|
||||
val klass = (resolvedCall.resultingDescriptor as? ConstructorDescriptor)?.containingDeclaration ?: return null
|
||||
if (klass.kind != ClassKind.ANNOTATION_CLASS || klass.importableFqName != PROPERTY_KEY) return null
|
||||
return resolvedCall
|
||||
}
|
||||
|
||||
private fun JetStringTemplateExpression.isBundleName(): Boolean {
|
||||
val parent = JetPsiUtil.safeDeparenthesize(this).parent
|
||||
when (parent) {
|
||||
is JetValueArgument -> {
|
||||
val resolvedCall = parent.getStrictParentOfType<JetAnnotationEntry>()?.getPropertyKeyResolvedCall() ?: return false
|
||||
val valueParameter = (resolvedCall.getArgumentMapping(parent) as? ArgumentMatch)?.valueParameter ?: return false
|
||||
if (valueParameter.name != PROPERTY_KEY_RESOURCE_BUNDLE) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
is JetProperty -> {
|
||||
val contexts = (parent.useScope as? LocalSearchScope)?.scope ?: arrayOf(parent.containingFile)
|
||||
return contexts.any {
|
||||
it.anyDescendantOfType<JetAnnotationEntry> f@ { entry ->
|
||||
if (!entry.valueArguments.any { it.getArgumentName()?.asName == PROPERTY_KEY_RESOURCE_BUNDLE }) return@f false
|
||||
val resolvedCall = entry.getPropertyKeyResolvedCall() ?: return@f false
|
||||
val parameter = resolvedCall.resultingDescriptor.valueParameters.singleOrNull { it.name == PROPERTY_KEY_RESOURCE_BUNDLE }
|
||||
?: return@f false
|
||||
val valueArgument = resolvedCall.valueArguments[parameter] as? ExpressionValueArgument ?: return@f false
|
||||
val bundleNameExpression = valueArgument.valueArgument?.getArgumentExpression() ?: return@f false
|
||||
bundleNameExpression is JetSimpleNameExpression && bundleNameExpression.mainReference.resolve() == parent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
public object KotlinPropertyKeyReferenceProvider : PsiReferenceProvider() {
|
||||
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<out PsiReference> {
|
||||
if (!(element is JetStringTemplateExpression && element.isPlain())) return PsiReference.EMPTY_ARRAY
|
||||
val bundleName = element.getBundleNameByContext() ?: return PsiReference.EMPTY_ARRAY
|
||||
return arrayOf(PropertyReference(ElementManipulators.getValueText(element), element, bundleName, false))
|
||||
}
|
||||
}
|
||||
|
||||
public object KotlinResourceBundleNameReferenceProvider : PsiReferenceProvider() {
|
||||
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<out PsiReference> {
|
||||
if (!(element is JetStringTemplateExpression && element.isPlain() && element.isBundleName())) return PsiReference.EMPTY_ARRAY
|
||||
return arrayOf(ResourceBundleReference(element))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// PSI_ELEMENT: com.intellij.lang.properties.psi.PropertiesFile
|
||||
// FIND_BY_REF
|
||||
import org.jetbrains.annotations.PropertyKey
|
||||
|
||||
public fun message(@PropertyKey(resourceBundle = "<caret>idea.testData.findUsages.kotlin.propertyFiles.propertyFileUsagesByRef.2") key: String) = key
|
||||
|
||||
fun test() {
|
||||
message("foo.bar")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import org.jetbrains.annotations.PropertyKey;
|
||||
|
||||
class A {
|
||||
static String message(@PropertyKey(resourceBundle = "idea.testData.findUsages.kotlin.propertyFiles.propertyFileUsagesByRef.2") String key, Object... args) {
|
||||
return key;
|
||||
}
|
||||
|
||||
void test() {
|
||||
message("foo.bar");
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
foo.bar = test
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.jetbrains.annotations
|
||||
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.FIELD)
|
||||
public annotation class PropertyKey(public val resourceBundle: String)
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
[propertyFileUsagesByRef.0.kt] Usage in string constants (5: 51) public fun message(@PropertyKey(resourceBundle = "idea.testData.findUsages.kotlin.propertyFiles.propertyFileUsagesByRef.2") key: String) = key
|
||||
[propertyFileUsagesByRef.1.java] Method parameter declaration (4: 58) static String message(@PropertyKey(resourceBundle = "idea.testData.findUsages.kotlin.propertyFiles.propertyFileUsagesByRef.2") String key, Object... args) {
|
||||
@@ -0,0 +1,9 @@
|
||||
// PSI_ELEMENT: com.intellij.lang.properties.psi.Property
|
||||
// FIND_BY_REF
|
||||
import org.jetbrains.annotations.PropertyKey
|
||||
|
||||
public fun message(@PropertyKey(resourceBundle = "idea.testData.findUsages.kotlin.propertyFiles.propertyUsagesByRef.2") key: String) = key
|
||||
|
||||
fun test() {
|
||||
message("<caret>foo.bar")
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class A {
|
||||
void test() {
|
||||
PropertyUsages_1Kt.message("foo.bar");
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
foo.bar = test
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.jetbrains.annotations
|
||||
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.FIELD)
|
||||
public annotation class PropertyKey(public val resourceBundle: String)
|
||||
@@ -0,0 +1,2 @@
|
||||
[propertyUsagesByRef.0.kt] Usage in string constants (8: 14) message("foo.bar")
|
||||
[propertyUsagesByRef.1.java] Usage in string constants (3: 37) PropertyUsages_1Kt.message("foo.bar");
|
||||
@@ -0,0 +1,2 @@
|
||||
## FIND_FILE_USAGES
|
||||
foo.bar = test
|
||||
@@ -0,0 +1,10 @@
|
||||
import org.jetbrains.annotations.PropertyKey
|
||||
|
||||
private val BUNDLE_NAME = "idea.testData.findUsages.propertyFiles.propertyFileUsages.0"
|
||||
|
||||
public fun message(@PropertyKey(resourceBundle = "idea.testData.findUsages.propertyFiles.propertyFileUsages.0") key: String) = key
|
||||
public fun message2(@PropertyKey(resourceBundle = BUNDLE_NAME) key: String) = key
|
||||
|
||||
fun test() {
|
||||
message("foo.bar")
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.jetbrains.annotations
|
||||
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.FIELD)
|
||||
public annotation class PropertyKey(public val resourceBundle: String)
|
||||
@@ -0,0 +1,2 @@
|
||||
Usage in string constants (3: 28) private val BUNDLE_NAME = "idea.testData.findUsages.propertyFiles.propertyFileUsages.0"
|
||||
Usage in string constants (5: 51) public fun message(@PropertyKey(resourceBundle = "idea.testData.findUsages.propertyFiles.propertyFileUsages.0") key: String) = key
|
||||
@@ -0,0 +1 @@
|
||||
foo<caret>.bar = test
|
||||
@@ -0,0 +1,30 @@
|
||||
import org.jetbrains.annotations.PropertyKey
|
||||
|
||||
public fun message(@PropertyKey(resourceBundle = "idea.testData.findUsages.propertyFiles.propertyUsages.0") key: String) = key
|
||||
|
||||
public fun String.infixMessage(@PropertyKey(resourceBundle = "idea.testData.findUsages.propertyFiles.propertyUsages.0") key: String) = key
|
||||
|
||||
public fun @receiver:PropertyKey(resourceBundle = "idea.testData.findUsages.propertyFiles.propertyUsages.0") String.infixMessage2(s: String) = this
|
||||
|
||||
public fun @receiver:PropertyKey(resourceBundle = "idea.testData.findUsages.propertyFiles.propertyUsages.0") String.minus() = this
|
||||
|
||||
public fun Int.get(@PropertyKey(resourceBundle = "idea.testData.findUsages.propertyFiles.propertyUsages.0") key: String) = this
|
||||
|
||||
public fun @receiver:PropertyKey(resourceBundle = "idea.testData.findUsages.propertyFiles.propertyUsages.0") String.get(s: String) = this
|
||||
|
||||
fun test() {
|
||||
@PropertyKey(resourceBundle = "idea.testData.findUsages.propertyFiles.propertyUsages.0") val s1 = "foo.bar"
|
||||
@PropertyKey(resourceBundle = "idea.testData.findUsages.propertyFiles.propertyUsages.0") val s2 = "foo.baz"
|
||||
message("foo.bar")
|
||||
message("foo.baz")
|
||||
|
||||
"test" infixMessage "foo.bar"
|
||||
"foo.bar" infixMessage "test"
|
||||
"foo.bar" infixMessage2 "test"
|
||||
"test" infixMessage2 "foo.bar"
|
||||
"foo.bar".infixMessage2("test")
|
||||
-"foo.bar"
|
||||
1["foo.bar"]
|
||||
"foo.bar"["test"]
|
||||
"test"["foo.bar"]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class A {
|
||||
void test() {
|
||||
@PropertyKey(resourceBundle = "idea.testData.findUsages.propertyFiles.propertyUsages.0") String s1 = "foo.bar"
|
||||
@PropertyKey(resourceBundle = "idea.testData.findUsages.propertyFiles.propertyUsages.0") String s2 = "foo.baz"
|
||||
PropertyUsages_1Kt.message("foo.bar");
|
||||
PropertyUsages_1Kt.message("foo.baz");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.jetbrains.annotations
|
||||
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.FIELD)
|
||||
public annotation class PropertyKey(public val resourceBundle: String)
|
||||
@@ -0,0 +1,10 @@
|
||||
[propertyUsages.1.kt] Usage in string constants (16: 104) @PropertyKey(resourceBundle = "idea.testData.findUsages.propertyFiles.propertyUsages.0") val s1 = "foo.bar"
|
||||
[propertyUsages.1.kt] Usage in string constants (18: 14) message("foo.bar")
|
||||
[propertyUsages.1.kt] Usage in string constants (21: 26) "test" infixMessage "foo.bar"
|
||||
[propertyUsages.1.kt] Usage in string constants (23: 6) "foo.bar" infixMessage2 "test"
|
||||
[propertyUsages.1.kt] Usage in string constants (25: 6) "foo.bar".infixMessage2("test")
|
||||
[propertyUsages.1.kt] Usage in string constants (26: 7) -"foo.bar"
|
||||
[propertyUsages.1.kt] Usage in string constants (27: 8) 1["foo.bar"]
|
||||
[propertyUsages.1.kt] Usage in string constants (28: 6) "foo.bar"["test"]
|
||||
[propertyUsages.2.java] Usage in string constants (3: 111) @PropertyKey(resourceBundle = "idea.testData.findUsages.propertyFiles.propertyUsages.0") String s1 = "foo.bar"
|
||||
[propertyUsages.2.java] Usage in string constants (5: 37) PropertyUsages_1Kt.message("foo.bar");
|
||||
@@ -22,11 +22,12 @@ import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.intellij.codeInsight.JavaTargetElementEvaluator;
|
||||
import com.intellij.codeInsight.TargetElementUtil;
|
||||
import com.intellij.codeInsight.TargetElementUtilBase;
|
||||
import com.intellij.find.FindManager;
|
||||
import com.intellij.find.findUsages.*;
|
||||
import com.intellij.find.impl.FindManagerImpl;
|
||||
import com.intellij.lang.properties.psi.PropertiesFile;
|
||||
import com.intellij.lang.properties.psi.Property;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
@@ -296,11 +297,21 @@ public abstract class AbstractJetFindUsagesTest extends JetLightCodeInsightFixtu
|
||||
String mainFileText = FileUtil.loadFile(mainFile, true);
|
||||
final String prefix = mainFileName.substring(0, mainFileName.indexOf('.') + 1);
|
||||
|
||||
List<String> caretElementClassNames = InTextDirectivesUtils.findLinesWithPrefixesRemoved(mainFileText, "// PSI_ELEMENT: ");
|
||||
assert caretElementClassNames.size() == 1;
|
||||
//noinspection unchecked
|
||||
boolean isPropertiesFile = FileUtilRt.getExtension(path).equals("properties");
|
||||
|
||||
Class<T> caretElementClass = (Class<T>)Class.forName(caretElementClassNames.get(0));
|
||||
Class<T> caretElementClass;
|
||||
if (!isPropertiesFile) {
|
||||
List<String> caretElementClassNames = InTextDirectivesUtils.findLinesWithPrefixesRemoved(mainFileText, "// PSI_ELEMENT: ");
|
||||
assert caretElementClassNames.size() == 1;
|
||||
//noinspection unchecked
|
||||
caretElementClass = (Class<T>)Class.forName(caretElementClassNames.get(0));
|
||||
}
|
||||
else {
|
||||
//noinspection unchecked
|
||||
caretElementClass = (Class<T>) (InTextDirectivesUtils.isDirectiveDefined(mainFileText, "## FIND_FILE_USAGES")
|
||||
? PropertiesFile.class
|
||||
: Property.class);
|
||||
}
|
||||
|
||||
OptionsParser parser = OptionsParser.getParserByPsiElementClass(caretElementClass);
|
||||
|
||||
@@ -317,6 +328,7 @@ public abstract class AbstractJetFindUsagesTest extends JetLightCodeInsightFixtu
|
||||
return ext.equals("kt")
|
||||
|| ext.equals("java")
|
||||
|| ext.equals("xml")
|
||||
|| ext.equals("properties")
|
||||
|| (ext.equals("txt") && !name.endsWith(".results.txt"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1036,6 +1036,27 @@ public class JetFindUsagesTestGenerated extends AbstractJetFindUsagesTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/findUsages/kotlin/propertyFiles")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class PropertyFiles extends AbstractJetFindUsagesTest {
|
||||
public void testAllFilesPresentInPropertyFiles() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/findUsages/kotlin/propertyFiles"), Pattern.compile("^(.+)\\.0\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyFileUsagesByRef.0.kt")
|
||||
public void testPropertyFileUsagesByRef() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/propertyFiles/propertyFileUsagesByRef.0.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyUsagesByRef.0.kt")
|
||||
public void testPropertyUsagesByRef() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/propertyFiles/propertyUsagesByRef.0.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/findUsages/kotlin/unresolvedAnnotation")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -1315,4 +1336,25 @@ public class JetFindUsagesTestGenerated extends AbstractJetFindUsagesTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/findUsages/propertyFiles")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class PropertyFiles extends AbstractJetFindUsagesTest {
|
||||
public void testAllFilesPresentInPropertyFiles() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/findUsages/propertyFiles"), Pattern.compile("^(.+)\\.0\\.properties$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyFileUsages.0.properties")
|
||||
public void testPropertyFileUsages() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/propertyFiles/propertyFileUsages.0.properties");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyUsages.0.properties")
|
||||
public void testPropertyUsages() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/findUsages/propertyFiles/propertyUsages.0.properties");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user