From 4c7eca583963c6a830f631067058c82d8cb8b982 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 30 Jun 2014 21:22:47 +0200 Subject: [PATCH] IDEA-126595 provide completion variants for Charset.forName() --- .../impl/JavaCharsetReferenceContributor.java | 52 +++++++++ .../completion/normal/CharsetName.java | 7 ++ .../completion/NormalCompletionTest.groovy | 6 + .../analysis/encoding/EncodingReference.java | 103 ++++++++++++++++++ resources/src/META-INF/IdeaPlugin.xml | 1 + .../com/intellij/spellchecker/jetbrains.dic | 1 + .../encoding/XmlEncodingReference.java | 77 +------------ 7 files changed, 172 insertions(+), 75 deletions(-) create mode 100644 java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaCharsetReferenceContributor.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/CharsetName.java create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/EncodingReference.java diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaCharsetReferenceContributor.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaCharsetReferenceContributor.java new file mode 100644 index 000000000000..db1a385d5137 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaCharsetReferenceContributor.java @@ -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; + } + }); + } +} diff --git a/java/java-tests/testData/codeInsight/completion/normal/CharsetName.java b/java/java-tests/testData/codeInsight/completion/normal/CharsetName.java new file mode 100644 index 000000000000..c932c81751d6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/CharsetName.java @@ -0,0 +1,7 @@ +import java.nio.charset.Charset; + +public final class FileAttributes { + { + Charset.forName("utf") + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 16132567de64..79a94aaa8148 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -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> { public static class Inner {} }" myFixture.configureFromExistingVirtualFile(myFixture.addClass(text).containingFile.virtualFile) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/EncodingReference.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/EncodingReference.java new file mode 100644 index 000000000000..d3f0da5e5d0f --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/EncodingReference.java @@ -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 suggestions = new ArrayList(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; + } + +} diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 4c8b217d526d..329fc3def69f 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -1471,6 +1471,7 @@ implementationClass="com.intellij.psi.impl.JavaRegExpHost"/> + diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic index 6ac3516a8b37..71cb555d1838 100644 --- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic +++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic @@ -57,6 +57,7 @@ cdata cglib changelist charset +charsets checkbox checkboxes checksum diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/XmlEncodingReference.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/XmlEncodingReference.java index d6ab939090fe..3515297f31de 100644 --- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/XmlEncodingReference.java +++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/XmlEncodingReference.java @@ -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 { - private final XmlAttributeValue myValue; - - private final String myCharsetName; - private final TextRange myRangeInElement; +public class XmlEncodingReference extends EncodingReference implements EmptyResolveMessageProvider, Comparable { 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 suggestions = new ArrayList(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;