Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Jemerov
2012-07-02 19:43:27 +02:00
61 changed files with 990 additions and 327 deletions
@@ -1,62 +0,0 @@
/*
* Copyright 2000-2010 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.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.Consumer;
/**
* @author nik
*/
public abstract class AbstractBasicToClassNameDelegator extends CompletionContributor {
protected abstract boolean isClassNameCompletionSupported(CompletionResultSet result, PsiFile file, PsiElement position);
protected void updateProperties(LookupElement lookupElement) {
}
@Override
public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
if (parameters.getCompletionType() != CompletionType.BASIC || parameters.getInvocationCount() == 0) return;
final PsiFile file = parameters.getOriginalFile();
final PsiElement position = parameters.getPosition();
if (!isClassNameCompletionSupported(result, file, position)) return;
final boolean empty = result.runRemainingContributors(parameters, true).isEmpty();
final CompletionParameters classParams;
final int invocationCount = parameters.getInvocationCount();
if (empty) {
classParams = parameters.withType(CompletionType.CLASS_NAME);
}
else if (invocationCount > 1) {
classParams = parameters.withType(CompletionType.CLASS_NAME).withInvocationCount(invocationCount - 1);
} else {
return;
}
CompletionService.getCompletionService().getVariantsFromContributors(classParams, null, new Consumer<CompletionResult>() {
public void consume(final CompletionResult lookupElement) {
updateProperties(lookupElement.getLookupElement());
result.passResult(lookupElement);
}
});
}
}
@@ -22,6 +22,7 @@ import com.intellij.lang.LangBundle;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileTypes.impl.CustomSyntaxTableFileType;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.PsiJavaElementPattern;
@@ -30,7 +31,6 @@ import com.intellij.psi.filters.ClassFilter;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.filters.TrueFilter;
import com.intellij.psi.filters.element.ExcludeDeclaredFilter;
import com.intellij.psi.filters.types.AssignableFromFilter;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Consumer;
@@ -52,10 +52,10 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
@Override
public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet _result) {
if (parameters.isExtendedCompletion()) {
if (parameters.getCompletionType() == CompletionType.CLASS_NAME ||
parameters.isExtendedCompletion() && mayContainClassName(parameters)) {
CompletionResultSet result = _result.withPrefixMatcher(CompletionUtil.findReferenceOrAlphanumericPrefix(parameters));
addAllClasses(parameters, parameters.getInvocationCount() <= 1,
JavaCompletionSorting.addJavaSorting(parameters, result).getPrefixMatcher(), new Consumer<LookupElement>() {
addAllClasses(parameters, parameters.getInvocationCount() <= 1, result.getPrefixMatcher(), new Consumer<LookupElement>() {
@Override
public void consume(LookupElement element) {
_result.addElement(element);
@@ -64,28 +64,29 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
}
}
private static boolean mayContainClassName(CompletionParameters parameters) {
PsiElement position = parameters.getPosition();
PsiFile file = position.getContainingFile();
if (file instanceof PsiPlainTextFile || file.getFileType() instanceof CustomSyntaxTableFileType) {
return true;
}
if (SkipAutopopupInStrings.isInStringLiteral(position)) {
return true;
}
if (PsiTreeUtil.getParentOfType(position, PsiComment.class, false) != null) {
return true;
}
return false;
}
public static void addAllClasses(CompletionParameters parameters,
final boolean filterByScope,
@NotNull final PrefixMatcher matcher,
@NotNull final Consumer<LookupElement> consumer) {
final PsiElement insertedElement = parameters.getPosition();
final ElementFilter filter;
if (JavaSmartCompletionContributor.AFTER_THROW_NEW.accepts(insertedElement) ||
JavaCompletionContributor.INSIDE_METHOD_THROWS_CLAUSE.accepts(insertedElement) ||
JavaCompletionContributor.IN_CATCH_TYPE.accepts(insertedElement) ||
JavaCompletionContributor.IN_MULTI_CATCH_TYPE.accepts(insertedElement)) {
filter = new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE);
}
else if (JavaCompletionContributor.IN_RESOURCE_TYPE.accepts(insertedElement)) {
filter = new AssignableFromFilter(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE);
}
else if (IN_TYPE_PARAMETER.accepts(insertedElement)) {
filter = new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class));
}
else {
filter = TrueFilter.INSTANCE;
}
final ElementFilter filter =
IN_TYPE_PARAMETER.accepts(insertedElement) ? new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class)) : TrueFilter.INSTANCE;
final boolean inJavaContext = parameters.getPosition() instanceof PsiIdentifier;
final boolean afterNew = AFTER_NEW.accepts(insertedElement);
@@ -107,13 +108,10 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
}
}
final boolean lookingForAnnotations = psiElement().afterLeaf("@").accepts(insertedElement);
final boolean pkgContext = JavaCompletionUtil.inSomePackage(insertedElement);
AllClassesGetter.processJavaClasses(parameters, matcher, filterByScope, new Consumer<PsiClass>() {
@Override
public void consume(PsiClass psiClass) {
if (lookingForAnnotations && !psiClass.isAnnotationType()) return;
if (filter.isAcceptable(psiClass, insertedElement)) {
if (!inJavaContext) {
consumer.consume(AllClassesGetter.createLookupItem(psiClass, AllClassesGetter.TRY_SHORTENING));
@@ -179,8 +177,8 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
}
private static boolean shouldShowSecondSmartCompletionHint(final CompletionParameters parameters) {
return parameters.getCompletionType() == CompletionType.CLASS_NAME &&
parameters.getInvocationCount() == 1 &&
return parameters.getCompletionType() == CompletionType.BASIC &&
parameters.getInvocationCount() == 2 &&
parameters.getOriginalFile().getLanguage().isKindOf(JavaLanguage.INSTANCE);
}
}
@@ -19,27 +19,41 @@ import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.lang.StdLanguages;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.Consumer;
/**
* @author peter
*/
public class XmlBasicToClassNameDelegator extends AbstractBasicToClassNameDelegator {
public class XmlBasicToClassNameDelegator extends CompletionContributor {
@Override
protected boolean isClassNameCompletionSupported(CompletionResultSet result, PsiFile file, PsiElement position) {
if (!JavaCompletionContributor.mayStartClassName(result)) return false;
public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) {
PsiElement position = parameters.getPosition();
if (parameters.getCompletionType() != CompletionType.BASIC ||
!JavaCompletionContributor.mayStartClassName(result) ||
!position.getContainingFile().getLanguage().isKindOf(StdLanguages.XML)) {
return;
}
return file.getLanguage().isKindOf(StdLanguages.XML);
}
final boolean empty = result.runRemainingContributors(parameters, true).isEmpty();
@Override
protected void updateProperties(LookupElement lookupElement) {
JavaPsiClassReferenceElement classElement = lookupElement.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
if (classElement != null) {
classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
if (!empty && parameters.getInvocationCount() == 0) {
result.restartCompletionWhenNothingMatches();
}
if (empty || parameters.isExtendedCompletion()) {
CompletionService.getCompletionService().getVariantsFromContributors(parameters.delegateToClassName(), null, new Consumer<CompletionResult>() {
public void consume(final CompletionResult completionResult) {
LookupElement lookupElement = completionResult.getLookupElement();
JavaPsiClassReferenceElement classElement = lookupElement.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
if (classElement != null) {
classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
}
lookupElement.putUserData(XmlCompletionContributor.WORD_COMPLETION_COMPATIBLE, Boolean.TRUE); //todo think of a less dirty interaction
result.passResult(completionResult);
}
});
}
lookupElement.putUserData(XmlCompletionContributor.WORD_COMPLETION_COMPATIBLE, Boolean.TRUE); //todo think of a less dirty interaction
}
}
@@ -17,13 +17,20 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightMethodUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.impl.PriorityIntentionActionWrapper;
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider<PsiJavaCodeReferenceElement> {
@Override
public void registerFixes(PsiJavaCodeReferenceElement ref, QuickFixActionRegistrar registrar) {
@@ -37,15 +44,13 @@ public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider
PsiReferenceExpression refExpr = (PsiReferenceExpression)ref;
registrar.register(fixRange, new CreateEnumConstantFromUsageFix(refExpr), null);
registrar.register(fixRange, new CreateConstantFieldFromUsageFix(refExpr), null);
registrar.register(fixRange, new CreateFieldFromUsageFix(refExpr), null);
registrar.register(new RenameWrongRefFix(refExpr));
if (!ref.isQualified()) {
registrar.register(fixRange, new BringVariableIntoScopeFix(refExpr), null);
registrar.register(fixRange, new CreateLocalFromUsageFix(refExpr), null);
registrar.register(fixRange, new CreateParameterFromUsageFix(refExpr), null);
}
registerPriorityActions(registrar,fixRange,refExpr);
}
registrar.register(new CreateClassFromUsageFix(ref, CreateClassKind.INTERFACE));
@@ -65,6 +70,57 @@ public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider
}
}
private static void registerPriorityActions(@NotNull final QuickFixActionRegistrar registrar,
@NotNull final TextRange fixRange,
@NotNull final PsiReferenceExpression refExpr) {
final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(refExpr.getProject());
final Map<VariableKind, IntentionAction> map = new HashMap<VariableKind, IntentionAction>() {
{
put(VariableKind.FIELD, new CreateFieldFromUsageFix(refExpr));
put(VariableKind.STATIC_FINAL_FIELD, new CreateConstantFieldFromUsageFix(refExpr));
if (!refExpr.isQualified()) {
put(VariableKind.LOCAL_VARIABLE, new CreateLocalFromUsageFix(refExpr));
put(VariableKind.PARAMETER, new CreateParameterFromUsageFix(refExpr));
}
}
};
final VariableKind kind = getKind(styleManager, refExpr);
if (map.containsKey(kind)){
map.put(kind, PriorityIntentionActionWrapper.highPriority(map.get(kind)));
}
for (IntentionAction action : map.values()){
registrar.register(fixRange, action, null);
}
}
@NotNull
private static VariableKind getKind(@NotNull JavaCodeStyleManager styleManager,
@NotNull PsiReferenceExpression refExpr) {
final String reference = refExpr.getText();
if (reference.toUpperCase().equals(reference)){
return VariableKind.STATIC_FINAL_FIELD;
}
for (VariableKind kind : VariableKind.values()) {
final String prefix = styleManager.getPrefixByVariableKind(kind);
final String suffix = styleManager.getSuffixByVariableKind(kind);
if (prefix.isEmpty() && suffix.isEmpty()) {
continue;
}
if (reference.startsWith(prefix) && reference.endsWith(suffix)) {
return kind;
}
}
return VariableKind.LOCAL_VARIABLE;
}
@Override
@NotNull
public Class<PsiJavaCodeReferenceElement> getReferenceClass() {
@@ -55,7 +55,7 @@ public class FileEqualsUsageInspection extends InternalInspection {
if (clazz == null) return;
String methodName = method.getName();
if ("java.io.File".equals(clazz.getQualifiedName())
if (CommonClassNames.JAVA_IO_FILE.equals(clazz.getQualifiedName())
&& ("equals".equals(methodName) || "compareTo".equals(methodName) || "hashCode".equals(methodName))) {
holder.registerProblem(methodExpression,
"Do not use File.equals/hashCode/compareTo as they don't honor case-sensitivity on MacOS. Use FileUtil.filesEquals/fileHashCode/compareFiles instead",
@@ -87,4 +87,5 @@ public interface CommonClassNames {
@NonNls String JAVA_LANG_INVOKE_MH_POLYMORPHIC = "java.lang.invoke.MethodHandle.PolymorphicSignature";
String TARGET_ANNOTATION_FQ_NAME = "java.lang.annotation.Target";
@NonNls String JAVA_LANG_RUNNABLE = "java.lang.Runnable";
@NonNls String JAVA_IO_FILE = "java.io.File";
}
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
@@ -64,6 +65,7 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase {
String path = "/afterNewThrowable";
configureByFile(path + "/before1.java");
myFixture.type('\n');
checkResultByFile(path + "/after1.java");
}
@@ -80,6 +82,7 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase {
String path = "/afterNewThrowable";
configureByFile(path + "/before2.java");
myFixture.type('\n');
checkResultByFile(path + "/after2.java");
}
@@ -94,6 +97,12 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase {
checkResultByFile(getTestName(false) + "_after.txt");
}
public void testInPropertiesFile() throws Exception {
myFixture.configureByText("a.properties", "abc = StrinBui<caret>");
complete();
myFixture.checkResult("abc = java.lang.StringBuilder<caret>");
}
public void testDoubleStringBuffer() throws Exception {
createClass("package java.lang; public class StringBuffer {}");
doTest();
@@ -198,6 +207,7 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase {
private void cleanupVfs() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
FileDocumentManager.getInstance().saveAllDocuments();
for (VirtualFile file : myFixture.getTempDirFixture().getFile("").getChildren()) {
try {
file.delete(this);