properties: rewrite fix for IDEA-97844. associate string literal in field with properties file

This commit is contained in:
Dmitry Batkovich
2016-09-02 14:33:49 +03:00
parent 58d7b4a6dd
commit 847c24ecb1
4 changed files with 91 additions and 19 deletions
@@ -17,17 +17,18 @@ package com.intellij.lang.properties;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.lang.properties.psi.impl.PropertyValueImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.patterns.PsiJavaPatterns;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.AnnotatedElementsSearch;
import com.intellij.util.ProcessingContext;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;
import java.util.List;
import static com.intellij.patterns.PsiJavaPatterns.literalExpression;
import static com.intellij.patterns.PsiJavaPatterns.psiNameValuePair;
@@ -36,6 +37,7 @@ import static com.intellij.patterns.PsiJavaPatterns.psiNameValuePair;
* @author peter
*/
public class PropertiesReferenceContributor extends PsiReferenceContributor{
private static final Logger LOG = Logger.getInstance(PropertiesReferenceContributor.class);
private static final JavaClassReferenceProvider CLASS_REFERENCE_PROVIDER = new JavaClassReferenceProvider() {
public boolean isSoft() {
@@ -63,24 +65,26 @@ public class PropertiesReferenceContributor extends PsiReferenceContributor{
if (field.getInitializer() != element || !field.hasModifierProperty(PsiModifier.FINAL)) {
return PsiReference.EMPTY_ARRAY;
}
Set<PsiReference> references = new THashSet<>(TObjectHashingStrategy.IDENTITY);
for (PsiMethod method : PsiTreeUtil.findChildrenOfType(element.getContainingFile(), PsiMethod.class)) {
for (PsiParameter parameter : method.getParameterList().getParameters()) {
final PsiModifierList modifierList = parameter.getModifierList();
if (modifierList != null) {
final PsiAnnotation annotation = modifierList.findAnnotation(AnnotationUtil.PROPERTY_KEY);
if (annotation != null) {
for (PsiNameValuePair pair : annotation.getParameterList().getAttributes()) {
if (AnnotationUtil.PROPERTY_KEY_RESOURCE_BUNDLE_PARAMETER.equals(pair.getName())) {
final PsiAnnotationMemberValue value = pair.getValue();
if (value instanceof PsiReferenceExpression && ((PsiReferenceExpression)value).resolve() == field) {
Collections.addAll(references, myUnderlying.getReferencesByElement(element, context));
}
List<PsiReference> references = new ArrayList<>();
final PsiClass propertyKeyAnnotation =
JavaPsiFacade.getInstance(element.getProject()).findClass(AnnotationUtil.PROPERTY_KEY, element.getResolveScope());
if (propertyKeyAnnotation != null) {
AnnotatedElementsSearch.searchPsiParameters(propertyKeyAnnotation, new LocalSearchScope(element.getContainingFile()))
.forEach(parameter -> {
final PsiModifierList list = parameter.getModifierList();
LOG.assertTrue(list != null);
final PsiAnnotation annotation = list.findAnnotation(AnnotationUtil.PROPERTY_KEY);
LOG.assertTrue(annotation != null);
for (PsiNameValuePair pair : annotation.getParameterList().getAttributes()) {
if (AnnotationUtil.PROPERTY_KEY_RESOURCE_BUNDLE_PARAMETER.equals(pair.getName())) {
final PsiAnnotationMemberValue value = pair.getValue();
if (value instanceof PsiReferenceExpression && ((PsiReferenceExpression)value).resolve() == field) {
Collections.addAll(references, myUnderlying.getReferencesByElement(element, context));
}
}
}
}
}
return true;
});
}
return references.toArray(new PsiReference[references.size()]);
}
@@ -0,0 +1,16 @@
import org.jetbrains.annotations.PropertyKey;
import java.util.ResourceBundle;
public class MyClass {
private final static String BUNDLE_NAME = "i18n";
private final static ResourceBundle BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
public static void main(String[] args) {
System.out.print(getMessage("com.example.localization.welcomeMessage"));
}
private static String getMessage(@PropertyKey(resourceBundle = BUNDLE_NAME) String key) {
return BUNDLE.getString(key);
}
}
@@ -0,0 +1 @@
com.example.localization.welcomeMessage=Welcome to our App!
@@ -0,0 +1,51 @@
/*
* 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 com.intellij.codeInspection;
import com.intellij.openapi.application.PluginPathManager;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.*;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
public class PropertiesFileRenameReferenceTest extends LightCodeInsightFixtureTestCase {
@Override
protected String getBasePath() {
return PluginPathManager.getPluginHomePathRelative("java-i18n") + "/testData/rename";
}
public void testRenamePropertiesFile() {
final PsiFile[] files = myFixture.configureByFiles("i18n.properties", "MyClass.java");
final PsiFile propertiesFile = files[0];
final PsiFile javaSourceFile = files[1];
myFixture.renameElement(propertiesFile, "i19n.properties");
boolean[] found = {false};
PsiTreeUtil.processElements(javaSourceFile, new PsiElementProcessor() {
@Override
public boolean execute(@NotNull PsiElement element) {
if (PlatformPatterns.psiElement(PsiField.class).withName("BUNDLE_NAME").accepts(element)) {
assertEquals("i19n", ((PsiLiteralExpression)((PsiField)element).getInitializer()).getValue());
found[0] = true;
}
return true;
}
});
assertTrue(found[0]);
}
}