IDEA-126595 provide completion variants for Charset.forName()

This commit is contained in:
peter
2014-06-30 21:59:56 +02:00
parent ffc5d47e85
commit 4c7eca5839
7 changed files with 172 additions and 75 deletions
@@ -0,0 +1,52 @@
/*
* 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.
*/
package com.intellij.psi.impl.source.resolve.reference.impl;
import com.intellij.codeInsight.daemon.impl.analysis.encoding.EncodingReference;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.manipulators.StringLiteralManipulator;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import java.nio.charset.Charset;
import static com.intellij.patterns.PsiJavaPatterns.literalExpression;
import static com.intellij.patterns.PsiJavaPatterns.psiMethod;
import static com.intellij.patterns.StandardPatterns.string;
/**
* @author peter
*/
public class JavaCharsetReferenceContributor extends PsiReferenceContributor {
@Override
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
registrar.registerReferenceProvider(
literalExpression().methodCallParameter(
0, psiMethod().withName(string().oneOf("forName", "isSupported")).inClass(Charset.class.getName())),
new PsiReferenceProvider() {
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
PsiLiteralExpression literal = (PsiLiteralExpression)element;
Object value = literal.getValue();
if (value instanceof String) {
return new PsiReference[]{new EncodingReference(element, (String)value, StringLiteralManipulator.getValueRange(literal))};
}
return PsiReference.EMPTY_ARRAY;
}
});
}
}
@@ -0,0 +1,7 @@
import java.nio.charset.Charset;
public final class FileAttributes {
{
Charset.forName("utf<caret>")
}
}
@@ -1216,6 +1216,12 @@ class XInternalError {}
public void testConstantInAnno() { doTest() }
public void testCharsetName() {
myFixture.addClass("package java.nio.charset; public class Charset { public static Charset forName(String s) {} }")
configureByTestName()
assert myFixture.lookupElementStrings.contains('UTF-8')
}
public void testInnerClassInExtendsGenerics() {
def text = "package bar; class Foo extends List<Inne<caret>> { public static class Inner {} }"
myFixture.configureFromExistingVirtualFile(myFixture.addClass(text).containingFile.virtualFile)
@@ -0,0 +1,103 @@
/*
* 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.
*/
package com.intellij.codeInsight.daemon.impl.analysis.encoding;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* @author peter
*/
public class EncodingReference implements PsiReference {
private final PsiElement myElement;
private final String myCharsetName;
private final TextRange myRangeInElement;
public EncodingReference(PsiElement element, final String charsetName, final TextRange rangeInElement) {
myElement = element;
myCharsetName = charsetName;
myRangeInElement = rangeInElement;
}
@Override
public PsiElement getElement() {
return myElement;
}
@Override
public TextRange getRangeInElement() {
return myRangeInElement;
}
@Override
@Nullable
public PsiElement resolve() {
return CharsetToolkit.forName(myCharsetName) == null ? null : myElement;
//if (ApplicationManager.getApplication().isUnitTestMode()) return myValue; // tests do not have full JDK
//String fqn = charset.getClass().getName();
//return myValue.getManager().findClass(fqn, GlobalSearchScope.allScope(myValue.getProject()));
}
@Override
@NotNull
public String getCanonicalText() {
return myCharsetName;
}
@Override
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
return null;
}
@Override
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
return null;
}
@Override
public boolean isReferenceTo(PsiElement element) {
return false;
}
@Override
@NotNull
public Object[] getVariants() {
Charset[] charsets = CharsetToolkit.getAvailableCharsets();
List<LookupElement> suggestions = new ArrayList<LookupElement>(charsets.length);
for (Charset charset : charsets) {
suggestions.add(LookupElementBuilder.create(charset.name()).withCaseSensitivity(false));
}
return suggestions.toArray(new LookupElement[suggestions.size()]);
}
@Override
public boolean isSoft() {
return false;
}
}
+1
View File
@@ -1471,6 +1471,7 @@
implementationClass="com.intellij.psi.impl.JavaRegExpHost"/>
<psi.referenceContributor language="JAVA" implementation="com.intellij.psi.impl.source.resolve.reference.impl.JavaReflectionReferenceContributor"/>
<psi.referenceContributor language="JAVA" implementation="com.intellij.psi.impl.source.resolve.reference.impl.JavaCharsetReferenceContributor"/>
<writingAccessProvider implementation="com.intellij.refactoring.util.ClsElementWritingAccessProvider"/>
@@ -57,6 +57,7 @@ cdata
cglib
changelist
charset
charsets
checkbox
checkboxes
checksum
@@ -17,57 +17,21 @@ package com.intellij.codeInsight.daemon.impl.analysis.encoding;
import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
import com.intellij.codeInsight.daemon.XmlErrorMessages;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* @author cdr
*/
public class XmlEncodingReference implements PsiReference, EmptyResolveMessageProvider, Comparable<XmlEncodingReference> {
private final XmlAttributeValue myValue;
private final String myCharsetName;
private final TextRange myRangeInElement;
public class XmlEncodingReference extends EncodingReference implements EmptyResolveMessageProvider, Comparable<XmlEncodingReference> {
private final int myPriority;
public XmlEncodingReference(XmlAttributeValue value, final String charsetName, final TextRange rangeInElement, int priority) {
myValue = value;
myCharsetName = charsetName;
myRangeInElement = rangeInElement;
super(value, charsetName, rangeInElement);
myPriority = priority;
}
@Override
public PsiElement getElement() {
return myValue;
}
@Override
public TextRange getRangeInElement() {
return myRangeInElement;
}
@Override
@Nullable
public PsiElement resolve() {
return CharsetToolkit.forName(myCharsetName) == null ? null : myValue;
//if (ApplicationManager.getApplication().isUnitTestMode()) return myValue; // tests do not have full JDK
//String fqn = charset.getClass().getName();
//return myValue.getManager().findClass(fqn, GlobalSearchScope.allScope(myValue.getProject()));
}
@Override
@NotNull
public String getUnresolvedMessagePattern() {
@@ -75,43 +39,6 @@ public class XmlEncodingReference implements PsiReference, EmptyResolveMessagePr
return XmlErrorMessages.message("unknown.encoding.0");
}
@Override
@NotNull
public String getCanonicalText() {
return myCharsetName;
}
@Override
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
return null;
}
@Override
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
return null;
}
@Override
public boolean isReferenceTo(PsiElement element) {
return false;
}
@Override
@NotNull
public Object[] getVariants() {
Charset[] charsets = CharsetToolkit.getAvailableCharsets();
List<LookupElement> suggestions = new ArrayList<LookupElement>(charsets.length);
for (Charset charset : charsets) {
suggestions.add(LookupElementBuilder.create(charset.name()).withCaseSensitivity(false));
}
return suggestions.toArray(new LookupElement[suggestions.size()]);
}
@Override
public boolean isSoft() {
return false;
}
@Override
public int compareTo(@NotNull XmlEncodingReference ref) {
return myPriority - ref.myPriority;