diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2013-04-01 14:41:51 -0700 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2013-04-01 14:41:51 -0700 |
commit | 2bd2b7c2623d4266384e890271869efc044aabff (patch) | |
tree | 0b31f50e55975b6354ed458314e17b4441bb4e17 /java/java-impl/src | |
parent | 1d526b16d476792ca7ce47616d55833115e8d6ab (diff) | |
download | idea-2bd2b7c2623d4266384e890271869efc044aabff.tar.gz |
Snapshot ee98b298267d0e09d2cd2f0731b6480a56dd48e7 from master branch of git://git.jetbrains.org/idea/community.git
Change-Id: I4515f72af131fdea9fc6905a4dc0fe9532409a81
Diffstat (limited to 'java/java-impl/src')
84 files changed, 1313 insertions, 1176 deletions
diff --git a/java/java-impl/src/com/intellij/codeInsight/ConditionCheckManager.java b/java/java-impl/src/com/intellij/codeInsight/ConditionCheckManager.java index b9be30108002..f7edb1e3b250 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ConditionCheckManager.java +++ b/java/java-impl/src/com/intellij/codeInsight/ConditionCheckManager.java @@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiMethod; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -30,7 +31,10 @@ import java.util.List; */ @State( name = "ConditionCheckManager", - storages = {@Storage(id = "dir", file = StoragePathMacros.PROJECT_CONFIG_DIR + "/checker.xml", scheme = StorageScheme.DIRECTORY_BASED)} + storages = { + @Storage(id = "dir", file = StoragePathMacros.PROJECT_CONFIG_DIR + "/checker.xml", scheme = StorageScheme.DIRECTORY_BASED), + @Storage(file = StoragePathMacros.PROJECT_FILE) + } ) public class ConditionCheckManager implements PersistentStateComponent<ConditionCheckManager.State> { @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) private State state; @@ -143,7 +147,7 @@ public class ConditionCheckManager implements PersistentStateComponent<Condition loadMethods(myAssertFalseMethods, state.myAssertFalseMethods, ConditionChecker.Type.ASSERT_FALSE_METHOD); } - public void loadMethods(List<ConditionChecker> listToLoadTo, List<String> listToLoadFrom, ConditionChecker.Type type){ + private static void loadMethods(List<ConditionChecker> listToLoadTo, List<String> listToLoadFrom, ConditionChecker.Type type){ listToLoadTo.clear(); for (String setting : listToLoadFrom) { try { @@ -154,86 +158,25 @@ public class ConditionCheckManager implements PersistentStateComponent<Condition } } - public static boolean isMethod(@NotNull PsiMethod psiMethod, List<ConditionChecker> checkers) { - for (ConditionChecker checker : checkers) { - if (checker.matchesPsiMethod(psiMethod)) { - return true; - } - } - return false; - } - - public static boolean isCheck(PsiMethod psiMethod) { - ConditionCheckManager manager = getInstance(psiMethod.getProject()); - return isMethod(psiMethod, manager.getIsNullCheckMethods()) || - isMethod(psiMethod, manager.getIsNotNullCheckMethods()) || - isMethod(psiMethod, manager.getAssertIsNullMethods()) || - isMethod(psiMethod, manager.getAssertIsNotNullMethods()) || - isAssertTrueCheckMethod(psiMethod) || - isAssertFalseCheckMethod(psiMethod); - } - - public static boolean isNullCheckMethod(PsiMethod psiMethod) { - return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getIsNullCheckMethods()); - } - - public static boolean isNotNullCheckMethod(PsiMethod psiMethod) { - return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getIsNotNullCheckMethods()); - } - - public static boolean isAssertIsNullCheckMethod(PsiMethod psiMethod) { - return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getAssertIsNullMethods()); - } - - public static boolean isAssertIsNotNullCheckMethod(PsiMethod psiMethod) { - return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getAssertIsNotNullMethods()); - } - - public static boolean isAssertTrueCheckMethod(PsiMethod psiMethod) { - return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getAssertTrueMethods()); - } - - public static boolean isAssertFalseCheckMethod(PsiMethod psiMethod) { - return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getAssertFalseMethods()); - } - - public static boolean isNullCheckMethod(PsiMethod psiMethod, int paramIndex) { - return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getIsNullCheckMethods()); - } - - public static boolean isNotNullCheckMethod(PsiMethod psiMethod, int paramIndex) { - return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getIsNotNullCheckMethods()); - } - - public static boolean isAssertIsNullCheckMethod(PsiMethod psiMethod, int paramIndex) { - return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getAssertIsNullMethods()); - } - - public static boolean isAssertIsNotNullCheckMethod(PsiMethod psiMethod, int paramIndex) { - return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getAssertIsNotNullMethods()); + @Nullable + public static ConditionChecker findConditionChecker(@NotNull PsiMethod method) { + ConditionCheckManager instance = getInstance(method.getProject()); + ConditionChecker checker = methodMatches(method, instance.getIsNullCheckMethods()); + if (checker == null) checker = methodMatches(method, instance.getIsNotNullCheckMethods()); + if (checker == null) checker = methodMatches(method, instance.getAssertIsNullMethods()); + if (checker == null) checker = methodMatches(method, instance.getAssertIsNotNullMethods()); + if (checker == null) checker = methodMatches(method, instance.getAssertTrueMethods()); + if (checker == null) checker = methodMatches(method, instance.getAssertFalseMethods()); + return checker; } - public static boolean isAssertTrueCheckMethod(PsiMethod psiMethod, int paramIndex) { - return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getAssertTrueMethods()); - } - - public static boolean isAssertFalseCheckMethod(PsiMethod psiMethod, int paramIndex) { - return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getAssertFalseMethods()); - } - - public static boolean methodMatches(PsiMethod psiMethod, List<ConditionChecker> checkers) { + private static ConditionChecker methodMatches(PsiMethod psiMethod, List<ConditionChecker> checkers) { for (ConditionChecker checker : checkers) { - if (checker.matchesPsiMethod(psiMethod)) - return true; + if (checker.matchesPsiMethod(psiMethod)) { + return checker; + } } - return false; + return null; } - public static boolean methodMatches(PsiMethod psiMethod, int paramIndex, List<ConditionChecker> checkers) { - for (ConditionChecker checker : checkers) { - if (checker.matchesPsiMethod(psiMethod, paramIndex)) - return true; - } - return false; - } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java index b8a5c34c3b11..a25001065d11 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java @@ -76,7 +76,7 @@ public class JavaCharFilter extends CharFilter { } - if (c == '[') return CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP; + if (c == '[' || c == ']' || c == ')' || c == '>') return CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP; if (c == '<' && o instanceof PsiClass) return Result.SELECT_ITEM_AND_FINISH_LOOKUP; if (c == '(') { if (o instanceof PsiClass) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java index 0cb06a123166..61fef1b8706e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java @@ -235,6 +235,8 @@ public class JavaCompletionContributor extends CompletionContributor { } } + JavaOverrideCompletionContributor.fillCompletionVariants(parameters, result); + addAllClasses(parameters, result, inheritors); final PsiElement parent = position.getParent(); @@ -254,8 +256,7 @@ public class JavaCompletionContributor extends CompletionContributor { public static void addAllClasses(CompletionParameters parameters, final CompletionResultSet result, final InheritorsHolder inheritors) { - if (!isClassNamePossible(parameters.getPosition()) && parameters.getInvocationCount() <= 1 || - !mayStartClassName(result)) { + if (!isClassNamePossible(parameters) || !mayStartClassName(result)) { return; } @@ -378,10 +379,12 @@ public class JavaCompletionContributor extends CompletionContributor { } } - public static boolean isClassNamePossible(final PsiElement position) { - final PsiElement parent = position.getParent(); - if (!(parent instanceof PsiJavaCodeReferenceElement)) return false; - if (((PsiJavaCodeReferenceElement)parent).getQualifier() != null) return false; + static boolean isClassNamePossible(CompletionParameters parameters) { + boolean isSecondCompletion = parameters.getInvocationCount() >= 2; + + final PsiElement parent = parameters.getPosition().getParent(); + if (!(parent instanceof PsiJavaCodeReferenceElement)) return isSecondCompletion; + if (((PsiJavaCodeReferenceElement)parent).getQualifier() != null) return isSecondCompletion; if (parent instanceof PsiJavaCodeReferenceElementImpl && ((PsiJavaCodeReferenceElementImpl)parent).getKind() == PsiJavaCodeReferenceElementImpl.PACKAGE_NAME_KIND) { @@ -394,7 +397,7 @@ public class JavaCompletionContributor extends CompletionContributor { } if (psiElement().inside(PsiImportStatement.class).accepts(parent)) { - return false; + return isSecondCompletion; } if (grand instanceof PsiAnonymousClass) { @@ -404,7 +407,7 @@ public class JavaCompletionContributor extends CompletionContributor { return false; } - if (JavaCompletionData.isAfterPrimitiveOrArrayType(position)) { + if (JavaCompletionData.isAfterPrimitiveOrArrayType(parameters.getPosition())) { return false; } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java index b264d0e2bd00..7992e0a4c07d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -483,8 +483,8 @@ public class JavaCompletionData extends JavaAwareCompletionData { } } - if ((isInsideParameterList(position) || isAtResourceVariableStart(position)) && - !psiElement().afterLeaf(PsiKeyword.FINAL).accepts(position) && + if ((isInsideParameterList(position) || isAtResourceVariableStart(position)) && + !psiElement().afterLeaf(PsiKeyword.FINAL).accepts(position) && !AFTER_DOT.accepts(position)) { result.addElement(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE_BEFORE_WORD)); } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java index 236e2e6768f6..853debf37051 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java @@ -51,26 +51,18 @@ public class JavaCompletionSorting { } public static CompletionResultSet addJavaSorting(final CompletionParameters parameters, CompletionResultSet result) { - String prefix = result.getPrefixMatcher().getPrefix(); final PsiElement position = parameters.getPosition(); final ExpectedTypeInfo[] expectedTypes = PsiJavaPatterns.psiElement().beforeLeaf(PsiJavaPatterns.psiElement().withText(".")).accepts(position) ? ExpectedTypeInfo.EMPTY_ARRAY : JavaSmartCompletionContributor.getExpectedTypes(parameters); final CompletionType type = parameters.getCompletionType(); final boolean smart = type == CompletionType.SMART; final boolean afterNew = JavaSmartCompletionContributor.AFTER_NEW.accepts(position); - List<LookupElementWeigher> afterPriority = new ArrayList<LookupElementWeigher>(); - if (smart) { - afterPriority.add(new PreferDefaultTypeWeigher(expectedTypes, parameters)); - } - ContainerUtil.addIfNotNull(afterPriority, recursion(parameters, expectedTypes)); - afterPriority.add(new PreferSimilarlyEnding(expectedTypes, prefix)); - List<LookupElementWeigher> afterProximity = new ArrayList<LookupElementWeigher>(); afterProximity.add(new PreferContainingSameWords(expectedTypes)); if (smart) { afterProximity.add(new PreferFieldsAndGetters()); } - afterProximity.add(new PreferShorter(expectedTypes, prefix)); + afterProximity.add(new PreferShorter(expectedTypes)); CompletionSorter sorter = CompletionSorter.defaultSorter(parameters, result.getPrefixMatcher()); if (!smart && afterNew) { @@ -78,20 +70,22 @@ public class JavaCompletionSorting { } else { sorter = ((CompletionSorterImpl)sorter).withClassifier("liftShorterClasses", true, new LiftShorterClasses(position)); } + if (smart) { + sorter = sorter.weighAfter("priority", new PreferDefaultTypeWeigher(expectedTypes, parameters)); + } List<LookupElementWeigher> afterPrefix = ContainerUtil.newArrayList(); if (!smart) { ContainerUtil.addIfNotNull(afterPrefix, preferStatics(position, expectedTypes)); } + ContainerUtil.addIfNotNull(afterPrefix, recursion(parameters, expectedTypes)); if (!smart && !afterNew) { afterPrefix.add(new PreferExpected(false, expectedTypes)); } - afterPrefix.add(new PreferByKindWeigher(type, position)); - Collections.addAll(afterPrefix, new PreferNonGeneric(), new PreferAccessible(position), new PreferSimple(), + Collections.addAll(afterPrefix, new PreferByKindWeigher(type, position), new PreferSimilarlyEnding(expectedTypes), + new PreferNonGeneric(), new PreferAccessible(position), new PreferSimple(), new PreferEnumConstants(parameters)); - - - sorter = sorter.weighAfter("priority", afterPriority.toArray(new LookupElementWeigher[afterPriority.size()])); + sorter = sorter.weighAfter("prefix", afterPrefix.toArray(new LookupElementWeigher[afterPrefix.size()])); sorter = sorter.weighAfter("proximity", afterProximity.toArray(new LookupElementWeigher[afterProximity.size()])); return result.withRelevanceSorter(sorter); @@ -207,18 +201,14 @@ public class JavaCompletionSorting { return null; } - private static int getNameEndMatchingDegree(final String name, ExpectedTypeInfo[] expectedInfos, String prefix) { + private static int getNameEndMatchingDegree(final String name, ExpectedTypeInfo[] expectedInfos) { int res = 0; if (name != null && expectedInfos != null) { - if (prefix.equals(name)) { - res = Integer.MAX_VALUE; - } else { - final List<String> words = NameUtil.nameToWordsLowerCase(name); - final List<String> wordsNoDigits = NameUtil.nameToWordsLowerCase(truncDigits(name)); - int max1 = calcMatch(words, 0, expectedInfos); - max1 = calcMatch(wordsNoDigits, max1, expectedInfos); - res = max1; - } + final List<String> words = NameUtil.nameToWordsLowerCase(name); + final List<String> wordsNoDigits = NameUtil.nameToWordsLowerCase(truncDigits(name)); + int max1 = calcMatch(words, 0, expectedInfos); + max1 = calcMatch(wordsNoDigits, max1, expectedInfos); + res = max1; } return res; @@ -457,19 +447,17 @@ public class JavaCompletionSorting { private static class PreferSimilarlyEnding extends LookupElementWeigher { private final ExpectedTypeInfo[] myExpectedTypes; - private final String myPrefix; - public PreferSimilarlyEnding(ExpectedTypeInfo[] expectedTypes, String prefix) { + public PreferSimilarlyEnding(ExpectedTypeInfo[] expectedTypes) { super("nameEnd"); myExpectedTypes = expectedTypes; - myPrefix = prefix; } @NotNull @Override public Comparable weigh(@NotNull LookupElement element) { final String name = getLookupObjectName(element.getObject()); - return -getNameEndMatchingDegree(name, myExpectedTypes, myPrefix); + return -getNameEndMatchingDegree(name, myExpectedTypes); } } @@ -521,12 +509,10 @@ public class JavaCompletionSorting { private static class PreferShorter extends LookupElementWeigher { private final ExpectedTypeInfo[] myExpectedTypes; - private final String myPrefix; - public PreferShorter(ExpectedTypeInfo[] expectedTypes, String prefix) { + public PreferShorter(ExpectedTypeInfo[] expectedTypes) { super("shorter"); myExpectedTypes = expectedTypes; - myPrefix = prefix; } @NotNull @@ -535,7 +521,7 @@ public class JavaCompletionSorting { final Object object = element.getObject(); final String name = getLookupObjectName(object); - if (name != null && getNameEndMatchingDegree(name, myExpectedTypes, myPrefix) != 0) { + if (name != null && getNameEndMatchingDegree(name, myExpectedTypes) != 0) { return NameUtil.nameToWords(name).length - 1000; } return 0; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionStatistician.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionStatistician.java index b0309da46d85..4a42e11903be 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionStatistician.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionStatistician.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.ExpectedTypeInfo; +import com.intellij.codeInsight.ExpectedTypeInfoImpl; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupItem; import com.intellij.psi.*; @@ -45,23 +46,26 @@ public class JavaCompletionStatistician extends CompletionStatistician{ PsiType qualifierType = JavaCompletionUtil.getQualifierType(item); if (o instanceof PsiMember) { + final ExpectedTypeInfo[] infos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location); + final ExpectedTypeInfo firstInfo = infos != null && infos.length > 0 ? infos[0] : null; String key2 = JavaStatisticsManager.getMemberUseKey2((PsiMember)o); if (o instanceof PsiClass) { - final ExpectedTypeInfo[] infos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location); - PsiType expectedType = infos != null && infos.length > 0 ? infos[0].getDefaultType() : null; + PsiType expectedType = firstInfo != null ? firstInfo.getDefaultType() : null; return new StatisticsInfo(JavaStatisticsManager.getAfterNewKey(expectedType), key2); } PsiClass containingClass = ((PsiMember)o).getContainingClass(); if (containingClass != null) { - String context = JavaStatisticsManager.getMemberUseKey2(containingClass); + String expectedName = firstInfo instanceof ExpectedTypeInfoImpl ? ((ExpectedTypeInfoImpl)firstInfo).expectedName.compute() : null; + String contextPrefix = expectedName == null ? "" : "expectedName=" + expectedName + "###"; + String context = contextPrefix + JavaStatisticsManager.getMemberUseKey2(containingClass); if (o instanceof PsiMethod) { String memberValue = JavaStatisticsManager.getMemberUseKey2(RecursionWeigher.findDeepestSuper((PsiMethod)o)); - List<StatisticsInfo> superMethodInfos = ContainerUtil.newArrayList(new StatisticsInfo(context, memberValue)); + List<StatisticsInfo> superMethodInfos = ContainerUtil.newArrayList(new StatisticsInfo(contextPrefix + context, memberValue)); for (PsiClass superClass : InheritanceUtil.getSuperClasses(containingClass)) { - superMethodInfos.add(new StatisticsInfo(JavaStatisticsManager.getMemberUseKey2(superClass), memberValue)); + superMethodInfos.add(new StatisticsInfo(contextPrefix + JavaStatisticsManager.getMemberUseKey2(superClass), memberValue)); } return StatisticsInfo.createComposite(superMethodInfos); } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index 053fc7220065..e2050a458438 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -654,11 +654,11 @@ public class JavaCompletionUtil { assert document != null; document.replaceString(startOffset, endOffset, name); - final RangeMarker toDelete = insertTemporary(startOffset + name.length(), document, " "); + int newEndOffset = startOffset + name.length(); + final RangeMarker toDelete = insertTemporary(newEndOffset, document, " "); documentManager.commitAllDocuments(); - int newEndOffset = endOffset; PsiElement element = file.findElementAt(startOffset); if (element instanceof PsiIdentifier) { PsiElement parent = element.getParent(); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java index 1a21b65af873..1026f48f432f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -52,8 +52,11 @@ import static com.intellij.patterns.StandardPatterns.or; * @author peter */ public class JavaMemberNameCompletionContributor extends CompletionContributor { - public static final ElementPattern<PsiElement> INSIDE_TYPE_PARAMS_PATTERN = - psiElement().afterLeaf(psiElement().withText("?").afterLeaf("<", ",")); + public static final ElementPattern<PsiElement> INSIDE_TYPE_PARAMS_PATTERN = psiElement(). + afterLeaf(psiElement().withText("?").andOr( + psiElement().afterLeaf("<", ","), + psiElement().afterSiblingSkipping(psiElement().whitespaceCommentEmptyOrError(), psiElement(PsiAnnotation.class)))); + static final int MAX_SCOPE_SIZE_TO_SEARCH_UNRESOLVED = 50000; @Override @@ -410,7 +413,7 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor { continue outer; } } - + LookupElement element = PrioritizedLookupElement.withPriority(LookupElementBuilder.create(name).withAutoCompletionPolicy(AutoCompletionPolicy.GIVE_CHANCE_TO_OVERWRITE), -i); if (callback != null) { element = LookupElementDecorator.withInsertHandler(element, new InsertHandler<LookupElementDecorator<LookupElement>>() { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNameIdentifierConfidence.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNameIdentifierConfidence.java new file mode 100644 index 000000000000..08b40b726df4 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNameIdentifierConfidence.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2013 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.CodeInsightSettings; +import com.intellij.lang.java.JavaLanguage; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMember; +import com.intellij.psi.PsiNameIdentifierOwner; +import com.intellij.psi.PsiVariable; +import com.intellij.util.ThreeState; +import org.jetbrains.annotations.NotNull; + +/** + * @author peter + */ +public class JavaNameIdentifierConfidence extends CompletionConfidence { + @NotNull + @Override + public ThreeState shouldFocusLookup(@NotNull CompletionParameters parameters) { + if (CodeInsightSettings.getInstance().SELECT_AUTOPOPUP_SUGGESTIONS_BY_CHARS) { + return ThreeState.UNSURE; + } + + final PsiElement position = parameters.getPosition(); + final PsiElement parent = position.getParent(); + if (parent instanceof PsiVariable || parent instanceof PsiMember) { + final PsiElement nameIdentifier = ((PsiNameIdentifierOwner)parent).getNameIdentifier(); + if (parent.getLanguage().isKindOf(JavaLanguage.INSTANCE) && nameIdentifier == position) { + return ThreeState.YES; + } + } + return ThreeState.UNSURE; + } + +} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java index d860c328b4af..6e95a4cad530 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java @@ -74,7 +74,7 @@ public class JavaNoVariantsDelegator extends CompletionContributor { if (parameters.getInvocationCount() <= 1 && JavaCompletionContributor.mayStartClassName(result) && - JavaCompletionContributor.isClassNamePossible(position)) { + JavaCompletionContributor.isClassNamePossible(parameters)) { suggestNonImportedClasses(parameters, result); return; } @@ -110,7 +110,12 @@ public class JavaNoVariantsDelegator extends CompletionContributor { return; } - String fullPrefix = position.getContainingFile().getText().substring(parent.getTextRange().getStartOffset(), parameters.getOffset()); + PsiFile file = position.getContainingFile(); + if (file instanceof PsiJavaCodeReferenceCodeFragment) { + return; + } + + String fullPrefix = parent.getText().substring(0, parameters.getOffset() - parent.getTextRange().getStartOffset()); CompletionResultSet qualifiedCollector = result.withPrefixMatcher(fullPrefix); ElementFilter filter = JavaCompletionContributor.getReferenceFilter(position); for (LookupElement base : suggestQualifierItems(parameters, (PsiJavaCodeReferenceElement)qualifier, filter)) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaOverrideCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaOverrideCompletionContributor.java index d71de30567c2..7467edc91687 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaOverrideCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaOverrideCompletionContributor.java @@ -27,9 +27,8 @@ import com.intellij.psi.*; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.psi.util.PsiFormatUtilBase; -import com.intellij.psi.util.TypeConversionUtil; import com.intellij.ui.RowIcon; -import com.intellij.util.Consumer; +import com.intellij.util.VisibilityUtil; import java.util.List; @@ -38,11 +37,10 @@ import static com.intellij.patterns.PlatformPatterns.psiElement; /** * @author peter */ -public class JavaOverrideCompletionContributor extends CompletionContributor { +public class JavaOverrideCompletionContributor { static final Key<Boolean> OVERRIDE_ELEMENT = Key.create("OVERRIDE_ELEMENT"); - @Override - public void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet _result) { + public static void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result) { if (parameters.getCompletionType() != CompletionType.BASIC && parameters.getCompletionType() != CompletionType.SMART) { return; } @@ -53,7 +51,6 @@ public class JavaOverrideCompletionContributor extends CompletionContributor { andNot(psiElement().afterLeaf(psiElement().inside(PsiModifierList.class))).accepts(position)) { final PsiClass parent = CompletionUtil.getOriginalElement((PsiClass)position.getParent().getParent().getParent()); if (parent != null) { - CompletionResultSet result = JavaCompletionSorting.addJavaSorting(parameters, _result); addSuperSignatureElements(parent, true, result); addSuperSignatureElements(parent, false, result); } @@ -64,17 +61,9 @@ public class JavaOverrideCompletionContributor extends CompletionContributor { private static void addSuperSignatureElements(final PsiClass parent, boolean implemented, CompletionResultSet result) { for (CandidateInfo candidate : OverrideImplementExploreUtil.getMethodsToOverrideImplement(parent, implemented)) { PsiMethod baseMethod = (PsiMethod)candidate.getElement(); - if (!baseMethod.isConstructor()) { - PsiClass baseClass = baseMethod.getContainingClass(); - List<PsiMethod> prototypes = OverrideImplementUtil.overrideOrImplementMethod(parent, baseMethod, candidate.getSubstitutor(), new Consumer<PsiMethod>() { - @Override - public void consume(PsiMethod method) { - OverrideImplementUtil.deleteDocComment(method); - } - }); - if (!prototypes.isEmpty() && baseClass != null) { - result.addElement(createOverridingLookupElement(parent, implemented, baseMethod, baseClass, prototypes.get(0))); - } + PsiClass baseClass = baseMethod.getContainingClass(); + if (!baseMethod.isConstructor() && baseClass != null) { + result.addElement(createOverridingLookupElement(parent, implemented, baseMethod, baseClass, candidate.getSubstitutor())); } } } @@ -82,18 +71,16 @@ public class JavaOverrideCompletionContributor extends CompletionContributor { private static LookupElementBuilder createOverridingLookupElement(final PsiClass parent, boolean implemented, final PsiMethod baseMethod, - PsiClass baseClass, final PsiMethod prototype) { - PsiIdentifier nameIdentifier = prototype.getNameIdentifier(); - assert nameIdentifier != null; + PsiClass baseClass, PsiSubstitutor substitutor) { + String methodName = baseMethod.getName(); - String signature = prototype.getModifierList().getText(); - if (!signature.isEmpty()) { - signature += " "; - } - PsiType returnType = prototype.getReturnType(); - signature += TypeConversionUtil.erasure(returnType).getPresentableText() + " " + prototype.getName(); + String visibility = VisibilityUtil.getVisibilityModifier(baseMethod.getModifierList()); + String modifiers = (visibility == PsiModifier.PACKAGE_LOCAL ? "" : visibility + " "); + + PsiType type = substitutor.substitute(baseMethod.getReturnType()); + String signature = modifiers + (type == null ? "" : type.getPresentableText() + " ") + methodName; - String parameters = PsiFormatUtil.formatMethod(prototype, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_NAME); + String parameters = PsiFormatUtil.formatMethod(baseMethod, substitutor, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_NAME); InsertHandler<LookupElement> insertHandler = new InsertHandler<LookupElement>() { @Override @@ -114,7 +101,7 @@ public class JavaOverrideCompletionContributor extends CompletionContributor { icon.setIcon(baseMethod.getIcon(0), 0); icon.setIcon(implemented ? AllIcons.Gutter.ImplementingMethod : AllIcons.Gutter.OverridingMethod, 1); - LookupElementBuilder element = LookupElementBuilder.create(baseMethod, signature).withLookupString(prototype.getName()). + LookupElementBuilder element = LookupElementBuilder.create(baseMethod, signature).withLookupString(methodName). withLookupString(signature).withInsertHandler(insertHandler). appendTailText(parameters, false).appendTailText(" {...}", true).withTypeText(baseClass.getName()).withIcon(icon); element.putUserData(OVERRIDE_ELEMENT, true); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java index a3a44ad6d4aa..6e2c627dc625 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -22,8 +22,8 @@ import com.intellij.openapi.util.Condition; import com.intellij.patterns.ElementPattern; import com.intellij.psi.*; import com.intellij.psi.filters.getters.MembersGetter; +import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.impl.source.tree.JavaElementType; -import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiTreeUtil; @@ -92,27 +92,15 @@ public class PreferByKindWeigher extends LookupElementWeigher { if (psiElement().withParents(PsiJavaCodeReferenceElement.class, PsiAnnotation.class).accepts(position)) { final PsiAnnotation annotation = PsiTreeUtil.getParentOfType(position, PsiAnnotation.class); assert annotation != null; - PsiAnnotationOwner owner = annotation.getOwner(); - if (owner instanceof PsiModifierList || owner instanceof PsiTypeElement || owner instanceof PsiTypeParameter) { - PsiElement member = (PsiElement)owner; - if (member instanceof PsiModifierList) { - member = member.getParent(); - } - if (member instanceof PsiTypeElement && member.getParent() instanceof PsiMethod) { - member = member.getParent(); + final PsiAnnotation.TargetType[] targets = PsiImplUtil.getTargetsForLocation(annotation.getOwner()); + return new Condition<PsiClass>() { + @Override + public boolean value(PsiClass psiClass) { + return psiClass.isAnnotationType() && PsiImplUtil.findApplicableTarget(psiClass, targets) != null; } - final String[] elementTypeFields = PsiAnnotationImpl.getApplicableElementTypeFields(member); - return new Condition<PsiClass>() { - @Override - public boolean value(PsiClass psiClass) { - if (!psiClass.isAnnotationType()) { - return false; - } - return PsiAnnotationImpl.isAnnotationApplicable(false, psiClass, elementTypeFields, position.getResolveScope()); - } - }; - } + }; } + //noinspection unchecked return Condition.FALSE; } @@ -179,7 +167,7 @@ public class PreferByKindWeigher extends LookupElementWeigher { return MyResult.qualifiedWithGetter; } } - + return MyResult.normal; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaColorProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaColorProvider.java index 47e56b27c6e2..dfc7169a2777 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaColorProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaColorProvider.java @@ -20,6 +20,7 @@ import com.intellij.openapi.editor.ElementColorProvider; import com.intellij.psi.*; import com.intellij.psi.impl.JavaConstantExpressionEvaluator; import com.intellij.psi.util.PsiTypesUtil; +import com.intellij.ui.ColorUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -147,7 +148,7 @@ public class JavaColorProvider implements ElementColorProvider { private static void replaceInt(PsiExpression expr, int newValue, boolean hex) { PsiElementFactory factory = JavaPsiFacade.getElementFactory(expr.getProject()); if (getInt(expr) != newValue) { - String text = hex ? "0x" + Integer.toHexString(newValue & 0x00ffffff).toUpperCase() : Integer.toString(newValue); + String text = hex ? "0x" + ColorUtil.toHex(new Color(newValue)).toUpperCase() : Integer.toString(newValue); expr.replace(factory.createExpressionFromText(text, null)); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java index 47456217955b..f0ac84d94ab3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java @@ -26,7 +26,7 @@ import com.intellij.psi.util.PsiMatcherImpl; import com.intellij.psi.util.PsiMatchers; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; -import com.intellij.util.ArrayUtil; +import com.intellij.util.ArrayUtilRt; import com.intellij.util.containers.BidirectionalMap; import com.intellij.util.containers.ConcurrentHashMap; import org.jetbrains.annotations.NonNls; @@ -34,6 +34,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.ref.SoftReference; +import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -47,7 +48,6 @@ public class RefCountHolder { private final Map<PsiNamedElement, Boolean> myDclsUsedMap = new ConcurrentHashMap<PsiNamedElement, Boolean>(); private final Map<PsiReference, PsiImportStatementBase> myImportStatements = new ConcurrentHashMap<PsiReference, PsiImportStatementBase>(); - private final Map<PsiElement,Boolean> myPossiblyDuplicateElements = new ConcurrentHashMap<PsiElement, Boolean>(); private final AtomicReference<ProgressIndicator> myState = new AtomicReference<ProgressIndicator>(VIRGIN); private static final ProgressIndicator VIRGIN = new DaemonProgressIndicator(); // just created or cleared private static final ProgressIndicator READY = new DaemonProgressIndicator(); @@ -124,7 +124,6 @@ public class RefCountHolder { } myImportStatements.clear(); myDclsUsedMap.clear(); - myPossiblyDuplicateElements.clear(); } public void registerLocallyReferenced(@NotNull PsiNamedElement result) { @@ -181,16 +180,16 @@ public class RefCountHolder { } } removeInvalidFrom(myDclsUsedMap.keySet()); - removeInvalidFrom(myPossiblyDuplicateElements.keySet()); } - private static void removeInvalidFrom(Iterable<? extends PsiElement> collection) { + + private static void removeInvalidFrom(@NotNull Collection<? extends PsiElement> collection) { for (Iterator<? extends PsiElement> it = collection.iterator(); it.hasNext();) { PsiElement element = it.next(); if (!element.isValid()) it.remove(); } } - public boolean isReferenced(PsiNamedElement element) { + public boolean isReferenced(@NotNull PsiNamedElement element) { List<PsiReference> array; synchronized (myLocalRefsMap) { array = myLocalRefsMap.getKeysByValue(element); @@ -201,13 +200,13 @@ public class RefCountHolder { return usedStatus == Boolean.TRUE; } - private static boolean isParameterUsedRecursively(final PsiElement element, final List<PsiReference> array) { + private static boolean isParameterUsedRecursively(@NotNull PsiElement element, @NotNull List<PsiReference> array) { if (!(element instanceof PsiParameter)) return false; PsiParameter parameter = (PsiParameter)element; PsiElement scope = parameter.getDeclarationScope(); if (!(scope instanceof PsiMethod)) return false; PsiMethod method = (PsiMethod)scope; - int paramIndex = ArrayUtil.find(method.getParameterList().getParameters(), parameter); + int paramIndex = ArrayUtilRt.find(method.getParameterList().getParameters(), parameter); for (PsiReference reference : array) { if (!(reference instanceof PsiElement)) return false; @@ -223,7 +222,7 @@ public class RefCountHolder { if (method != methodExpression.resolve()) return false; PsiExpressionList argumentList = methodCallExpression.getArgumentList(); PsiExpression[] arguments = argumentList.getExpressions(); - int argumentIndex = ArrayUtil.find(arguments, argument); + int argumentIndex = ArrayUtilRt.find(arguments, argument); if (paramIndex != argumentIndex) return false; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java index 68c4e1f5a0bc..98b582f73545 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -27,14 +27,13 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.patterns.ElementPattern; -import com.intellij.patterns.PatternCondition; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl; +import com.intellij.psi.impl.PsiImplUtil; +import com.intellij.psi.impl.source.PsiClassReferenceType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.ProcessingContext; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -161,17 +160,14 @@ public class AnnotationsHighlightUtil { @Nullable public static HighlightInfo checkDuplicateAnnotations(PsiAnnotation annotationToCheck) { PsiAnnotationOwner owner = annotationToCheck.getOwner(); - if (owner == null) { - return null; - } + if (owner == null) return null; PsiJavaCodeReferenceElement element = annotationToCheck.getNameReferenceElement(); if (element == null) return null; PsiElement resolved = element.resolve(); if (!(resolved instanceof PsiClass)) return null; - PsiAnnotation[] annotations = owner.getApplicableAnnotations(); - for (PsiAnnotation annotation : annotations) { + for (PsiAnnotation annotation : owner.getAnnotations()) { if (annotation == annotationToCheck) continue; PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement(); if (nameRef == null) continue; @@ -254,48 +250,115 @@ public class AnnotationsHighlightUtil { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); } - private static final ElementPattern<PsiElement> ANNOTATION_ALLOWED = psiElement().andOr( - psiElement().with(new PatternCondition<PsiElement>("annotationOwner") { - @Override - public boolean accepts(@NotNull PsiElement element, ProcessingContext context) { - return element instanceof PsiAnnotationOwner; - } - }), + private static final ElementPattern<PsiElement> ANY_ANNOTATION_ALLOWED = psiElement().andOr( psiElement().withParent(PsiNameValuePair.class), psiElement().withParents(PsiArrayInitializerMemberValue.class, PsiNameValuePair.class), psiElement().withParent(PsiAnnotationMethod.class).afterLeaf(PsiKeyword.DEFAULT) ); @Nullable - public static HighlightInfo checkApplicability(final PsiAnnotation annotation) { + public static HighlightInfo checkApplicability(@NotNull PsiAnnotation annotation) { + if (ANY_ANNOTATION_ALLOWED.accepts(annotation)) { + return null; + } + + PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement(); + if (nameRef == null) return null; + PsiAnnotationOwner owner = annotation.getOwner(); - if (owner instanceof PsiModifierList || owner instanceof PsiTypeElement || owner instanceof PsiTypeParameter) { - PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement(); - if (nameRef == null) { - return null; + PsiAnnotation.TargetType[] targets = PsiImplUtil.getTargetsForLocation(owner); + if (owner == null || targets.length == 0) { + String message = JavaErrorMessages.message("annotation.not.allowed.here"); + return annotationError(annotation, message); + } + + if (!(owner instanceof PsiModifierList)) { + HighlightInfo info = HighlightUtil.checkTypeAnnotationFeature(annotation); + if (info != null) return info; + } + + PsiAnnotation.TargetType applicable = PsiImplUtil.findApplicableTarget(annotation, targets); + if (applicable == PsiAnnotation.TargetType.UNKNOWN) return null; + + if (applicable == null) { + String target = JavaErrorMessages.message("annotation.target." + targets[0]); + String message = JavaErrorMessages.message("annotation.not.applicable", nameRef.getText(), target); + return annotationError(annotation, message); + } + + if (applicable == PsiAnnotation.TargetType.TYPE_USE) { + if (owner instanceof PsiClassReferenceType) { + PsiJavaCodeReferenceElement ref = ((PsiClassReferenceType)owner).getReference(); + HighlightInfo info = checkReferenceTarget(annotation, ref); + if (info != null) return info; } - PsiElement member = owner instanceof PsiModifierList ? ((PsiElement)owner).getParent() : (PsiElement)owner; - String[] elementTypeFields = PsiAnnotationImpl.getApplicableElementTypeFields(member); - if (elementTypeFields == null || PsiAnnotationImpl.isAnnotationApplicableTo(annotation, false, elementTypeFields)) { - return null; + else if (owner instanceof PsiModifierList) { + PsiElement nextElement = PsiTreeUtil.skipSiblingsForward((PsiModifierList)owner, + PsiComment.class, PsiWhiteSpace.class, PsiTypeParameterList.class); + if (nextElement instanceof PsiTypeElement) { + PsiTypeElement typeElement = (PsiTypeElement)nextElement; + PsiType type = typeElement.getType(); + if (PsiType.VOID.equals(type)) { + String message = JavaErrorMessages.message("annotation.not.allowed.void"); + return annotationError(annotation, message); + } + if (!(type instanceof PsiPrimitiveType)) { + PsiJavaCodeReferenceElement ref = getOutermostReferenceElement(typeElement.getInnermostComponentReferenceElement()); + HighlightInfo info = checkReferenceTarget(annotation, ref); + if (info != null) return info; + } + } + } + else if (owner instanceof PsiTypeElement) { + PsiElement context = PsiTreeUtil.skipParentsOfType((PsiTypeElement)owner, PsiTypeElement.class); + if (context instanceof PsiClassObjectAccessExpression) { + String message = JavaErrorMessages.message("annotation.not.allowed.class"); + return annotationError(annotation, message); + } } - String target = JavaErrorMessages.message("annotation.target." + elementTypeFields[0]); - String description = JavaErrorMessages.message("annotation.not.applicable", nameRef.getText(), target); - HighlightInfo highlightInfo = - HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(nameRef).descriptionAndTooltip(description).create(); - QuickFixAction.registerQuickFixAction(highlightInfo, new DeleteNotApplicableAnnotationAction(annotation)); - return highlightInfo; } - if (!ANNOTATION_ALLOWED.accepts(annotation)) { - String message = JavaErrorMessages.message("annotation.not.allowed.here"); - HighlightInfo highlightInfo = - HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(annotation).descriptionAndTooltip(message).create(); - QuickFixAction.registerQuickFixAction(highlightInfo, new DeleteNotApplicableAnnotationAction(annotation)); - return highlightInfo; + return null; + } + + private static HighlightInfo annotationError(PsiAnnotation annotation, String message) { + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(annotation).descriptionAndTooltip(message).create(); + QuickFixAction.registerQuickFixAction(info, new DeleteAnnotationAction(annotation)); + return info; + } + + @Nullable + private static HighlightInfo checkReferenceTarget(PsiAnnotation annotation, @Nullable PsiJavaCodeReferenceElement ref) { + if (ref == null) return null; + PsiElement refTarget = ref.resolve(); + if (refTarget == null) return null; + + String message = null; + if (!(refTarget instanceof PsiClass)) { + message = JavaErrorMessages.message("annotation.not.allowed.ref"); + } + else { + PsiElement parent = ref.getParent(); + if (parent instanceof PsiJavaCodeReferenceElement) { + PsiElement qualified = ((PsiJavaCodeReferenceElement)parent).resolve(); + if (qualified instanceof PsiMember && ((PsiMember)qualified).hasModifierProperty(PsiModifier.STATIC)) { + message = JavaErrorMessages.message("annotation.not.allowed.static"); + } + } } - return null; + return message != null ? annotationError(annotation, message) : null; + } + + @Nullable + private static PsiJavaCodeReferenceElement getOutermostReferenceElement(@Nullable PsiJavaCodeReferenceElement ref) { + if (ref == null) return null; + + PsiElement qualifier; + while ((qualifier = ref.getQualifier()) instanceof PsiJavaCodeReferenceElement) { + ref = (PsiJavaCodeReferenceElement)qualifier; + } + return ref; } public static HighlightInfo checkForeignInnerClassesUsed(final PsiAnnotation annotation) { @@ -463,10 +526,10 @@ public class AnnotationsHighlightUtil { } } - private static class DeleteNotApplicableAnnotationAction implements IntentionAction { + private static class DeleteAnnotationAction implements IntentionAction { private final PsiAnnotation myAnnotation; - public DeleteNotApplicableAnnotationAction(PsiAnnotation annotation) { + public DeleteAnnotationAction(PsiAnnotation annotation) { myAnnotation = annotation; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index ebd37010a2aa..cefa4f40bc26 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -150,6 +150,7 @@ public class GenericsHighlightUtil { final String description; if (targetParametersNum == 0) { if (PsiTreeUtil.getParentOfType(referenceParameterList, PsiCall.class) != null && + typeParameterListOwner instanceof PsiMethod && JavaVersionService.getInstance().isAtLeast(referenceParameterList, JavaSdkVersion.JDK_1_7)) { description = null; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index f2afaa1b66e0..88d41ed78a4d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -1061,10 +1061,13 @@ public class HighlightMethodUtil { if (otherSuperReturnType == null || currentType == null || otherSuperReturnType.equals(currentType)) continue; if (PsiUtil.isLanguageLevel5OrHigher(currentMethod)) { - if (otherSuperReturnType.isAssignableFrom(currentType)) continue; - if (currentType.isAssignableFrom(otherSuperReturnType)) { - returnTypeSubstitutable = otherSuperSignature; - continue; + //http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.8 Example 8.1.5-3 + if (!(otherSuperReturnType instanceof PsiPrimitiveType || currentType instanceof PsiPrimitiveType)) { + if (otherSuperReturnType.isAssignableFrom(currentType)) continue; + if (currentType.isAssignableFrom(otherSuperReturnType)) { + returnTypeSubstitutable = otherSuperSignature; + continue; + } } } return createIncompatibleReturnTypeMessage(currentMethod, currentMethod, otherSuperMethod, false, otherSuperReturnType, diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java index 8bb1be302162..085d75e43376 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java @@ -52,6 +52,13 @@ public class HighlightNamesUtil { final PsiElement elementToHighlight, final boolean isDeclaration, @NotNull EditorColorsScheme colorsScheme) { + return highlightMethodName(method, elementToHighlight, elementToHighlight.getTextRange(), colorsScheme, isDeclaration); + } + + @Nullable + public static HighlightInfo highlightMethodName(@NotNull PsiMethod method, + final PsiElement elementToHighlight, + TextRange range, @NotNull EditorColorsScheme colorsScheme, final boolean isDeclaration) { boolean isInherited = false; if (!isDeclaration) { @@ -64,7 +71,7 @@ public class HighlightNamesUtil { HighlightInfoType type = getMethodNameHighlightType(method, isDeclaration, isInherited); if (type != null && elementToHighlight != null) { TextAttributes attributes = mergeWithScopeAttributes(method, type, colorsScheme); - HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(type).range(elementToHighlight.getTextRange()); + HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(type).range(range); if (attributes != null) { builder.textAttributes(attributes); } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index f5b78ba3ce6d..211bcfb67774 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -549,14 +549,13 @@ public class HighlightUtil extends HighlightUtilBase { @Nullable static HighlightInfo checkVariableAlreadyDefined(@NotNull PsiVariable variable) { if (variable instanceof ExternallyDefinedPsiElement) return null; - PsiIdentifier identifier = variable.getNameIdentifier(); - assert identifier != null : variable; - String name = variable.getName(); boolean isIncorrect = false; + PsiElement declarationScope; if (variable instanceof PsiLocalVariable || - variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiCatchSection || - variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiForeachStatement || - variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiLambdaExpression) { + variable instanceof PsiParameter && + ((declarationScope = ((PsiParameter)variable).getDeclarationScope()) instanceof PsiCatchSection || + declarationScope instanceof PsiForeachStatement || + declarationScope instanceof PsiLambdaExpression)) { @SuppressWarnings("unchecked") PsiElement scope = PsiTreeUtil.getParentOfType(variable, PsiFile.class, PsiMethod.class, PsiClassInitializer.class, PsiResourceList.class); VariablesNotProcessor proc = new VariablesNotProcessor(variable, false) { @@ -565,6 +564,8 @@ public class HighlightUtil extends HighlightUtilBase { return (var instanceof PsiLocalVariable || var instanceof PsiParameter) && super.check(var, state); } }; + PsiIdentifier identifier = variable.getNameIdentifier(); + assert identifier != null : variable; PsiScopesUtil.treeWalkUp(proc, identifier, scope); if (scope instanceof PsiResourceList && proc.size() == 0) { scope = PsiTreeUtil.getParentOfType(variable, PsiFile.class, PsiMethod.class, PsiClassInitializer.class); @@ -578,7 +579,7 @@ public class HighlightUtil extends HighlightUtilBase { PsiField field = (PsiField)variable; PsiClass aClass = field.getContainingClass(); if (aClass == null) return null; - PsiField fieldByName = aClass.findFieldByName(name, false); + PsiField fieldByName = aClass.findFieldByName(variable.getName(), false); if (fieldByName != null && fieldByName != field) { isIncorrect = true; } @@ -589,7 +590,7 @@ public class HighlightUtil extends HighlightUtilBase { for (PsiElement child : children) { if (child instanceof PsiVariable) { if (child.equals(variable)) continue; - if (name.equals(((PsiVariable)child).getName())) { + if (variable.getName().equals(((PsiVariable)child).getName())) { isIncorrect = true; break; } @@ -598,7 +599,9 @@ public class HighlightUtil extends HighlightUtilBase { } if (isIncorrect) { - String description = JavaErrorMessages.message("variable.already.defined", name); + String description = JavaErrorMessages.message("variable.already.defined", variable.getName()); + PsiIdentifier identifier = variable.getNameIdentifier(); + assert identifier != null : variable; HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(description).create(); if (variable instanceof PsiLocalVariable) { @@ -948,14 +951,13 @@ public class HighlightUtil extends HighlightUtilBase { final String message = JavaErrorMessages.message("illegal.line.end.in.character.literal"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } - final StringBuilder chars = StringBuilderSpinAllocator.alloc(); + StringBuilder chars = new StringBuilder(); final boolean success = PsiLiteralExpressionImpl.parseStringCharacters(text, chars, null); if (!success) { final String message = JavaErrorMessages.message("illegal.escape.character.in.character.literal"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } - final int length = chars.length(); - StringBuilderSpinAllocator.dispose(chars); + int length = chars.length(); if (length > 1) { final String message = JavaErrorMessages.message("too.many.characters.in.character.literal"); final HighlightInfo info = @@ -1255,8 +1257,8 @@ public class HighlightUtil extends HighlightUtilBase { public static HighlightInfo checkSwitchSelectorType(@NotNull PsiSwitchStatement statement) { final PsiExpression expression = statement.getExpression(); HighlightInfo errorResult = null; - if (expression != null && expression.getType() != null) { - PsiType type = expression.getType(); + PsiType type = expression == null ? null : expression.getType(); + if (type != null) { if (!isValidTypeForSwitchSelector(type, PsiUtil.isLanguageLevel7OrHigher(expression))) { String message = JavaErrorMessages.message("incompatible.types", JavaErrorMessages.message("valid.switch.selector.types"), formatType(type)); @@ -1380,7 +1382,7 @@ public class HighlightUtil extends HighlightUtilBase { if (aClass.isInterface()) { return thisNotFoundInInterfaceInfo(expr); } - + if (aClass instanceof PsiAnonymousClass && PsiTreeUtil.isAncestor(((PsiAnonymousClass)aClass).getArgumentList(), expr, true)) { final PsiClass parentClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class, true); if (parentClass != null && parentClass.isInterface()) { @@ -1392,9 +1394,8 @@ public class HighlightUtil extends HighlightUtilBase { return null; } - private static HighlightInfo thisNotFoundInInterfaceInfo(PsiExpression expr) { - return HighlightInfo - .newHighlightInfo(HighlightInfoType.ERROR).range(expr).descriptionAndTooltip("Cannot find symbol variable this").create(); + private static HighlightInfo thisNotFoundInInterfaceInfo(@NotNull PsiExpression expr) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expr).descriptionAndTooltip("Cannot find symbol variable this").create(); } private static boolean resolvesToImmediateSuperInterface(@NotNull PsiExpression expr, @@ -1609,7 +1610,10 @@ public class HighlightUtil extends HighlightUtilBase { if (parent instanceof PsiReferenceExpression || parent instanceof PsiMethodCallExpression) return null; if (resolved instanceof PsiVariable) return null; String description = JavaErrorMessages.message("expression.expected"); - return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); + final HighlightInfo info = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); + UnresolvedReferenceQuickFixProvider.registerReferenceFixes(expression, new QuickFixActionRegistrarImpl(info)); + return info; } @@ -2265,7 +2269,7 @@ public class HighlightUtil extends HighlightUtilBase { if (thenType == null || elseType == null) return null; if (conditionalExpression.getType() == null) { // cannot derive type of conditional expression - // elsetype will never be castable to thentype, so no quick fix here + // elseType will never be castable to thenType, so no quick fix here return createIncompatibleTypeHighlightInfo(thenType, elseType, expression.getTextRange(), 0); } return null; @@ -2625,7 +2629,7 @@ public class HighlightUtil extends HighlightUtilBase { return null; } - private static enum Feature { + private enum Feature { GENERICS(LanguageLevel.JDK_1_5, "feature.generics"), ANNOTATIONS(LanguageLevel.JDK_1_5, "feature.annotations"), STATIC_IMPORTS(LanguageLevel.JDK_1_5, "feature.static.imports"), @@ -2639,12 +2643,13 @@ public class HighlightUtil extends HighlightUtilBase { UNDERSCORES(LanguageLevel.JDK_1_7, "feature.underscores.in.literals"), EXTENSION_METHODS(LanguageLevel.JDK_1_8, "feature.extension.methods"), METHOD_REFERENCES(LanguageLevel.JDK_1_8, "feature.method.references"), - LAMBDA_EXPRESSIONS(LanguageLevel.JDK_1_8, "feature.lambda.expressions"); + LAMBDA_EXPRESSIONS(LanguageLevel.JDK_1_8, "feature.lambda.expressions"), + TYPE_ANNOTATIONS(LanguageLevel.JDK_1_8, "feature.type.annotations"); private final LanguageLevel level; private final String key; - private Feature(final LanguageLevel level, @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) final String key) { + Feature(final LanguageLevel level, @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) final String key) { this.level = level; this.key = key; } @@ -2653,9 +2658,8 @@ public class HighlightUtil extends HighlightUtilBase { @Nullable private static HighlightInfo checkFeature(@Nullable final PsiElement element, @NotNull final Feature feature) { if (element != null && element.getManager().isInProject(element) && !PsiUtil.getLanguageLevel(element).isAtLeast(feature.level)) { - final String message = JavaErrorMessages.message("insufficient.language.level", JavaErrorMessages.message(feature.key)); - final HighlightInfo info = - HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(message).create(); + String message = JavaErrorMessages.message("insufficient.language.level", JavaErrorMessages.message(feature.key)); + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(message).create(); QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(feature.level)); QuickFixAction.registerQuickFixAction(info, new ShowModulePropertiesFix(element)); return info; @@ -2665,57 +2669,62 @@ public class HighlightUtil extends HighlightUtilBase { } @Nullable - public static HighlightInfo checkGenericsFeature(final PsiElement parameterList, final int listSize) { + public static HighlightInfo checkGenericsFeature(PsiElement parameterList, int listSize) { return listSize > 0 ? checkFeature(parameterList, Feature.GENERICS) : null; } @Nullable - public static HighlightInfo checkAnnotationFeature(final PsiElement element) { + public static HighlightInfo checkAnnotationFeature(PsiElement element) { return checkFeature(element, Feature.ANNOTATIONS); } @Nullable - public static HighlightInfo checkForEachFeature(final PsiForeachStatement statement) { + public static HighlightInfo checkForEachFeature(PsiForeachStatement statement) { return checkFeature(statement, Feature.FOR_EACH); } @Nullable - public static HighlightInfo checkStaticImportFeature(final PsiImportStaticStatement statement) { + public static HighlightInfo checkStaticImportFeature(PsiImportStaticStatement statement) { return checkFeature(statement, Feature.STATIC_IMPORTS); } @Nullable - public static HighlightInfo checkVarargFeature(final PsiParameter parameter) { + public static HighlightInfo checkVarargFeature(PsiParameter parameter) { return checkFeature(parameter, Feature.VARARGS); } @Nullable - public static HighlightInfo checkDiamondFeature(@NotNull final PsiTypeElement typeElement) { + public static HighlightInfo checkDiamondFeature(PsiTypeElement typeElement) { return typeElement.getType() instanceof PsiDiamondType ? checkFeature(typeElement.getParent(), Feature.DIAMOND_TYPES) : null; } @Nullable - public static HighlightInfo checkMultiCatchFeature(@NotNull final PsiParameter parameter) { + public static HighlightInfo checkMultiCatchFeature(PsiParameter parameter) { return parameter.getType() instanceof PsiDisjunctionType ? checkFeature(parameter, Feature.MULTI_CATCH) : null; } @Nullable - public static HighlightInfo checkTryWithResourcesFeature(@NotNull final PsiResourceVariable resourceVariable) { + public static HighlightInfo checkTryWithResourcesFeature(PsiResourceVariable resourceVariable) { return checkFeature(resourceVariable.getParent(), Feature.TRY_WITH_RESOURCES); } @Nullable - public static HighlightInfo checkExtensionMethodsFeature(final PsiMethod method) { + public static HighlightInfo checkExtensionMethodsFeature(PsiMethod method) { return checkFeature(method, Feature.EXTENSION_METHODS); } @Nullable - public static HighlightInfo checkMethodReferencesFeature(final PsiMethodReferenceExpression expression) { + public static HighlightInfo checkMethodReferencesFeature(PsiMethodReferenceExpression expression) { return checkFeature(expression, Feature.METHOD_REFERENCES); } @Nullable - public static HighlightInfo checkLambdaFeature(final PsiLambdaExpression expression) { + public static HighlightInfo checkLambdaFeature(PsiLambdaExpression expression) { return checkFeature(expression, Feature.LAMBDA_EXPRESSIONS); } + + @Nullable + public static HighlightInfo checkTypeAnnotationFeature(PsiAnnotation annotation) { + return checkFeature(annotation, Feature.TYPE_ANNOTATIONS); + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 7d97295b8bab..3b6ef960f407 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -693,7 +693,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (parent instanceof PsiMethodCallExpression) { PsiMethod method = ((PsiMethodCallExpression)parent).resolveMethod(); PsiElement methodNameElement = element.getReferenceNameElement(); - if (method != null && methodNameElement != null) { + if (method != null && methodNameElement != null&& !(methodNameElement instanceof PsiKeyword)) { myHolder.add(HighlightNamesUtil.highlightMethodName(method, methodNameElement, false, colorsScheme)); myHolder.add(HighlightNamesUtil.highlightClassNameInQualifier(element, colorsScheme)); } @@ -707,7 +707,12 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } } else { - myHolder.add(HighlightNamesUtil.highlightMethodName(method, element, false, colorsScheme)); + final PsiElement referenceNameElement = element.getReferenceNameElement(); + if(referenceNameElement != null) { + // exclude type parameters from the highlighted text range + TextRange range = new TextRange(element.getTextRange().getStartOffset(), referenceNameElement.getTextRange().getEndOffset()); + myHolder.add(HighlightNamesUtil.highlightMethodName(method, referenceNameElement, range, colorsScheme, false)); + } } } catch (IndexNotReadyException ignored) { @@ -959,6 +964,14 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (PsiTreeUtil.isAncestor(aClass, place, false) && aClass.hasTypeParameters()) { myHolder.add(HighlightClassUtil.checkCreateInnerClassFromStaticContext(ref, place, (PsiClass)resolved)); } + } else if (resolved instanceof PsiTypeParameter) { + final PsiTypeParameterListOwner owner = ((PsiTypeParameter)resolved).getOwner(); + if (owner instanceof PsiClass) { + final PsiClass outerClass = (PsiClass)owner; + if (!HighlightClassUtil.hasEnclosingInstanceInScope(outerClass, ref, true, false)) { + myHolder.add(HighlightClassUtil.reportIllegalEnclosingUsage(ref, aClass, (PsiClass)owner, ref)); + } + } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddDefaultConstructorFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddDefaultConstructorFix.java index 8fbaea90571a..21e5a189f086 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddDefaultConstructorFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddDefaultConstructorFix.java @@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull; public class AddDefaultConstructorFix extends AddMethodFix { public AddDefaultConstructorFix(PsiClass aClass) { - this(aClass, PsiUtil.getMaximumModifierForMember(aClass)); + this(aClass, PsiUtil.getMaximumModifierForMember(aClass, false)); } public AddDefaultConstructorFix(PsiClass aClass, @NotNull @PsiModifier.ModifierConstant final String modifier) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeNewOperatorTypeFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeNewOperatorTypeFix.java index 3d75b961b500..f168b6355ffd 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeNewOperatorTypeFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeNewOperatorTypeFix.java @@ -122,10 +122,11 @@ public class ChangeNewOperatorTypeFix implements IntentionAction { } if (anonymousClass != null) { - final PsiAnonymousClass newAnonymousClass = (PsiAnonymousClass)newExpression.getAnonymousClass().replace(anonymousClass); - final PsiClass aClass = PsiUtil.resolveClassInType(toType); - assert aClass != null; - newAnonymousClass.getBaseClassReference().replace(factory.createClassReferenceElement(aClass)); + PsiAnonymousClass newAnonymousClass = newExpression.getAnonymousClass(); + final PsiElement childInside = anonymousClass.getLBrace().getNextSibling(); + if (childInside != null) { + newAnonymousClass.addRange(childInside, anonymousClass.getRBrace().getPrevSibling()); + } } selection = null; caretOffset = -1; @@ -151,7 +152,10 @@ public class ChangeNewOperatorTypeFix implements IntentionAction { PsiType newType = lType; if (rType instanceof PsiClassType && newType instanceof PsiClassType) { final PsiClassType.ClassResolveResult rResolveResult = ((PsiClassType)rType).resolveGenerics(); - final PsiClass rClass = rResolveResult.getElement(); + PsiClass rClass = rResolveResult.getElement(); + if (rClass instanceof PsiAnonymousClass) { + rClass = ((PsiAnonymousClass)rClass).getBaseClassType().resolve(); + } if (rClass != null) { final PsiClassType.ClassResolveResult lResolveResult = ((PsiClassType)newType).resolveGenerics(); final PsiClass lClass = lResolveResult.getElement(); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateClassFromUsageBaseFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateClassFromUsageBaseFix.java index 4b18b60a19bd..3d482f54b4ab 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateClassFromUsageBaseFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateClassFromUsageBaseFix.java @@ -23,6 +23,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,7 +39,7 @@ public abstract class CreateClassFromUsageBaseFix extends BaseIntentionAction { public CreateClassFromUsageBaseFix(CreateClassKind kind, final PsiJavaCodeReferenceElement refElement) { myKind = kind; - myRefElement = SmartPointerManager.getInstance(refElement.getProject()).createLazyPointer(refElement); + myRefElement = SmartPointerManager.getInstance(refElement.getProject()).createSmartPsiElementPointer(refElement); } protected abstract String getText(String varName); @@ -113,6 +114,12 @@ public abstract class CreateClassFromUsageBaseFix extends BaseIntentionAction { PsiElement parent = element.getParent(); if (parent instanceof PsiExpression && !(parent instanceof PsiReferenceExpression)) return false; if (!isAvailableInContext(element)) return false; + final String superClassName = getSuperClassName(element); + if (superClassName != null) { + if (superClassName.equals(CommonClassNames.JAVA_LANG_ENUM) && myKind != CreateClassKind.ENUM) return false; + final PsiClass psiClass = JavaPsiFacade.getInstance(project).findClass(superClassName, GlobalSearchScope.allScope(project)); + if (psiClass != null && psiClass.hasModifierProperty(PsiModifier.FINAL)) return false; + } final int offset = editor.getCaretModel().getOffset(); if (CreateFromUsageUtils.shouldShowTag(offset, nameElement, element)) { setText(getText(nameElement.getText())); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java index 18c2e0b1c6b4..139a605ae60d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java @@ -66,8 +66,6 @@ public class CreateFieldFromUsageFix extends CreateVarFromUsageFix { } while (parentClass instanceof PsiAnonymousClass); - final PsiFile targetFile = targetClass.getContainingFile(); - ExpectedTypeInfo[] expectedTypes = CreateFromUsageUtils.guessExpectedTypes(myReferenceExpression, false); String fieldName = myReferenceExpression.getReferenceName(); @@ -94,10 +92,20 @@ public class CreateFieldFromUsageFix extends CreateVarFromUsageFix { setupVisibility(parentClass, targetClass, field.getModifierList()); + createFieldFromUsageTemplate(targetClass, project, expectedTypes, field, createConstantField(), myReferenceExpression); + } + + public static void createFieldFromUsageTemplate(final PsiClass targetClass, + final Project project, + final ExpectedTypeInfo[] expectedTypes, + final PsiField field, + final boolean createConstantField, + final PsiElement context) { + final PsiFile targetFile = targetClass.getContainingFile(); final Editor newEditor = positionCursor(project, targetFile, field); if (newEditor == null) return; Template template = - CreateFieldFromUsageHelper.setupTemplate(field, expectedTypes, targetClass, newEditor, myReferenceExpression, createConstantField()); + CreateFieldFromUsageHelper.setupTemplate(field, expectedTypes, targetClass, newEditor, context, createConstantField); startTemplate(newEditor, template, project, new TemplateEditingAdapter() { @Override diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java index 83b43424bad2..492b0b0ec741 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java @@ -163,7 +163,7 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction { } protected void setupVisibility(PsiClass parentClass, PsiClass targetClass, PsiModifierList list) throws IncorrectOperationException { - if (targetClass.isInterface()) { + if (targetClass.isInterface() && list.getFirstChild() != null) { list.deleteChildRange(list.getFirstChild(), list.getLastChild()); return; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java index 962c90a91846..086c1caaab88 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java @@ -85,6 +85,7 @@ public class CreateFromUsageUtils { if (!unresolvedOnly) { for (JavaResolveResult result : results) { if (!result.isValidResult()) return false; + if (result.getElement() instanceof PsiPackage) return false; } } return true; @@ -446,7 +447,7 @@ public class CreateFromUsageUtils { targetClass = (PsiClass) sourceFile.add(aClass); } - if (superClassName != null) { + if (superClassName != null && (classKind != CreateClassKind.ENUM || !superClassName.equals(CommonClassNames.JAVA_LANG_ENUM))) { final PsiClass superClass = facade.findClass(superClassName, targetClass.getResolveScope()); final PsiJavaCodeReferenceElement superClassReference = factory.createReferenceElementByFQClassName(superClassName, targetClass.getResolveScope()); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java index 22d4cbdb1a61..155c7ac89281 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java @@ -60,7 +60,7 @@ public class CreateLocalFromUsageFix extends CreateVarFromUsageFix { @Override protected void invokeImpl(final PsiClass targetClass) { - if (CreateFromUsageUtils.isValidReference(myReferenceExpression, true)) { + if (CreateFromUsageUtils.isValidReference(myReferenceExpression, false)) { return; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodQuickFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodQuickFix.java index a1323ae5fd90..38a3d59eaf24 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodQuickFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodQuickFix.java @@ -18,7 +18,7 @@ package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.daemon.QuickFixBundle; -import com.intellij.codeInspection.IntentionAndQuickFixAction; +import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; @@ -35,22 +35,22 @@ import org.jetbrains.annotations.Nullable; import java.util.List; -public class CreateMethodQuickFix extends IntentionAndQuickFixAction { - protected final PsiClass myTargetClass; +public class CreateMethodQuickFix extends LocalQuickFixAndIntentionActionOnPsiElement { protected final String mySignature; protected final String myBody; private CreateMethodQuickFix(final PsiClass targetClass, @NonNls final String signature, @NonNls final String body) { - myTargetClass = targetClass; + super(targetClass); mySignature = signature; myBody = body; } @Override @NotNull - public String getName() { - - String signature = PsiFormatUtil.formatMethod(createMethod(myTargetClass.getProject()), PsiSubstitutor.EMPTY, + public String getText() { + PsiClass myTargetClass = (PsiClass)getStartElement(); + String signature = myTargetClass == null ? "" : + PsiFormatUtil.formatMethod(createMethod(myTargetClass), PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_TYPE | PsiFormatUtilBase.SHOW_PARAMETERS | @@ -66,10 +66,15 @@ public class CreateMethodQuickFix extends IntentionAndQuickFixAction { } @Override - public void applyFix(Project project, PsiFile file, @Nullable Editor editor) { + public void invoke(@NotNull Project project, + @NotNull PsiFile file, + @Nullable("is null when called from inspection") Editor editor, + @NotNull PsiElement startElement, + @NotNull PsiElement endElement) { + PsiClass myTargetClass = (PsiClass)startElement; if (!CodeInsightUtilBase.preparePsiElementForWrite(myTargetClass.getContainingFile())) return; - PsiMethod method = createMethod(project); + PsiMethod method = createMethod(myTargetClass); List<Pair<PsiExpression, PsiType>> arguments = ContainerUtil.map2List(method.getParameterList().getParameters(), new Function<PsiParameter, Pair<PsiExpression, PsiType>>() { @Override @@ -82,8 +87,12 @@ public class CreateMethodQuickFix extends IntentionAndQuickFixAction { CreateMethodFromUsageFix.doCreate(myTargetClass, method, arguments, PsiSubstitutor.EMPTY, ExpectedTypeInfo.EMPTY_ARRAY, method); } - private PsiMethod createMethod(Project project) { - PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory(); + private PsiMethod createMethod(@NotNull PsiClass myTargetClass) { + Project project = myTargetClass.getProject(); + JVMElementFactory elementFactory = JVMElementFactories.getFactory(myTargetClass.getLanguage(), project); + if (elementFactory == null) { + elementFactory = JavaPsiFacade.getElementFactory(project); + } String methodText = mySignature + (myTargetClass.isInterface() ? ";" : "{" + myBody + "}"); return elementFactory.createMethodFromText(methodText, null); } @@ -92,7 +101,7 @@ public class CreateMethodQuickFix extends IntentionAndQuickFixAction { public static CreateMethodQuickFix createFix(@NotNull PsiClass targetClass, @NonNls final String signature, @NonNls final String body) { CreateMethodQuickFix fix = new CreateMethodQuickFix(targetClass, signature, body); try { - fix.createMethod(targetClass.getProject()); + fix.createMethod(targetClass); return fix; } catch (IncorrectOperationException e) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateParameterFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateParameterFromUsageFix.java index 10317d9cbbba..a280e02f8c40 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateParameterFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateParameterFromUsageFix.java @@ -17,9 +17,13 @@ package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.ide.util.SuperMethodWarningUtil; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTypesUtil; @@ -67,14 +71,14 @@ public class CreateParameterFromUsageFix extends CreateVarFromUsageFix { @Override protected void invokeImpl(PsiClass targetClass) { - if (CreateFromUsageUtils.isValidReference(myReferenceExpression, true)) return; + if (CreateFromUsageUtils.isValidReference(myReferenceExpression, false)) return; final Project project = myReferenceExpression.getProject(); PsiType[] expectedTypes = CreateFromUsageUtils.guessType(myReferenceExpression, false); PsiType type = expectedTypes[0]; - String varName = myReferenceExpression.getReferenceName(); + final String varName = myReferenceExpression.getReferenceName(); PsiMethod method = PsiTreeUtil.getParentOfType(myReferenceExpression, PsiMethod.class); LOG.assertTrue(method != null); method = IntroduceParameterHandler.chooseEnclosingMethod(method); @@ -93,7 +97,8 @@ public class CreateParameterFromUsageFix extends CreateVarFromUsageFix { parameterInfos.add(parameterInfos.size() - 1, parameterInfo); } - if (ApplicationManager.getApplication().isUnitTestMode()) { + final Application application = ApplicationManager.getApplication(); + if (application.isUnitTestMode()) { ParameterInfoImpl[] array = parameterInfos.toArray(new ParameterInfoImpl[parameterInfos.size()]); String modifier = PsiUtil.getAccessModifier(PsiUtil.getAccessLevel(method.getModifierList())); ChangeSignatureProcessor processor = @@ -102,7 +107,7 @@ public class CreateParameterFromUsageFix extends CreateVarFromUsageFix { } else { final PsiMethod finalMethod = method; - ApplicationManager.getApplication().invokeLater(new Runnable() { + application.invokeLater(new Runnable() { @Override public void run() { if (project.isDisposed()) return; @@ -110,6 +115,27 @@ public class CreateParameterFromUsageFix extends CreateVarFromUsageFix { JavaChangeSignatureDialog dialog = JavaChangeSignatureDialog.createAndPreselectNew(project, finalMethod, parameterInfos, true, myReferenceExpression); dialog.setParameterInfos(parameterInfos); dialog.show(); + if (dialog.isOK()) { + for (ParameterInfoImpl info : parameterInfos) { + if (info.getOldIndex() == -1) { + final String newParamName = info.getName(); + if (!Comparing.strEqual(varName, newParamName)) { + final PsiExpression newExpr = JavaPsiFacade.getElementFactory(project).createExpressionFromText(newParamName, finalMethod); + new WriteCommandAction(project){ + @Override + protected void run(Result result) throws Throwable { + final PsiReferenceExpression[] refs = + CreateFromUsageUtils.collectExpressions(myReferenceExpression, PsiMember.class, PsiFile.class); + for (PsiReferenceExpression ref : refs) { + ref.replace(newExpr.copy()); + } + } + }.execute(); + } + break; + } + } + } } catch (Exception e) { throw new RuntimeException(e); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java index dc2963ee63e0..dfc477ac173d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java @@ -306,7 +306,13 @@ public class SimplifyBooleanExpressionFix implements IntentionAction { else { final PsiJavaToken javaToken = expression.getTokenBeforeOperand(operand); if (javaToken != null && !PsiTreeUtil.hasErrorElements(operand) && !PsiTreeUtil.hasErrorElements(lExpr)) { - resultExpression = JavaPsiFacade.getElementFactory(expression.getProject()).createExpressionFromText(lExpr.getText() + javaToken.getText() + operand.getText(), expression); + try { + resultExpression = JavaPsiFacade.getElementFactory(expression.getProject()).createExpressionFromText(lExpr.getText() + javaToken.getText() + operand.getText(), expression); + } + catch (IncorrectOperationException e) { + resultExpression = null; + LOG.error("lExpr: " + lExpr.getText() + "; op: " + javaToken.getText() + "; rExpr: " + operand.getText() + "; top: " + expression.getText()); + } } else { resultExpression = null; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableTypeFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableTypeFix.java index ecbd28d3eaae..d60b10e4a0ba 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableTypeFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableTypeFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -45,7 +45,7 @@ public class VariableTypeFix extends LocalQuickFixAndIntentionActionOnPsiElement public VariableTypeFix(@NotNull PsiVariable variable, PsiType toReturn) { super(variable); - myReturnType = toReturn != null ? GenericsUtil.getVariableTypeByExpressionType(toReturn) : null; + myReturnType = GenericsUtil.getVariableTypeByExpressionType(toReturn); myName = variable.getName(); } diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/LiteralSelectioner.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/LiteralSelectioner.java index 988f7ff4c4a8..1c51da143810 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/LiteralSelectioner.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/LiteralSelectioner.java @@ -22,7 +22,6 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.JavaTokenType; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiLiteralExpression; -import com.intellij.psi.StringEscapesTokenTypes; import java.util.List; @@ -44,25 +43,9 @@ public class LiteralSelectioner extends BasicSelectioner { List<TextRange> result = super.select(e, editorText, cursorOffset, editor); TextRange range = e.getTextRange(); - final StringLiteralLexer lexer = new StringLiteralLexer('\"', JavaTokenType.STRING_LITERAL); - lexer.start(editorText, range.getStartOffset(), range.getEndOffset()); - - while (lexer.getTokenType() != null) { - if (lexer.getTokenStart() <= cursorOffset && cursorOffset < lexer.getTokenEnd()) { - if (StringEscapesTokenTypes.STRING_LITERAL_ESCAPES.contains(lexer.getTokenType())) { - result.add(new TextRange(lexer.getTokenStart(), lexer.getTokenEnd())); - } - else { - TextRange word = SelectWordUtil.getWordSelectionRange(editorText, cursorOffset); - if (word != null) { - result.add(new TextRange(Math.max(word.getStartOffset(), lexer.getTokenStart()), - Math.min(word.getEndOffset(), lexer.getTokenEnd()))); - } - } - break; - } - lexer.advance(); - } + SelectWordUtil.addWordHonoringEscapeSequences(editorText, range, cursorOffset, + new StringLiteralLexer('\"', JavaTokenType.STRING_LITERAL), + result); result.add(new TextRange(range.getStartOffset() + 1, range.getEndOffset() - 1)); diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateConstructorHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateConstructorHandler.java index f6281302fa89..0cd7a76edde7 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateConstructorHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateConstructorHandler.java @@ -219,7 +219,8 @@ public class GenerateConstructorHandler extends GenerateMembersHandlerBase { CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject()); PsiMethod constructor = factory.createConstructor(aClass.getName(), aClass); - String modifier = PsiUtil.getMaximumModifierForMember(aClass); + String modifier = PsiUtil.getMaximumModifierForMember(aClass, false); + if (modifier != null) { PsiUtil.setModifierProperty(constructor, modifier, true); } diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java index 376238573e6b..a3c52e718a9b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java @@ -407,10 +407,9 @@ public class GenerateEqualsHelper implements Runnable { private static void addTempForDoubleInitialization(PsiField field, @NonNls StringBuilder buffer) { buffer.append(" = "); + buffer.append("Double.doubleToLongBits("); buffer.append(field.getName()); - buffer.append(" != +0.0d ? Double.doubleToLongBits("); - buffer.append(field.getName()); - buffer.append(") : 0L;\n"); + buffer.append(");\n"); } private String addTempDeclaration(@NonNls StringBuilder buffer, boolean resultDeclarationCompleted) { diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateGetterAndSetterHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateGetterAndSetterHandler.java index 5f4664cde24f..41062a1b18d1 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateGetterAndSetterHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateGetterAndSetterHandler.java @@ -20,6 +20,7 @@ import com.intellij.psi.PsiClass; import com.intellij.util.IncorrectOperationException; import java.util.ArrayList; +import java.util.Collections; public class GenerateGetterAndSetterHandler extends GenerateGetterSetterHandlerBase{ private final GenerateGetterHandler myGenerateGetterHandler = new GenerateGetterHandler(); @@ -35,9 +36,9 @@ public class GenerateGetterAndSetterHandler extends GenerateGetterSetterHandlerB GenerationInfo[] getters = myGenerateGetterHandler.generateMemberPrototypes(aClass, original); GenerationInfo[] setters = myGenerateSetterHandler.generateMemberPrototypes(aClass, original); - if (getters.length > 0 && setters.length > 0){ - array.add(getters[0]); - array.add(setters[0]); + if (getters.length + setters.length > 0){ + Collections.addAll(array, getters); + Collections.addAll(array, setters); } return array.toArray(new GenerationInfo[array.size()]); diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateGetterHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateGetterHandler.java index fcf4e67d9dd7..d7aca706b64f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateGetterHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateGetterHandler.java @@ -35,7 +35,13 @@ public class GenerateGetterHandler extends GenerateGetterSetterHandlerBase { @Override protected GenerationInfo[] generateMemberPrototypes(PsiClass aClass, ClassMember original) throws IncorrectOperationException { - if (original instanceof EncapsulatableClassMember) { + if (original instanceof PropertyClassMember) { + final PropertyClassMember propertyClassMember = (PropertyClassMember)original; + final GenerationInfo[] getters = propertyClassMember.generateGetters(); + if (getters != null) { + return getters; + } + } else if (original instanceof EncapsulatableClassMember) { final EncapsulatableClassMember encapsulatableClassMember = (EncapsulatableClassMember)original; final GenerationInfo getter = encapsulatableClassMember.generateGetter(); if (getter != null) { diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateSetterHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateSetterHandler.java index 0e6b2389121e..e33f1b8bb004 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateSetterHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateSetterHandler.java @@ -27,7 +27,14 @@ public class GenerateSetterHandler extends GenerateGetterSetterHandlerBase { @Override protected GenerationInfo[] generateMemberPrototypes(PsiClass aClass, ClassMember original) throws IncorrectOperationException { - if (original instanceof EncapsulatableClassMember) { + if (original instanceof PropertyClassMember) { + final PropertyClassMember propertyClassMember = (PropertyClassMember)original; + final GenerationInfo[] getters = propertyClassMember.generateSetters(); + if (getters != null) { + return getters; + } + } + else if (original instanceof EncapsulatableClassMember) { final EncapsulatableClassMember encapsulatableClassMember = (EncapsulatableClassMember)original; final GenerationInfo setter = encapsulatableClassMember.generateSetter(); if (setter != null) { diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GetterSetterPrototypeProvider.java b/java/java-impl/src/com/intellij/codeInsight/generation/GetterSetterPrototypeProvider.java new file mode 100644 index 000000000000..727bd8143dd9 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GetterSetterPrototypeProvider.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2013 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.generation; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.psi.PsiField; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiModifier; +import com.intellij.psi.util.PropertyUtil; + +/** + * User: anna + * Date: 3/4/13 + */ +public abstract class GetterSetterPrototypeProvider { + public static final ExtensionPointName<GetterSetterPrototypeProvider> EP_NAME = ExtensionPointName.create("com.intellij.getterSetterProvider"); + public abstract boolean canGeneratePrototypeFor(PsiField field); + public abstract PsiMethod[] generateGetters(PsiField field); + public abstract PsiMethod[] generateSetters(PsiField field); + + public abstract boolean isReadOnly(PsiField field); + + public static PsiMethod[] generateGetterSetters(PsiField field, boolean generateGetter) { + for (GetterSetterPrototypeProvider provider : Extensions.getExtensions(EP_NAME)) { + if (provider.canGeneratePrototypeFor(field)) { + return generateGetter ? provider.generateGetters(field) : provider.generateSetters(field); + } + } + return new PsiMethod[] {generateGetter ? PropertyUtil.generateGetterPrototype(field) : PropertyUtil.generateSetterPrototype(field)}; + } + + public static boolean isReadOnlyProperty(PsiField field) { + for (GetterSetterPrototypeProvider provider : Extensions.getExtensions(EP_NAME)) { + if (provider.canGeneratePrototypeFor(field)) { + return provider.isReadOnly(field); + } + } + return field.hasModifierProperty(PsiModifier.FINAL); + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java index 8a2fa775a35a..3bc0edb2b8c3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java @@ -482,7 +482,7 @@ public class OverrideImplementUtil extends OverrideImplementExploreUtil { final PsiMethodMember[] onlyPrimary = convertToMethodMembers(candidates); final PsiMethodMember[] all = ArrayUtil.mergeArrays(onlyPrimary, convertToMethodMembers(secondary)); - final Ref<Boolean> merge = Ref.create(PropertiesComponent.getInstance(project).isTrueValue(PROP_COMBINED_OVERRIDE_IMPLEMENT)); + final Ref<Boolean> merge = Ref.create(PropertiesComponent.getInstance(project).getBoolean(PROP_COMBINED_OVERRIDE_IMPLEMENT, true)); final MemberChooser<PsiMethodMember> chooser = new MemberChooser<PsiMethodMember>(toImplement || merge.get() ? all : onlyPrimary, false, true, project, PsiUtil.isLanguageLevel5OrHigher(aClass)) { @Override diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/PropertyClassMember.java b/java/java-impl/src/com/intellij/codeInsight/generation/PropertyClassMember.java new file mode 100644 index 000000000000..006e5e539932 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/generation/PropertyClassMember.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2013 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.generation; + +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.Nullable; + +/** + * User: anna + * Date: 3/4/13 + */ +public interface PropertyClassMember extends EncapsulatableClassMember { + /** + * @return PsiElement or TemplateGenerationInfo + */ + @Nullable + GenerationInfo[] generateGetters() throws IncorrectOperationException; + + /** + * @return PsiElement or TemplateGenerationInfo + */ + @Nullable + GenerationInfo[] generateSetters() throws IncorrectOperationException; +} diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java b/java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java index 9e42a4f823c7..a4817c51c320 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java @@ -16,16 +16,19 @@ package com.intellij.codeInsight.generation; import com.intellij.psi.*; -import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.psi.util.PsiFormatUtilBase; import com.intellij.psi.util.PsiUtil; +import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; + /** * @author peter */ -public class PsiFieldMember extends PsiElementClassMember<PsiField> implements EncapsulatableClassMember { +public class PsiFieldMember extends PsiElementClassMember<PsiField> implements PropertyClassMember { private static final int FIELD_OPTIONS = PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_TYPE | PsiFormatUtilBase.TYPE_AFTER; public PsiFieldMember(final PsiField field) { @@ -36,12 +39,46 @@ public class PsiFieldMember extends PsiElementClassMember<PsiField> implements E super(psiMember, substitutor, PsiFormatUtil.formatVariable(psiMember, FIELD_OPTIONS, PsiSubstitutor.EMPTY)); } + @Nullable @Override + public GenerationInfo generateGetter() throws IncorrectOperationException { + final GenerationInfo[] infos = generateGetters(); + return infos != null && infos.length > 0 ? infos[0] : null; + } + @Nullable - public PsiGenerationInfo generateGetter() { - PsiField field = getElement(); - final PsiMethod method = createMethodIfNotExists(field, PropertyUtil.generateGetterPrototype(field)); - return method != null ? new PsiGenerationInfo(method) : null; + @Override + public GenerationInfo[] generateGetters() throws IncorrectOperationException { + final PsiField field = getElement(); + return createGenerateInfos(field, GetterSetterPrototypeProvider.generateGetterSetters(field, true)); + } + + @Nullable + @Override + public GenerationInfo generateSetter() throws IncorrectOperationException { + final GenerationInfo[] infos = generateSetters(); + return infos != null && infos.length > 0 ? infos[0] : null; + } + + @Override + @Nullable + public GenerationInfo[] generateSetters() { + final PsiField field = getElement(); + if (GetterSetterPrototypeProvider.isReadOnlyProperty(field)) { + return null; + } + return createGenerateInfos(field, GetterSetterPrototypeProvider.generateGetterSetters(field, false)); + } + + private static GenerationInfo[] createGenerateInfos(PsiField field, PsiMethod[] prototypes) { + final List<GenerationInfo> methods = new ArrayList<GenerationInfo>(); + for (PsiMethod prototype : prototypes) { + final PsiMethod method = createMethodIfNotExists(field, prototype); + if (method != null) { + methods.add(new PsiGenerationInfo(method)); + } + } + return methods.isEmpty() ? null : methods.toArray(new GenerationInfo[methods.size()]); } @Nullable @@ -50,7 +87,7 @@ public class PsiFieldMember extends PsiElementClassMember<PsiField> implements E PsiMethod existing = aClass.findMethodBySignature(template, false); if (existing == null) { if (template != null) { - String modifier = PsiUtil.getMaximumModifierForMember(aClass); + String modifier = aClass.isEnum() && aClass.hasModifierProperty(PsiModifier.PUBLIC) ? null : PsiUtil.getMaximumModifierForMember(aClass); if (modifier != null) { PsiUtil.setModifierProperty(template, modifier, true); } @@ -61,15 +98,4 @@ public class PsiFieldMember extends PsiElementClassMember<PsiField> implements E return null; } } - - @Override - @Nullable - public PsiGenerationInfo generateSetter() { - PsiField field = getElement(); - if (field.hasModifierProperty(PsiModifier.FINAL)) { - return null; - } - final PsiMethod method = createMethodIfNotExists(field, PropertyUtil.generateSetterPrototype(field)); - return method == null ? null : new PsiGenerationInfo(method); - } } diff --git a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/AnnotationParameterInfoHandler.java b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/AnnotationParameterInfoHandler.java index 9242049390c6..b3434ac20c10 100644 --- a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/AnnotationParameterInfoHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/AnnotationParameterInfoHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -91,7 +91,8 @@ public class AnnotationParameterInfoHandler implements ParameterInfoHandler<PsiA public void updateParameterInfo(@NotNull final PsiAnnotationParameterList o, final UpdateParameterInfoContext context) { CharSequence chars = context.getEditor().getDocument().getCharsSequence(); int offset1 = CharArrayUtil.shiftForward(chars, context.getEditor().getCaretModel().getOffset(), " \t"); - if (chars.charAt(offset1) == ',') { + final char c = chars.charAt(offset1); + if (c == ',' || c == ')') { offset1 = CharArrayUtil.shiftBackward(chars, offset1 - 1, " \t"); } context.setHighlightedParameter(findAnnotationMethod(context.getFile(), offset1)); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddSingleMemberStaticImportAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddSingleMemberStaticImportAction.java index 04663044c59c..4f4d74c36cda 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddSingleMemberStaticImportAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddSingleMemberStaticImportAction.java @@ -102,7 +102,7 @@ public class AddSingleMemberStaticImportAction extends PsiElementBaseIntentionAc @Nullable private static PsiClass getResolvedClass(PsiElement element, PsiMember resolved) { PsiClass aClass = resolved.getContainingClass(); - if (!PsiUtil.isAccessible(aClass, element, null)) { + if (aClass != null && !PsiUtil.isAccessible(aClass, element, null)) { final PsiElement qualifier = ((PsiJavaCodeReferenceElement)element.getParent()).getQualifier(); if (qualifier instanceof PsiReferenceExpression) { final PsiElement qResolved = ((PsiReferenceExpression)qualifier).resolve(); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SurroundAutoCloseableAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SurroundAutoCloseableAction.java index d4b60392b365..5f4fb9c081eb 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SurroundAutoCloseableAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SurroundAutoCloseableAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -31,9 +31,8 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; @@ -113,78 +112,56 @@ public class SurroundAutoCloseableAction extends PsiElementBaseIntentionAction { } } - @Nullable - private static List<PsiElement> moveStatements(@NotNull final PsiElement first, final PsiElement last, final PsiTryStatement statement) { - final PsiCodeBlock tryBlock = statement.getTryBlock(); + private static List<PsiElement> moveStatements(@NotNull PsiElement first, PsiElement last, PsiTryStatement statement) { + PsiCodeBlock tryBlock = statement.getTryBlock(); assert tryBlock != null : statement.getText(); - final PsiJavaToken rBrace = tryBlock.getRBrace(); - assert rBrace != null : statement.getText(); + PsiElement parent = statement.getParent(); - final PsiElement parent = statement.getParent(); - final LocalSearchScope scope = new LocalSearchScope(parent); - List<PsiElement> toFormat = null, toDelete = null; - - final PsiElement stopAt = last.getNextSibling(); + List<PsiElement> toFormat = new SmartList<PsiElement>(); + PsiElement stopAt = last.getNextSibling(); for (PsiElement child = first; child != null && child != stopAt; child = child.getNextSibling()) { if (!(child instanceof PsiDeclarationStatement)) continue; - final PsiElement[] declaredElements = ((PsiDeclarationStatement)child).getDeclaredElements(); - int varsProcessed = 0; - for (PsiElement declared : declaredElements) { + PsiElement anchor = child; + for (PsiElement declared : ((PsiDeclarationStatement)child).getDeclaredElements()) { if (!(declared instanceof PsiLocalVariable)) continue; - final boolean contained = ReferencesSearch.search(declared, scope).forEach(new Processor<PsiReference>() { + final int endOffset = last.getTextRange().getEndOffset(); + boolean contained = ReferencesSearch.search(declared, new LocalSearchScope(parent)).forEach(new Processor<PsiReference>() { @Override public boolean process(PsiReference reference) { - return reference.getElement().getTextOffset() <= last.getTextRange().getEndOffset(); + return reference.getElement().getTextOffset() <= endOffset; } }); if (!contained) { - final PsiLocalVariable var = (PsiLocalVariable)declared; - final PsiElementFactory factory = JavaPsiFacade.getElementFactory(statement.getProject()); - final String name = var.getName(); + PsiLocalVariable var = (PsiLocalVariable)declared; + PsiElementFactory factory = JavaPsiFacade.getElementFactory(statement.getProject()); + + String name = var.getName(); assert name != null : child.getText(); + toFormat.add(parent.addBefore(factory.createVariableDeclarationStatement(name, var.getType(), null), statement)); - toFormat = plus(toFormat, parent.addBefore(factory.createVariableDeclarationStatement(name, var.getType(), null), statement)); + PsiExpression varInit = var.getInitializer(); + assert varInit != null : child.getText(); + String varAssignText = name + " = " + varInit.getText() + ";"; + anchor = parent.addAfter(factory.createStatementFromText(varAssignText, parent), anchor); - final PsiExpression varInit = var.getInitializer(); - if (varInit != null) { - final String varAssignText = name + " = " + varInit.getText() + ";"; - parent.addBefore(factory.createStatementFromText(varAssignText, parent), child.getNextSibling()); - } - - ++varsProcessed; - toDelete = plus(toDelete, declared); - declared.delete(); + var.delete(); } } - if (varsProcessed == declaredElements.length) { - toDelete = plus(toDelete, child); - } - } - - if (toDelete != null) { - for (PsiElement element : toDelete) { - if (element.isValid()) { - element.delete(); - } + if (child == last && !child.isValid()) { + last = anchor; } } - tryBlock.addRangeBefore(first, last, rBrace); + tryBlock.addRangeBefore(first, last, tryBlock.getRBrace()); parent.deleteChildRange(first, last); return toFormat; } - private static List<PsiElement> plus(@Nullable List<PsiElement> list, PsiElement element) { - if (list == null) list = ContainerUtil.newArrayList(); - list.add(element); - return list; - } - @NotNull @Override public String getFamilyName() { diff --git a/java/java-impl/src/com/intellij/codeInspection/LambdaCanBeMethReferenceInspection.java b/java/java-impl/src/com/intellij/codeInspection/LambdaCanBeMethReferenceInspection.java index 1c54bff2716e..aabb43ae6554 100644 --- a/java/java-impl/src/com/intellij/codeInspection/LambdaCanBeMethReferenceInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/LambdaCanBeMethReferenceInspection.java @@ -186,6 +186,17 @@ public class LambdaCanBeMethReferenceInspection extends BaseJavaLocalInspectionT if (usedInQualifier.get()) return null; } return methodCall; + } else if (methodCall instanceof PsiNewExpression) { + final PsiExpression[] dimensions = ((PsiNewExpression)methodCall).getArrayDimensions(); + if (dimensions.length > 0) { + final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType); + if (interfaceMethod != null) { + final PsiParameter[] psiParameters = interfaceMethod.getParameterList().getParameters(); + if (psiParameters.length == 1 && PsiType.INT.equals(psiParameters[0].getType())) { + return methodCall; + } + } + } } } return null; @@ -205,7 +216,15 @@ public class LambdaCanBeMethReferenceInspection extends BaseJavaLocalInspectionT final String methodReferenceName = methodExpression.getReferenceName(); if (qualifierExpression != null) { boolean isReceiverType = PsiMethodReferenceUtil.isReceiverType(functionalInterfaceType, containingClass, psiMethod); - methodRefText = (isReceiverType ? getClassReferenceName(containingClass) : qualifierExpression.getText()) + "::" + ((PsiMethodCallExpression)element).getTypeArgumentList().getText() + methodReferenceName; + final String qualifier; + if (isReceiverType) { + final PsiType qualifierExpressionType = qualifierExpression.getType(); + qualifier = qualifierExpressionType != null ? qualifierExpressionType.getCanonicalText() : getClassReferenceName(containingClass); + } + else { + qualifier = qualifierExpression.getText(); + } + methodRefText = qualifier + "::" + ((PsiMethodCallExpression)element).getTypeArgumentList().getText() + methodReferenceName; } else { methodRefText = @@ -229,8 +248,24 @@ public class LambdaCanBeMethReferenceInspection extends BaseJavaLocalInspectionT } } } + final PsiType newExprType = ((PsiNewExpression)element).getType(); if (containingClass != null) { - methodRefText = getClassReferenceName(containingClass) + "::new"; + methodRefText = getClassReferenceName(containingClass); + } else if (newExprType instanceof PsiArrayType){ + final PsiType deepComponentType = newExprType.getDeepComponentType(); + if (deepComponentType instanceof PsiPrimitiveType) { + methodRefText = deepComponentType.getCanonicalText(); + } + } + + if (methodRefText != null) { + if (newExprType != null) { + int dim = newExprType.getArrayDimensions(); + while (dim-- > 0) { + methodRefText += "[]"; + } + } + methodRefText += "::new"; } } return methodRefText; diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index 05f75a3a8fcf..270a3062e0f1 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -16,6 +16,7 @@ package com.intellij.codeInspection.dataFlow; import com.intellij.codeInsight.ConditionCheckManager; +import com.intellij.codeInsight.ConditionChecker; import com.intellij.codeInsight.ExceptionUtil; import com.intellij.codeInspection.dataFlow.instructions.*; import com.intellij.codeInspection.dataFlow.value.*; @@ -34,14 +35,9 @@ import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; -import static com.intellij.psi.CommonClassNames.JAVA_LANG_ERROR; -import static com.intellij.psi.CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION; -import static com.intellij.psi.CommonClassNames.JAVA_LANG_THROWABLE; +import static com.intellij.psi.CommonClassNames.*; class ControlFlowAnalyzer extends JavaElementVisitor { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer"); @@ -90,7 +86,9 @@ class ControlFlowAnalyzer extends JavaElementVisitor { pass2Flow.setFields(myFields.toArray(new DfaVariableValue[myFields.size()])); - LOG.assertTrue(myPass1Flow.getInstructionCount() == pass2Flow.getInstructionCount()); + if (myPass1Flow.getInstructionCount() != pass2Flow.getInstructionCount()) { + LOG.error(Arrays.toString(myPass1Flow.getInstructions()) + "!=\n" + Arrays.toString(pass2Flow.getInstructions())); + } addInstruction(new ReturnInstruction()); @@ -1044,7 +1042,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { rExpr.accept(this); if (!comparingRef) { - generateBoxingUnboxingInstructionFor(rExpr,castType); + generateBoxingUnboxingInstructionFor(rExpr, castType); } } @@ -1291,17 +1289,16 @@ class ControlFlowAnalyzer extends JavaElementVisitor { PsiMethod resolved = expression.resolveMethod(); if (resolved != null) { - final PsiExpressionList argList = expression.getArgumentList(); @NonNls String methodName = resolved.getName(); - PsiExpression[] params = argList.getExpressions(); + PsiExpression[] params = expression.getArgumentList().getExpressions(); PsiClass owner = resolved.getContainingClass(); final int exitPoint = getEndOffset(expression) - 1; if (owner != null) { final String className = owner.getQualifiedName(); if ("java.lang.System".equals(className)) { if ("exit".equals(methodName)) { - pushParameters(params, false, false); + pushParameters(params, -1); addInstruction(new ReturnInstruction()); return true; } @@ -1310,114 +1307,50 @@ class ControlFlowAnalyzer extends JavaElementVisitor { "junit.framework.TestCase".equals(className) || "org.testng.Assert".equals(className)) { boolean testng = "org.testng.Assert".equals(className); if ("fail".equals(methodName)) { - pushParameters(params, false, !testng); + pushParameters(params, -1); returnCheckingFinally(); return true; } - else if ("assertTrue".equals(methodName)) { - pushParameters(params, true, !testng); + + int checkedParam = testng ? 0 : params.length - 1; + if ("assertTrue".equals(methodName)) { + pushParameters(params, checkedParam); conditionalExit(exitPoint, false); return true; } - else if ("assertFalse".equals(methodName)) { - pushParameters(params, true, !testng); + if ("assertFalse".equals(methodName)) { + pushParameters(params, checkedParam); conditionalExit(exitPoint, true); return true; } - else if ("assertNull".equals(methodName)) { - pushParameters(params, true, !testng); - - addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null)); - addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, expression.getProject())); - conditionalExit(exitPoint, false); + if ("assertNull".equals(methodName)) { + pushParameters(params, checkedParam); + handleAssertNullityMethod(expression, exitPoint, false); return true; } - else if ("assertNotNull".equals(methodName)) { - pushParameters(params, true, !testng); - - addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null)); - addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, expression.getProject())); - conditionalExit(exitPoint, true); + if ("assertNotNull".equals(methodName)) { + pushParameters(params, checkedParam); + handleAssertNullityMethod(expression, exitPoint, true); return true; } return false; } } - if (ConditionCheckManager.isCheck(resolved)) { - if (ConditionCheckManager.isAssertIsNullCheckMethod(resolved)) { - int paramIndex = 0; - for (PsiExpression param : params) { - param.accept(this); - if (ConditionCheckManager.isAssertIsNullCheckMethod(resolved, paramIndex++)) { - addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null)); - addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, expression.getProject())); - conditionalExit(exitPoint, false); // Exit if Equal NULL is True - } else { - addInstruction(new PopInstruction()); - } - } - return true; - } else if (ConditionCheckManager.isAssertIsNotNullCheckMethod(resolved)) { - int paramIndex = 0; - for (PsiExpression param : params) { - param.accept(this); - if (ConditionCheckManager.isAssertIsNotNullCheckMethod(resolved, paramIndex++)) { - addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null)); - addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, expression.getProject())); - conditionalExit(exitPoint, true); // Exit if NotEqual NULL is True - } else { - addInstruction(new PopInstruction()); - } - } - return true; - } else if (ConditionCheckManager.isNullCheckMethod(resolved)) { - int paramIndex = 0; - for (PsiExpression param : params) { - param.accept(this); - if (ConditionCheckManager.isNullCheckMethod(resolved, paramIndex++)) { - addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null)); - addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, expression.getProject())); - } else { - addInstruction(new PopInstruction()); - } - } - return true; - } else if (ConditionCheckManager.isNotNullCheckMethod(resolved)) { - int paramIndex = 0; - for (PsiExpression param : params) { - param.accept(this); - if (ConditionCheckManager.isNotNullCheckMethod(resolved, paramIndex++)) { - addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null)); - addInstruction(new BinopInstruction(JavaTokenType.NE, null, expression.getProject())); - } else { - addInstruction(new PopInstruction()); - } - } - return true; - } else if (ConditionCheckManager.isAssertTrueCheckMethod(resolved)) { - int paramIndex = 0; - for (PsiExpression param : params) { - param.accept(this); - if (ConditionCheckManager.isAssertTrueCheckMethod(resolved, paramIndex++)) { - conditionalExit(exitPoint, false); - } else { - addInstruction(new PopInstruction()); - } - } - return true; - } else if (ConditionCheckManager.isAssertFalseCheckMethod(resolved)) { - int paramIndex = 0; - for (PsiExpression param : params) { - param.accept(this); - if (ConditionCheckManager.isAssertFalseCheckMethod(resolved, paramIndex++)) { - conditionalExit(exitPoint, true); - } else { - addInstruction(new PopInstruction()); - } - } - return true; + ConditionChecker checker = ConditionCheckManager.findConditionChecker(resolved); + if (checker != null) { + pushParameters(params, checker.getCheckedParameterIndex()); + + ConditionChecker.Type type = checker.getConditionCheckType(); + if (type == ConditionChecker.Type.ASSERT_IS_NULL_METHOD || type == ConditionChecker.Type.ASSERT_IS_NOT_NULL_METHOD) { + handleAssertNullityMethod(expression, exitPoint, type == ConditionChecker.Type.ASSERT_IS_NOT_NULL_METHOD); + } else if (type == ConditionChecker.Type.IS_NULL_METHOD || type == ConditionChecker.Type.IS_NOT_NULL_METHOD) { + addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null)); + addInstruction(new BinopInstruction(type == ConditionChecker.Type.IS_NULL_METHOD ? JavaTokenType.EQEQ : JavaTokenType.NE, null, expression.getProject())); + } else { //assertTrue or assertFalse + conditionalExit(exitPoint, type == ConditionChecker.Type.ASSERT_FALSE_METHOD); } + return true; } // Idea project only. @@ -1426,22 +1359,10 @@ class ControlFlowAnalyzer extends JavaElementVisitor { final PsiType qualifierType = qualifierExpression.getType(); if (qualifierType != null && qualifierType.equalsToText("com.intellij.openapi.diagnostic.Logger")) { if ("error".equals(methodName)) { - for (PsiExpression param : params) { - param.accept(this); - addInstruction(new PopInstruction()); - } + pushParameters(params, -1); returnCheckingFinally(); return true; } - else if ("assertTrue".equals(methodName)) { - params[0].accept(this); - for (int i = 1; i < params.length; i++) { - params[i].accept(this); - addInstruction(new PopInstruction()); - } - conditionalExit(exitPoint, false); - return true; - } } } } @@ -1450,21 +1371,24 @@ class ControlFlowAnalyzer extends JavaElementVisitor { return false; } + private void handleAssertNullityMethod(PsiMethodCallExpression expression, int exitPoint, boolean assertNotNull) { + addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null)); + addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, expression.getProject())); + conditionalExit(exitPoint, assertNotNull); // Exit if ==null for assertNull and != null for assertNotNull + } + private void conditionalExit(final int continuePoint, final boolean exitIfTrue) { addInstruction(new ConditionalGotoInstruction(continuePoint, exitIfTrue, null)); addInstruction(new ReturnInstruction()); pushUnknown(); } - private void pushParameters(final PsiExpression[] params, final boolean leaveOnStack, boolean lastParameterIsSignificant) { + private void pushParameters(final PsiExpression[] params, final int leaveOnStack) { for (int i = 0; i < params.length; i++) { - PsiExpression param = params[i]; - param.accept(this); - if (leaveOnStack) { - if (lastParameterIsSignificant && i == params.length - 1 || !lastParameterIsSignificant && i == 0) continue; + params[i].accept(this); + if (leaveOnStack != i) { + addInstruction(new PopInstruction()); } - - addInstruction(new PopInstruction()); } } @@ -1671,7 +1595,11 @@ class ControlFlowAnalyzer extends JavaElementVisitor { boolean isCall = expression instanceof PsiMethodCallExpression; PsiExpression qualifier = refExpr.getQualifierExpression(); if (qualifier == null) { - return myFactory.getVarFactory().createVariableValue(var, refExpr.getType(), false, null, isCall); + DfaVariableValue result = myFactory.getVarFactory().createVariableValue(var, refExpr.getType(), false, null, isCall); + if (var instanceof PsiField) { + myFields.add(result); + } + return result; } if (DfaUtil.isFinalField(var) || DfaUtil.isPlainMutableField(var)) { diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java index 6a1ce9b2e82d..0340029fa713 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java @@ -255,8 +255,13 @@ public class DataFlowRunner { private void checkEnvironment(DataFlowRunner runner, DfaMemoryState memState, @Nullable PsiElement anchor) { if (myClassParent == anchor) { - DfaMemoryState copy = memState.createCopy(); + DfaMemoryStateImpl copy = (DfaMemoryStateImpl)memState.createCopy(); copy.flushFields(runner); + Set<DfaVariableValue> vars = new HashSet<DfaVariableValue>(copy.getVariableStates().keySet()); + for (DfaVariableValue value : vars) { + copy.flushDependencies(value); + } + myClosureStates.add(copy); } } diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java index 87e0d2dad351..547d8a47dc81 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java @@ -772,7 +772,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState { for (DfaVariableValue field : runner.getFields()) { if (myVariableStates.containsKey(field) || getEqClassIndex(field) >= 0) { if (!DfaUtil.isFinalField(field.getPsiVariable())) { - flushWithDependencies(field); + flushVariable(field); getVariableState(field).setNullable(false); } } @@ -780,16 +780,16 @@ public class DfaMemoryStateImpl implements DfaMemoryState { } public void flushVariable(@NotNull DfaVariableValue variable) { - flushWithDependencies(variable); + doFlush(variable); + flushDependencies(variable); } @Override public void flushVariableOutOfScope(DfaVariableValue variable) { - flushWithDependencies(variable); + flushVariable(variable); } - private void flushWithDependencies(DfaVariableValue variable) { - doFlush(variable); + public void flushDependencies(DfaVariableValue variable) { for (DfaVariableValue dependent : myFactory.getVarFactory().getAllQualifiedBy(variable)) { doFlush(dependent); } diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java index d68679796fc4..dcc4a3f290d9 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java @@ -159,8 +159,8 @@ public class DfaValueFactory { if (qualifier == null) { return true; } - if (qualifier instanceof PsiThisExpression){ - final PsiJavaCodeReferenceElement thisQualifier = ((PsiThisExpression)qualifier).getQualifier(); + if (qualifier instanceof PsiThisExpression || qualifier instanceof PsiSuperExpression) { + final PsiJavaCodeReferenceElement thisQualifier = ((PsiQualifiedExpression)qualifier).getQualifier(); if (thisQualifier == null) return true; final PsiClass innerMostClass = PsiTreeUtil.getParentOfType(refExpression, PsiClass.class); if (innerMostClass == thisQualifier.resolve()) { diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java index f56fcd8290eb..1a74dde51351 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java @@ -30,6 +30,7 @@ import com.intellij.psi.PsiType; import com.intellij.psi.PsiVariable; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -51,6 +52,7 @@ public class DfaVariableValue extends DfaValue { public DfaVariableValue createVariableValue(PsiVariable myVariable, boolean isNegated) { return createVariableValue(myVariable, myVariable.getType(), isNegated, null, false); } + @NotNull public DfaVariableValue createVariableValue(PsiVariable myVariable, @Nullable PsiType varType, boolean isNegated, @Nullable DfaVariableValue qualifier, boolean viaMethods) { mySharedInstance.myVariable = myVariable; diff --git a/java/java-impl/src/com/intellij/codeInspection/deprecation/DeprecatedDefenderSyntaxInspection.java b/java/java-impl/src/com/intellij/codeInspection/deprecation/DeprecatedDefenderSyntaxInspection.java deleted file mode 100644 index 1a9024d14e9f..000000000000 --- a/java/java-impl/src/com/intellij/codeInspection/deprecation/DeprecatedDefenderSyntaxInspection.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2000-2012 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.deprecation; - -import com.intellij.codeInspection.*; -import com.intellij.openapi.project.Project; -import com.intellij.psi.*; -import com.intellij.psi.impl.source.PsiModifierListImpl; -import com.intellij.psi.util.PsiUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -// todo[r.sh] drop this after transition period finished -public class DeprecatedDefenderSyntaxInspection extends BaseJavaLocalInspectionTool { - private final LocalQuickFix myQuickFix = new MyQuickFix(); - - @Nullable - @Override - public ProblemDescriptor[] checkMethod(@NotNull PsiMethod method, @NotNull InspectionManager manager, boolean isOnTheFly) { - final PsiJavaToken marker = PsiModifierListImpl.findExtensionMethodMarker(method); - return marker == null ? null : new ProblemDescriptor[]{ - manager.createProblemDescriptor(marker, getDisplayName(), myQuickFix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly) - }; - } - - private static class MyQuickFix implements LocalQuickFix { - @NotNull - @Override - public String getName() { - return InspectionsBundle.message("deprecated.defender.syntax.fix"); - } - - @NotNull - @Override - public String getFamilyName() { - return ""; - } - - @Override - public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - final PsiElement marker = descriptor.getPsiElement(); - if (marker != null && PsiUtil.isJavaToken(marker, JavaTokenType.DEFAULT_KEYWORD)) { - final PsiElement parent = marker.getParent(); - if (parent instanceof PsiMethod) { - marker.delete(); - final PsiMethod method = (PsiMethod)parent; - if (!method.hasModifierProperty(PsiModifier.DEFAULT)) { - PsiUtil.setModifierProperty(method, PsiModifier.DEFAULT, true); - } - } - } - } - } -} diff --git a/java/java-impl/src/com/intellij/codeInspection/deprecation/DeprecationInspection.java b/java/java-impl/src/com/intellij/codeInspection/deprecation/DeprecationInspection.java index ab940b08e54e..6016b5cf72de 100644 --- a/java/java-impl/src/com/intellij/codeInspection/deprecation/DeprecationInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/deprecation/DeprecationInspection.java @@ -45,10 +45,11 @@ public class DeprecationInspection extends BaseJavaLocalInspectionTool { public boolean IGNORE_INSIDE_DEPRECATED = false; public boolean IGNORE_ABSTRACT_DEPRECATED_OVERRIDES = true; + public boolean IGNORE_IMPORT_STATEMENTS = true; @NotNull public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { - return new DeprecationElementVisitor(holder, IGNORE_INSIDE_DEPRECATED, IGNORE_ABSTRACT_DEPRECATED_OVERRIDES); + return new DeprecationElementVisitor(holder, IGNORE_INSIDE_DEPRECATED, IGNORE_ABSTRACT_DEPRECATED_OVERRIDES, IGNORE_IMPORT_STATEMENTS); } @NotNull @@ -80,6 +81,7 @@ public class DeprecationInspection extends BaseJavaLocalInspectionTool { public JComponent createOptionsPanel() { final MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this); panel.addCheckbox("Ignore inside deprecated members", "IGNORE_INSIDE_DEPRECATED"); + panel.addCheckbox("Ignore inside non-static imports", "IGNORE_IMPORT_STATEMENTS"); panel.addCheckbox("<html>Ignore overrides of deprecated abstract methods from non-deprecated supers</html>", "IGNORE_ABSTRACT_DEPRECATED_OVERRIDES"); return panel; @@ -89,20 +91,32 @@ public class DeprecationInspection extends BaseJavaLocalInspectionTool { private final ProblemsHolder myHolder; private final boolean myIgnoreInsideDeprecated; private final boolean myIgnoreAbstractDeprecatedOverrides; + private final boolean myIgnoreImportStatements; public DeprecationElementVisitor(final ProblemsHolder holder, boolean ignoreInsideDeprecated, - boolean ignoreAbstractDeprecatedOverrides) { + boolean ignoreAbstractDeprecatedOverrides, + boolean ignoreImportStatements) { myHolder = holder; myIgnoreInsideDeprecated = ignoreInsideDeprecated; myIgnoreAbstractDeprecatedOverrides = ignoreAbstractDeprecatedOverrides; + myIgnoreImportStatements = ignoreImportStatements; } - @Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { - JavaResolveResult result = reference.advancedResolve(true); - PsiElement resolved = result.getElement(); - checkDeprecated(resolved, reference.getReferenceNameElement(), null, myIgnoreInsideDeprecated, myHolder); + @Override + public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { + JavaResolveResult result = reference.advancedResolve(true); + PsiElement resolved = result.getElement(); + checkDeprecated(resolved, reference.getReferenceNameElement(), null, myIgnoreInsideDeprecated, myIgnoreImportStatements, myHolder); + } + + @Override + public void visitImportStaticStatement(PsiImportStaticStatement statement) { + final PsiJavaCodeReferenceElement importReference = statement.getImportReference(); + if (importReference != null) { + checkDeprecated(importReference.resolve(), importReference.getReferenceNameElement(), null, myIgnoreInsideDeprecated, false, myHolder); } + } @Override public void visitReferenceExpression(PsiReferenceExpression expression) { visitReferenceElement(expression); @@ -131,7 +145,7 @@ public class DeprecationInspection extends BaseJavaLocalInspectionTool { PsiMethod constructor = result == null ? null : result.getElement(); if (constructor != null && expression.getClassOrAnonymousClassReference() != null) { if (expression.getClassReference() == null && constructor.getParameterList().getParametersCount() == 0) return; - checkDeprecated(constructor, expression.getClassOrAnonymousClassReference(), null, myIgnoreInsideDeprecated, myHolder); + checkDeprecated(constructor, expression.getClassOrAnonymousClassReference(), null, myIgnoreInsideDeprecated, myIgnoreImportStatements, myHolder); } } } @@ -223,13 +237,14 @@ public class DeprecationInspection extends BaseJavaLocalInspectionTool { PsiElement elementToHighlight, @Nullable TextRange rangeInElement, ProblemsHolder holder) { - checkDeprecated(refElement, elementToHighlight, rangeInElement, false, holder); + checkDeprecated(refElement, elementToHighlight, rangeInElement, false, false, holder); } public static void checkDeprecated(PsiElement refElement, PsiElement elementToHighlight, @Nullable TextRange rangeInElement, boolean ignoreInsideDeprecated, + boolean ignoreImportStatements, ProblemsHolder holder) { if (!(refElement instanceof PsiDocCommentOwner)) return; if (!((PsiDocCommentOwner)refElement).isDeprecated()) return; @@ -241,7 +256,7 @@ public class DeprecationInspection extends BaseJavaLocalInspectionTool { } } - if (PsiTreeUtil.getParentOfType(elementToHighlight, PsiImportStatementBase.class) != null) { + if (ignoreImportStatements && PsiTreeUtil.getParentOfType(elementToHighlight, PsiImportStatementBase.class) != null) { return; } diff --git a/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java b/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java index 8d8136c3893f..6da227b3b3d3 100644 --- a/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java +++ b/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java @@ -219,7 +219,7 @@ public class NullityInferrer { } private void registerAnnotation(@NotNull PsiModifierListOwner method, boolean isNullable) { - final SmartPsiElementPointer<PsiModifierListOwner> methodPointer = myPointerManager.createLazyPointer(method); + final SmartPsiElementPointer<PsiModifierListOwner> methodPointer = myPointerManager.createSmartPsiElementPointer(method); if (isNullable) { myNullableSet.add(methodPointer); } @@ -420,7 +420,7 @@ public class NullityInferrer { if (NullableNotNullManager.isNotNull(owner)) { return true; } - final SmartPsiElementPointer<PsiModifierListOwner> pointer = myPointerManager.createLazyPointer(owner); + final SmartPsiElementPointer<PsiModifierListOwner> pointer = myPointerManager.createSmartPsiElementPointer(owner); return myNotNullSet.contains(pointer); } @@ -428,7 +428,7 @@ public class NullityInferrer { if (NullableNotNullManager.isNullable(owner)) { return true; } - final SmartPsiElementPointer<PsiModifierListOwner> pointer = myPointerManager.createLazyPointer(owner); + final SmartPsiElementPointer<PsiModifierListOwner> pointer = myPointerManager.createSmartPsiElementPointer(owner); return myNullableSet.contains(pointer); } diff --git a/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java b/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java index b59d821bbecf..b6b535c2c918 100644 --- a/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java @@ -374,7 +374,12 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { fix = superMethodApplicable ? null : createChangeDefaultNotNullFix(nullableManager, method); } - holder.registerProblem(annotation, InspectionsBundle.message("nullable.stuff.problems.overridden.methods.are.not.annotated"), + PsiElement psiElement = annotation; + if (!annotation.isPhysical()) { + psiElement = method.getNameIdentifier(); + if (psiElement == null) continue; + } + holder.registerProblem(psiElement, InspectionsBundle.message("nullable.stuff.problems.overridden.methods.are.not.annotated"), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, wrapFix(fix)); methodQuickFixSuggested = true; @@ -387,10 +392,18 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { if (parameterAnnotated[i] && !nullableManager.isNotNull(parameter, false) && !nullableManager.isNullable(parameter, false)) { parameters[i].getNameIdentifier(); //be sure that corresponding tree element available PsiAnnotation annotation = AnnotationUtil.findAnnotation(parameters[i], nullableManager.getNotNulls()); - holder.registerProblem(annotation, + PsiElement psiElement = annotation; + if (!annotation.isPhysical()) { + psiElement = parameters[i].getNameIdentifier(); + if (psiElement == null) continue; + } + holder.registerProblem(psiElement, InspectionsBundle.message("nullable.stuff.problems.overridden.method.parameters.are.not.annotated"), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - wrapFix(!applicable ? createChangeDefaultNotNullFix(nullableManager, parameters[i]) : new AnnotateOverriddenMethodParameterFix(defaultNotNull, nullableManager.getDefaultNullable()))); + wrapFix(!applicable + ? createChangeDefaultNotNullFix(nullableManager, parameters[i]) + : new AnnotateOverriddenMethodParameterFix(defaultNotNull, + nullableManager.getDefaultNullable()))); parameterQuickFixSuggested[i] = true; } } diff --git a/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyInspection.java b/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyInspection.java index b88c88d6209c..049811978cc9 100644 --- a/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyInspection.java @@ -27,10 +27,12 @@ import java.util.Set; */ public class UnnecessaryModuleDependencyInspection extends GlobalInspectionTool { + @Override public RefGraphAnnotator getAnnotator(final RefManager refManager) { return new UnnecessaryModuleDependencyAnnotator(refManager); } + @Override public CommonProblemDescriptor[] checkElement(RefEntity refEntity, AnalysisScope scope, InspectionManager manager, final GlobalInspectionContext globalContext) { if (refEntity instanceof RefModule){ final RefModule refModule = (RefModule)refEntity; @@ -46,8 +48,10 @@ public class UnnecessaryModuleDependencyInspection extends GlobalInspectionTool InspectionsBundle.message("unnecessary.module.dependency.problem.descriptor", module.getName(), dependency.getName()), new RemoveModuleDependencyFix(module, dependency)); } else { - problemDescriptor = manager.createProblemDescriptor( - InspectionsBundle.message("suspected.module.dependency.problem.descriptor", module.getName(), dependency.getName(), scope.getDisplayName(), dependency.getName()), null); + String message = InspectionsBundle + .message("suspected.module.dependency.problem.descriptor", module.getName(), dependency.getName(), scope.getDisplayName(), + dependency.getName()); + problemDescriptor = manager.createProblemDescriptor(message); } descriptors.add(problemDescriptor); } @@ -57,16 +61,19 @@ public class UnnecessaryModuleDependencyInspection extends GlobalInspectionTool return null; } + @Override @NotNull public String getGroupDisplayName() { return GroupNames.DECLARATION_REDUNDANCY; } + @Override @NotNull public String getDisplayName() { return InspectionsBundle.message("unnecessary.module.dependency.display.name"); } + @Override @NotNull @NonNls public String getShortName() { @@ -82,16 +89,19 @@ public class UnnecessaryModuleDependencyInspection extends GlobalInspectionTool myDependency = dependency; } + @Override @NotNull public String getName() { return "Remove dependency"; } + @Override @NotNull public String getFamilyName() { return getName(); } + @Override public void applyFix(@NotNull Project project, @NotNull CommonProblemDescriptor descriptor) { final ModifiableRootModel model = ModuleRootManager.getInstance(myModule).getModifiableModel(); for (OrderEntry entry : model.getOrderEntries()) { diff --git a/java/java-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrowsDeclaration.java b/java/java-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrowsDeclaration.java index daf3868dd728..3acbb69316b4 100644 --- a/java/java-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrowsDeclaration.java +++ b/java/java-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrowsDeclaration.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -31,8 +31,8 @@ import java.util.HashSet; import java.util.Set; /** - * User: anna - * Date: 15-Nov-2005 + * @author anna + * @since 15-Nov-2005 */ public class RedundantThrowsDeclaration extends BaseJavaLocalInspectionTool { @NotNull @@ -66,10 +66,8 @@ public class RedundantThrowsDeclaration extends BaseJavaLocalInspectionTool { return problems.isEmpty() ? null : problems.toArray(new ProblemDescriptor[problems.size()]); } - - - //@top - private static ProblemDescriptor checkExceptionsNeverThrown(PsiJavaCodeReferenceElement referenceElement, InspectionManager inspectionManager, + private static ProblemDescriptor checkExceptionsNeverThrown(PsiJavaCodeReferenceElement referenceElement, + InspectionManager inspectionManager, boolean onTheFly) { if (!(referenceElement.getParent() instanceof PsiReferenceList)) return null; PsiReferenceList referenceList = (PsiReferenceList)referenceElement.getParent(); @@ -111,8 +109,7 @@ public class RedundantThrowsDeclaration extends BaseJavaLocalInspectionTool { } for (PsiClassType unhandledException : unhandled) { - if (unhandledException.isAssignableFrom(exceptionType) || - exceptionType.isAssignableFrom(unhandledException)) { + if (unhandledException.isAssignableFrom(exceptionType) || exceptionType.isAssignableFrom(unhandledException)) { return null; } } @@ -120,10 +117,7 @@ public class RedundantThrowsDeclaration extends BaseJavaLocalInspectionTool { if (HighlightMethodUtil.isSerializationRelatedMethod(method, containingClass)) return null; String description = JavaErrorMessages.message("exception.is.never.thrown", HighlightUtil.formatType(exceptionType)); - - final LocalQuickFix quickFixes = new DeleteThrowsFix(method, exceptionType); - return inspectionManager.createProblemDescriptor(referenceElement, description, quickFixes, ProblemHighlightType.LIKE_UNUSED_SYMBOL, - onTheFly); + LocalQuickFix quickFixes = new DeleteThrowsFix(method, exceptionType); + return inspectionManager.createProblemDescriptor(referenceElement, description, quickFixes, ProblemHighlightType.LIKE_UNUSED_SYMBOL, onTheFly); } - } diff --git a/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/ClassSmartPointerNode.java b/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/ClassSmartPointerNode.java index 39354b112f1a..f8245a99d042 100644 --- a/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/ClassSmartPointerNode.java +++ b/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/ClassSmartPointerNode.java @@ -28,7 +28,7 @@ import java.util.Collection; public class ClassSmartPointerNode extends BaseSmartPointerPsiNode<SmartPsiElementPointer>{ public ClassSmartPointerNode(Project project, PsiClass value, ViewSettings viewSettings) { - super(project, SmartPointerManager.getInstance(project).createLazyPointer(value), viewSettings); + super(project, SmartPointerManager.getInstance(project).createSmartPsiElementPointer(value), viewSettings); } public ClassSmartPointerNode(Project project, Object value, ViewSettings viewSettings) { diff --git a/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/FieldSmartPointerNode.java b/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/FieldSmartPointerNode.java index 8c30361b446a..8cb5ff2aba06 100644 --- a/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/FieldSmartPointerNode.java +++ b/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/FieldSmartPointerNode.java @@ -33,7 +33,7 @@ import java.util.Collections; public class FieldSmartPointerNode extends BaseSmartPointerPsiNode<SmartPsiElementPointer>{ public FieldSmartPointerNode(Project project, PsiField value, ViewSettings viewSettings) { - super(project, SmartPointerManager.getInstance(project).createLazyPointer(value), viewSettings); + super(project, SmartPointerManager.getInstance(project).createSmartPsiElementPointer(value), viewSettings); } public FieldSmartPointerNode(final Project project, final Object value, final ViewSettings viewSettings) { diff --git a/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/MethodSmartPointerNode.java b/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/MethodSmartPointerNode.java index e39e06c1dee9..7a81588166a5 100644 --- a/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/MethodSmartPointerNode.java +++ b/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/MethodSmartPointerNode.java @@ -32,7 +32,7 @@ import java.util.Collections; public class MethodSmartPointerNode extends BaseSmartPointerPsiNode<SmartPsiElementPointer>{ public MethodSmartPointerNode(Project project, PsiMethod value, ViewSettings viewSettings) { - super(project, SmartPointerManager.getInstance(project).createLazyPointer(value), viewSettings); + super(project, SmartPointerManager.getInstance(project).createSmartPsiElementPointer(value), viewSettings); } public MethodSmartPointerNode(final Project project, final Object value, final ViewSettings viewSettings) { diff --git a/java/java-impl/src/com/intellij/openapi/options/colors/pages/JavaColorSettingsPage.java b/java/java-impl/src/com/intellij/openapi/options/colors/pages/JavaColorSettingsPage.java index 3c584077122e..8697b8b37558 100644 --- a/java/java-impl/src/com/intellij/openapi/options/colors/pages/JavaColorSettingsPage.java +++ b/java/java-impl/src/com/intellij/openapi/options/colors/pages/JavaColorSettingsPage.java @@ -18,8 +18,6 @@ package com.intellij.openapi.options.colors.pages; import com.intellij.application.options.colors.InspectionColorSettingsPage; import com.intellij.ide.highlighter.JavaFileHighlighter; import com.intellij.ide.highlighter.JavaHighlightingColors; -import com.intellij.openapi.editor.HighlighterColors; -import com.intellij.openapi.editor.SyntaxHighlighterColors; import com.intellij.openapi.editor.colors.CodeInsightColors; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.fileTypes.StdFileTypes; @@ -181,7 +179,7 @@ public class JavaColorSettingsPage implements ColorSettingsPage, InspectionColor " int <localVar>a</localVar> = <implicitAnonymousParameter>localVar</implicitAnonymousParameter>;\n" + " }\n" + " };\n" + - " <reassignedParameter>reassignedParam</reassignedParameter> = new int[2];\n" + + " <reassignedParameter>reassignedParam</reassignedParameter> = new <constructorCall>ArrayList</constructorCall><<class>String</class>>().toArray(new int[0]);\n" + " }\n" + "}\n" + "enum <enum>AnEnum</enum> { <static_final>CONST1</static_final>, <static_final>CONST2</static_final> }\n"+ diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java index 456d49988305..d98845db4499 100644 --- a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java +++ b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java @@ -18,12 +18,12 @@ package com.intellij.psi.codeStyle.arrangement; import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; -import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType; -import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType; -import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier; +import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken; +import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens; import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; import com.intellij.psi.util.PropertyUtil; +import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,37 +33,41 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; +import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.*; +import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.*; + public class JavaArrangementVisitor extends JavaElementVisitor { - + private static final String NULL_CONTENT = "no content"; - - private static final Map<String, ArrangementModifier> MODIFIERS = new HashMap<String, ArrangementModifier>(); + + private static final Map<String, ArrangementSettingsToken> MODIFIERS = ContainerUtilRt.newHashMap(); + static { - MODIFIERS.put(PsiModifier.PUBLIC, ArrangementModifier.PUBLIC); - MODIFIERS.put(PsiModifier.PROTECTED, ArrangementModifier.PROTECTED); - MODIFIERS.put(PsiModifier.PRIVATE, ArrangementModifier.PRIVATE); - MODIFIERS.put(PsiModifier.PACKAGE_LOCAL, ArrangementModifier.PACKAGE_PRIVATE); - MODIFIERS.put(PsiModifier.STATIC, ArrangementModifier.STATIC); - MODIFIERS.put(PsiModifier.FINAL, ArrangementModifier.FINAL); - MODIFIERS.put(PsiModifier.TRANSIENT, ArrangementModifier.TRANSIENT); - MODIFIERS.put(PsiModifier.VOLATILE, ArrangementModifier.VOLATILE); - MODIFIERS.put(PsiModifier.SYNCHRONIZED, ArrangementModifier.SYNCHRONIZED); - MODIFIERS.put(PsiModifier.ABSTRACT, ArrangementModifier.ABSTRACT); + MODIFIERS.put(PsiModifier.PUBLIC, PUBLIC); + MODIFIERS.put(PsiModifier.PROTECTED, PROTECTED); + MODIFIERS.put(PsiModifier.PRIVATE, PRIVATE); + MODIFIERS.put(PsiModifier.PACKAGE_LOCAL, PACKAGE_PRIVATE); + MODIFIERS.put(PsiModifier.STATIC, STATIC); + MODIFIERS.put(PsiModifier.FINAL, FINAL); + MODIFIERS.put(PsiModifier.TRANSIENT, TRANSIENT); + MODIFIERS.put(PsiModifier.VOLATILE, VOLATILE); + MODIFIERS.put(PsiModifier.SYNCHRONIZED, SYNCHRONIZED); + MODIFIERS.put(PsiModifier.ABSTRACT, ABSTRACT); } @NotNull private final Stack<JavaElementArrangementEntry> myStack = new Stack<JavaElementArrangementEntry>(); @NotNull private final Map<PsiElement, JavaElementArrangementEntry> myEntries = new HashMap<PsiElement, JavaElementArrangementEntry>(); - @NotNull private final JavaArrangementParseInfo myInfo; - @NotNull private final Collection<TextRange> myRanges; - @NotNull private final Set<ArrangementGroupingType> myGroupingRules; - @NotNull private final MethodBodyProcessor myMethodBodyProcessor; - @Nullable private final Document myDocument; + @NotNull private final JavaArrangementParseInfo myInfo; + @NotNull private final Collection<TextRange> myRanges; + @NotNull private final Set<ArrangementSettingsToken> myGroupingRules; + @NotNull private final MethodBodyProcessor myMethodBodyProcessor; + @Nullable private final Document myDocument; public JavaArrangementVisitor(@NotNull JavaArrangementParseInfo infoHolder, @Nullable Document document, @NotNull Collection<TextRange> ranges, - @NotNull Set<ArrangementGroupingType> groupingRules) + @NotNull Set<ArrangementSettingsToken> groupingRules) { myInfo = infoHolder; myDocument = document; @@ -74,12 +78,12 @@ public class JavaArrangementVisitor extends JavaElementVisitor { @Override public void visitClass(PsiClass aClass) { - ArrangementEntryType type = ArrangementEntryType.CLASS; + ArrangementSettingsToken type = CLASS; if (aClass.isEnum()) { - type = ArrangementEntryType.ENUM; + type = ENUM; } else if (aClass.isInterface()) { - type = ArrangementEntryType.INTERFACE; + type = INTERFACE; } JavaElementArrangementEntry entry = createNewEntry(aClass, aClass.getTextRange(), type, aClass.getName(), true); processEntry(entry, aClass, aClass); @@ -88,7 +92,7 @@ public class JavaArrangementVisitor extends JavaElementVisitor { @Override public void visitAnonymousClass(PsiAnonymousClass aClass) { JavaElementArrangementEntry entry = createNewEntry( - aClass, aClass.getTextRange(), ArrangementEntryType.ANONYMOUS_CLASS, aClass.getName(), false + aClass, aClass.getTextRange(), ANONYMOUS_CLASS, aClass.getName(), false ); processEntry(entry, null, aClass); } @@ -104,34 +108,32 @@ public class JavaArrangementVisitor extends JavaElementVisitor { public void visitField(PsiField field) { // There is a possible case that more than one field is declared for the same type like 'int i, j;'. We want to process only // the first one then. - for (PsiElement e = field.getPrevSibling(); e != null; e = e.getPrevSibling()) { - if (e instanceof PsiWhiteSpace) { - continue; - } - if (e instanceof PsiJavaToken && ((PsiJavaToken)e).getTokenType() == JavaTokenType.COMMA) { - return; - } - else { - break; - } + PsiElement fieldPrev = getPreviousNonWsComment(field.getPrevSibling(), 0); + if (fieldPrev instanceof PsiJavaToken && ((PsiJavaToken)fieldPrev).getTokenType() == JavaTokenType.COMMA) { + return; } - + // There is a possible case that fields which share the same type declaration are located on different document lines, e.g.: // int i1, // i2; // We want to consider only the first declaration then but need to expand its range to all affected lines (up to semicolon). TextRange range = field.getTextRange(); PsiElement child = field.getLastChild(); - boolean needProcessing; - if (child instanceof PsiJavaToken) { - needProcessing = ((PsiJavaToken)child).getTokenType() != JavaTokenType.SEMICOLON; + boolean needSpecialProcessing = true; + if (isSemicolon(child)) { + needSpecialProcessing = false; } - else { - needProcessing = true; + else if (child instanceof PsiComment) { + // There is a possible field definition like below: + // int f; // my comment. + // The comment goes into field PSI here, that's why we need to handle it properly. + PsiElement prev = getPreviousNonWsComment(child, range.getStartOffset()); + needSpecialProcessing = prev != null && !isSemicolon(prev); } - if (needProcessing) { + + if (needSpecialProcessing) { for (PsiElement e = field.getNextSibling(); e != null; e = e.getNextSibling()) { - if (e instanceof PsiWhiteSpace) { // Skip white space + if (e instanceof PsiWhiteSpace || e instanceof PsiComment) { // Skip white space and comment continue; } else if (e instanceof PsiJavaToken) { @@ -144,7 +146,10 @@ public class JavaArrangementVisitor extends JavaElementVisitor { } else if (e instanceof PsiField) { PsiElement c = e.getLastChild(); - // Stop is field with semicolon has been found. + if (c != null) { + c = getPreviousNonWsComment(c, range.getStartOffset()); + } + // Stop if current field ends by a semicolon. if (c instanceof PsiErrorElement // Incomplete field without trailing semicolon || (c instanceof PsiJavaToken && ((PsiJavaToken)c).getTokenType() == JavaTokenType.SEMICOLON)) { @@ -157,13 +162,31 @@ public class JavaArrangementVisitor extends JavaElementVisitor { break; } } - JavaElementArrangementEntry entry = createNewEntry(field, range, ArrangementEntryType.FIELD, field.getName(), true); + JavaElementArrangementEntry entry = createNewEntry(field, range, FIELD, field.getName(), true); processEntry(entry, field, field.getInitializer()); } + @Nullable + private static PsiElement getPreviousNonWsComment(@Nullable PsiElement element, int minOffset) { + if (element == null) { + return null; + } + for (PsiElement e = element; e != null && e.getTextRange().getStartOffset() >= minOffset; e = e.getPrevSibling()) { + if (e instanceof PsiWhiteSpace || e instanceof PsiComment) { + continue; + } + return e; + } + return null; + } + + private static boolean isSemicolon(@Nullable PsiElement e) { + return e instanceof PsiJavaToken && ((PsiJavaToken)e).getTokenType() == JavaTokenType.SEMICOLON; + } + @Override public void visitClassInitializer(PsiClassInitializer initializer) { - JavaElementArrangementEntry entry = createNewEntry(initializer, initializer.getTextRange(), ArrangementEntryType.FIELD, null, true); + JavaElementArrangementEntry entry = createNewEntry(initializer, initializer.getTextRange(), FIELD, null, true); if (entry == null) { return; } @@ -192,7 +215,7 @@ public class JavaArrangementVisitor extends JavaElementVisitor { @Override public void visitMethod(PsiMethod method) { - ArrangementEntryType type = method.isConstructor() ? ArrangementEntryType.CONSTRUCTOR : ArrangementEntryType.METHOD; + ArrangementSettingsToken type = method.isConstructor() ? CONSTRUCTOR : METHOD; JavaElementArrangementEntry entry = createNewEntry(method, method.getTextRange(), type, method.getName(), true); if (entry == null) { return; @@ -217,7 +240,7 @@ public class JavaArrangementVisitor extends JavaElementVisitor { } private void parseProperties(PsiMethod method, JavaElementArrangementEntry entry) { - if (!myGroupingRules.contains(ArrangementGroupingType.GETTERS_AND_SETTERS)) { + if (!myGroupingRules.contains(StdArrangementTokens.Grouping.GETTERS_AND_SETTERS)) { return; } @@ -264,7 +287,7 @@ public class JavaArrangementVisitor extends JavaElementVisitor { return; } JavaElementArrangementEntry entry = - createNewEntry(anonymousClass, anonymousClass.getTextRange(), ArrangementEntryType.CLASS, anonymousClass.getName(), false); + createNewEntry(anonymousClass, anonymousClass.getTextRange(), CLASS, anonymousClass.getName(), false); processEntry(entry, null, anonymousClass); } @@ -307,7 +330,7 @@ public class JavaArrangementVisitor extends JavaElementVisitor { @Nullable private JavaElementArrangementEntry createNewEntry(@NotNull PsiElement element, @NotNull TextRange range, - @NotNull ArrangementEntryType type, + @NotNull ArrangementSettingsToken type, @Nullable String name, boolean canArrange) { @@ -356,14 +379,14 @@ public class JavaArrangementVisitor extends JavaElementVisitor { } for (String modifier : PsiModifier.MODIFIERS) { if (modifierList.hasModifierProperty(modifier)) { - ArrangementModifier arrangementModifier = MODIFIERS.get(modifier); + ArrangementSettingsToken arrangementModifier = MODIFIERS.get(modifier); if (arrangementModifier != null) { entry.addModifier(arrangementModifier); } } } if (modifierList.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) { - entry.addModifier(ArrangementModifier.PACKAGE_PRIVATE); + entry.addModifier(PACKAGE_PRIVATE); } } diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaElementArrangementEntry.java b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaElementArrangementEntry.java index 3e8499813fa3..b5fad6c02be2 100644 --- a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaElementArrangementEntry.java +++ b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaElementArrangementEntry.java @@ -17,12 +17,11 @@ package com.intellij.psi.codeStyle.arrangement; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType; -import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier; +import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken; +import com.intellij.util.containers.ContainerUtilRt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.EnumSet; import java.util.Set; /** @@ -35,15 +34,15 @@ public class JavaElementArrangementEntry extends DefaultArrangementEntry implements TypeAwareArrangementEntry, NameAwareArrangementEntry,ModifierAwareArrangementEntry { - private final Set<ArrangementModifier> myModifiers = EnumSet.noneOf(ArrangementModifier.class); + @NotNull private final Set<ArrangementSettingsToken> myModifiers = ContainerUtilRt.newHashSet(); + @NotNull private final Set<ArrangementSettingsToken> myTypes = ContainerUtilRt.newHashSet(); - @NotNull private final Set<ArrangementEntryType> myTypes; - @NotNull private final ArrangementEntryType myType; - @Nullable private final String myName; + @NotNull private final ArrangementSettingsToken myType; + @Nullable private final String myName; public JavaElementArrangementEntry(@Nullable ArrangementEntry parent, @NotNull TextRange range, - @NotNull ArrangementEntryType type, + @NotNull ArrangementSettingsToken type, @Nullable String name, boolean canBeMatched) { @@ -53,26 +52,23 @@ public class JavaElementArrangementEntry extends DefaultArrangementEntry public JavaElementArrangementEntry(@Nullable ArrangementEntry parent, int startOffset, int endOffset, - @NotNull ArrangementEntryType type, + @NotNull ArrangementSettingsToken type, @Nullable String name, boolean canBeArranged) { super(parent, startOffset, endOffset, canBeArranged); myType = type; - myTypes = EnumSet.of(type); - if (myType == ArrangementEntryType.CONSTRUCTOR) { - myTypes.add(ArrangementEntryType.METHOD); - } + myTypes.add(type); myName = name; } @NotNull @Override - public Set<ArrangementModifier> getModifiers() { + public Set<ArrangementSettingsToken> getModifiers() { return myModifiers; } - public void addModifier(@NotNull ArrangementModifier modifier) { + public void addModifier(@NotNull ArrangementSettingsToken modifier) { myModifiers.add(modifier); } @@ -84,12 +80,12 @@ public class JavaElementArrangementEntry extends DefaultArrangementEntry @NotNull @Override - public Set<ArrangementEntryType> getTypes() { + public Set<ArrangementSettingsToken> getTypes() { return myTypes; } @NotNull - public ArrangementEntryType getType() { + public ArrangementSettingsToken getType() { return myType; } diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java index 9cfcdfd16778..89c7d477087e 100644 --- a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java +++ b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java @@ -18,31 +18,25 @@ package com.intellij.psi.codeStyle.arrangement; import com.intellij.ide.highlighter.JavaHighlightingColors; import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.SyntaxHighlighterColors; -import com.intellij.openapi.editor.colors.CodeInsightColors; import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule; -import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType; -import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType; -import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier; +import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher; import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher; import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule; -import com.intellij.psi.codeStyle.arrangement.model.*; -import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType; -import com.intellij.psi.codeStyle.arrangement.settings.ArrangementColorsAware; -import com.intellij.psi.codeStyle.arrangement.settings.ArrangementConditionsGrouper; -import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware; -import com.intellij.util.Function; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition; +import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition; +import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition; +import com.intellij.psi.codeStyle.arrangement.std.ArrangementColorsAware; +import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsAware; +import com.intellij.psi.codeStyle.arrangement.std.*; import com.intellij.util.containers.ContainerUtilRt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,36 +45,45 @@ import java.awt.*; import java.util.*; import java.util.List; -import static com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType.*; -import static com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier.*; +import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.*; +import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Grouping.*; +import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.*; +import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.*; +import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.General.*; /** * @author Denis Zhdanov * @since 7/20/12 2:31 PM */ -public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>, ArrangementStandardSettingsAware, - ArrangementConditionsGrouper, ArrangementColorsAware -{ +public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>, ArrangementStandardSettingsAware, ArrangementColorsAware { // Type - @NotNull private static final Set<ArrangementEntryType> SUPPORTED_TYPES = EnumSet.of(INTERFACE, CLASS, ENUM, FIELD, METHOD, CONSTRUCTOR); - + @NotNull private static final Set<ArrangementSettingsToken> SUPPORTED_TYPES = + ContainerUtilRt.newLinkedHashSet( + FIELD, CONSTRUCTOR, METHOD, CLASS, INTERFACE, ENUM + ); // Modifier - @NotNull private static final Set<ArrangementModifier> SUPPORTED_MODIFIERS = EnumSet.of( - PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE, STATIC, FINAL, VOLATILE, TRANSIENT, SYNCHRONIZED, ABSTRACT - ); - - @NotNull private static final Object NO_TYPE = new Object(); - @NotNull private static final Map<Object, Set<ArrangementModifier>> MODIFIERS_BY_TYPE = new HashMap<Object, Set<ArrangementModifier>>(); - @NotNull private static final Collection<Set<?>> MUTEXES = new ArrayList<Set<?>>(); + @NotNull private static final Set<ArrangementSettingsToken> SUPPORTED_MODIFIERS = + ContainerUtilRt.newLinkedHashSet( + PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE, STATIC, FINAL, ABSTRACT, SYNCHRONIZED, TRANSIENT, VOLATILE + ); + @NotNull private static final List<ArrangementSettingsToken> SUPPORTED_ORDERS = + ContainerUtilRt.newArrayList(KEEP, BY_NAME); + @NotNull private static final ArrangementSettingsToken NO_TYPE = + new ArrangementSettingsToken("NO_TYPE", "NO_TYPE"); + @NotNull + private static final Map<ArrangementSettingsToken, Set<ArrangementSettingsToken>> MODIFIERS_BY_TYPE = + ContainerUtilRt.newHashMap(); + @NotNull private static final Collection<Set<ArrangementSettingsToken>> MUTEXES = + ContainerUtilRt.newArrayList(); static { - EnumSet<ArrangementModifier> visibilityModifiers = EnumSet.of(PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE); + Set<ArrangementSettingsToken> visibilityModifiers = ContainerUtilRt.newHashSet(PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE); MUTEXES.add(visibilityModifiers); MUTEXES.add(SUPPORTED_TYPES); - Set<ArrangementModifier> commonModifiers = concat(visibilityModifiers, STATIC, FINAL); - + Set<ArrangementSettingsToken> commonModifiers = concat(visibilityModifiers, STATIC, FINAL); + MODIFIERS_BY_TYPE.put(NO_TYPE, commonModifiers); MODIFIERS_BY_TYPE.put(ENUM, visibilityModifiers); MODIFIERS_BY_TYPE.put(INTERFACE, visibilityModifiers); @@ -90,134 +93,21 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>, MODIFIERS_BY_TYPE.put(FIELD, concat(commonModifiers, TRANSIENT, VOLATILE)); } - @NotNull private static final List<Set<ArrangementMatchCondition>> UI_GROUPING_RULES = ContainerUtilRt.newArrayList(); - static { - UI_GROUPING_RULES.add(new HashSet<ArrangementMatchCondition>( - ContainerUtil.map( - SUPPORTED_TYPES, - new Function<ArrangementEntryType, ArrangementMatchCondition>() { - @Override - public ArrangementMatchCondition fun(ArrangementEntryType type) { - return new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, type); - } - } - ) - )); - } - - private static final Map<ArrangementGroupingType, Set<ArrangementEntryOrderType>> GROUPING_RULES = ContainerUtilRt.newHashMap(); - static { - GROUPING_RULES.put(ArrangementGroupingType.GETTERS_AND_SETTERS, EnumSet.noneOf(ArrangementEntryOrderType.class)); - GROUPING_RULES.put(ArrangementGroupingType.OVERRIDDEN_METHODS, - EnumSet.of(ArrangementEntryOrderType.BY_NAME, ArrangementEntryOrderType.KEEP)); - GROUPING_RULES.put(ArrangementGroupingType.DEPENDENT_METHODS, - EnumSet.of(ArrangementEntryOrderType.BREADTH_FIRST, ArrangementEntryOrderType.DEPTH_FIRST)); - } - - private static final List<ArrangementGroupingRule> DEFAULT_GROUPING_RULES = new ArrayList<ArrangementGroupingRule>(); - static { - DEFAULT_GROUPING_RULES.add(new ArrangementGroupingRule(ArrangementGroupingType.GETTERS_AND_SETTERS)); - } - - private static final List<StdArrangementMatchRule> DEFAULT_MATCH_RULES = new ArrayList<StdArrangementMatchRule>(); + private static final Map<ArrangementSettingsToken, List<ArrangementSettingsToken>> GROUPING_RULES = ContainerUtilRt.newLinkedHashMap(); static { - ArrangementModifier[] visibility = {PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE}; - for (ArrangementModifier modifier : visibility) { - and(FIELD, STATIC, FINAL, modifier); - } - for (ArrangementModifier modifier : visibility) { - and(FIELD, STATIC, modifier); - } - for (ArrangementModifier modifier : visibility) { - and(FIELD, FINAL, modifier); - } - for (ArrangementModifier modifier : visibility) { - and(FIELD, modifier); - } - and(FIELD); - and(CONSTRUCTOR); - and(METHOD, STATIC); - and(METHOD); - and(ENUM); - and(INTERFACE); - and(CLASS, STATIC); - and(CLASS); - } - - private static final StdArrangementSettings DEFAULT_SETTINGS = new StdArrangementSettings(DEFAULT_GROUPING_RULES, DEFAULT_MATCH_RULES); - - private static void and(@NotNull Object... conditions) { - if (conditions.length == 1) { - DEFAULT_MATCH_RULES.add(new StdArrangementMatchRule(new StdArrangementEntryMatcher(new ArrangementAtomMatchCondition( - ArrangementUtil.parseType(conditions[0]), conditions[0] - )))); - return; - } - - ArrangementCompositeMatchCondition composite = new ArrangementCompositeMatchCondition(); - for (Object condition : conditions) { - composite.addOperand(new ArrangementAtomMatchCondition(ArrangementUtil.parseType(condition), condition)); - } - DEFAULT_MATCH_RULES.add(new StdArrangementMatchRule(new StdArrangementEntryMatcher(composite))); + GROUPING_RULES.put(GETTERS_AND_SETTERS, Collections.<ArrangementSettingsToken>emptyList()); + GROUPING_RULES.put(OVERRIDDEN_METHODS, ContainerUtilRt.newArrayList(BY_NAME, KEEP)); + GROUPING_RULES.put(DEPENDENT_METHODS, ContainerUtilRt.newArrayList(BREADTH_FIRST, DEPTH_FIRST)); } @NotNull - private static Set<ArrangementModifier> concat(@NotNull Set<ArrangementModifier> base, ArrangementModifier... modifiers) { - EnumSet<ArrangementModifier> result = EnumSet.copyOf(base); + private static Set<ArrangementSettingsToken> concat(@NotNull Set<ArrangementSettingsToken> base, ArrangementSettingsToken... modifiers) { + Set<ArrangementSettingsToken> result = ContainerUtilRt.newHashSet(base); Collections.addAll(result, modifiers); return result; } - @Nullable - @Override - public Pair<JavaElementArrangementEntry, List<JavaElementArrangementEntry>> parseWithNew( - @NotNull PsiElement root, - @Nullable Document document, - @NotNull Collection<TextRange> ranges, - @NotNull PsiElement element, - @Nullable ArrangementSettings settings) - { - Set<ArrangementGroupingType> groupingRules = getGroupingRules(settings); - JavaArrangementParseInfo existingEntriesInfo = new JavaArrangementParseInfo(); - root.accept(new JavaArrangementVisitor(existingEntriesInfo, document, ranges, groupingRules)); - - JavaArrangementParseInfo newEntryInfo = new JavaArrangementParseInfo(); - element.accept(new JavaArrangementVisitor(newEntryInfo, document, Collections.singleton(element.getTextRange()), groupingRules)); - if (newEntryInfo.getEntries().size() != 1) { - return null; - } - return Pair.create(newEntryInfo.getEntries().get(0), existingEntriesInfo.getEntries()); - } - - @NotNull - @Override - public List<JavaElementArrangementEntry> parse(@NotNull PsiElement root, - @Nullable Document document, - @NotNull Collection<TextRange> ranges, - @Nullable ArrangementSettings settings) - { - // Following entries are subject to arrangement: class, interface, field, method. - JavaArrangementParseInfo parseInfo = new JavaArrangementParseInfo(); - root.accept(new JavaArrangementVisitor(parseInfo, document, ranges, getGroupingRules(settings))); - if (settings != null) { - for (ArrangementGroupingRule rule : settings.getGroupings()) { - switch (rule.getGroupingType()) { - case GETTERS_AND_SETTERS: - setupGettersAndSetters(parseInfo); - break; - case DEPENDENT_METHODS: - setupUtilityMethods(parseInfo, rule.getOrderType()); - break; - case OVERRIDDEN_METHODS: - setupOverriddenMethods(parseInfo); - default: // Do nothing - } - } - } - return parseInfo.getEntries(); - } - private static void setupGettersAndSetters(@NotNull JavaArrangementParseInfo info) { Collection<JavaArrangementPropertyInfo> properties = info.getProperties(); for (JavaArrangementPropertyInfo propertyInfo : properties) { @@ -229,18 +119,19 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>, } } - private static void setupUtilityMethods(@NotNull JavaArrangementParseInfo info, @NotNull ArrangementEntryOrderType orderType) { - switch (orderType) { - case DEPTH_FIRST: - for (JavaArrangementMethodDependencyInfo rootInfo : info.getMethodDependencyRoots()) { - setupDepthFirstDependency(rootInfo); - } - break; - case BREADTH_FIRST: - for (JavaArrangementMethodDependencyInfo rootInfo : info.getMethodDependencyRoots()) { - setupBreadthFirstDependency(rootInfo); - } - default: // Unexpected type, do nothing + private static void setupUtilityMethods(@NotNull JavaArrangementParseInfo info, @NotNull ArrangementSettingsToken orderType) { + if (DEPTH_FIRST.equals(orderType)) { + for (JavaArrangementMethodDependencyInfo rootInfo : info.getMethodDependencyRoots()) { + setupDepthFirstDependency(rootInfo); + } + } + else if (BREADTH_FIRST.equals(orderType)) { + for (JavaArrangementMethodDependencyInfo rootInfo : info.getMethodDependencyRoots()) { + setupBreadthFirstDependency(rootInfo); + } + } + else { + assert false : orderType; } } @@ -280,16 +171,52 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>, } } } - + + @Nullable + @Override + public Pair<JavaElementArrangementEntry, List<JavaElementArrangementEntry>> parseWithNew( + @NotNull PsiElement root, + @Nullable Document document, + @NotNull Collection<TextRange> ranges, + @NotNull PsiElement element, + @Nullable ArrangementSettings settings) + { + Set<ArrangementSettingsToken> groupingRules = getGroupingRules(settings); + JavaArrangementParseInfo existingEntriesInfo = new JavaArrangementParseInfo(); + root.accept(new JavaArrangementVisitor(existingEntriesInfo, document, ranges, groupingRules)); + + JavaArrangementParseInfo newEntryInfo = new JavaArrangementParseInfo(); + element.accept(new JavaArrangementVisitor(newEntryInfo, document, Collections.singleton(element.getTextRange()), groupingRules)); + if (newEntryInfo.getEntries().size() != 1) { + return null; + } + return Pair.create(newEntryInfo.getEntries().get(0), existingEntriesInfo.getEntries()); + } + @NotNull - private static Set<ArrangementGroupingType> getGroupingRules(@Nullable ArrangementSettings settings) { - Set<ArrangementGroupingType> groupingRules = EnumSet.noneOf(ArrangementGroupingType.class); + @Override + public List<JavaElementArrangementEntry> parse(@NotNull PsiElement root, + @Nullable Document document, + @NotNull Collection<TextRange> ranges, + @Nullable ArrangementSettings settings) + { + // Following entries are subject to arrangement: class, interface, field, method. + JavaArrangementParseInfo parseInfo = new JavaArrangementParseInfo(); + root.accept(new JavaArrangementVisitor(parseInfo, document, ranges, getGroupingRules(settings))); if (settings != null) { for (ArrangementGroupingRule rule : settings.getGroupings()) { - groupingRules.add(rule.getGroupingType()); + if (GETTERS_AND_SETTERS.equals(rule.getGroupingType())) { + setupGettersAndSetters(parseInfo); + } + else if (DEPENDENT_METHODS.equals(rule.getGroupingType())) { + setupUtilityMethods(parseInfo, rule.getOrderType()); + } + else if (OVERRIDDEN_METHODS.equals(rule.getGroupingType())) { + setupOverriddenMethods(parseInfo); + } } } - return groupingRules; + return parseInfo.getEntries(); } @Override @@ -303,112 +230,153 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>, } CommonCodeStyleSettings commonSettings = settings.getCommonSettings(JavaLanguage.INSTANCE); - switch (target.getType()) { - case FIELD: - if (parent != null && parent.getType() == INTERFACE) { - return commonSettings.BLANK_LINES_AROUND_FIELD_IN_INTERFACE; - } - else { - return commonSettings.BLANK_LINES_AROUND_FIELD; - } - case METHOD: - if (parent != null && parent.getType() == INTERFACE) { - return commonSettings.BLANK_LINES_AROUND_METHOD_IN_INTERFACE; - } - else { - return commonSettings.BLANK_LINES_AROUND_METHOD; - } - case CLASS: return commonSettings.BLANK_LINES_AROUND_CLASS; - default: return -1; + if (FIELD.equals(target.getType())) { + if (parent != null && parent.getType() == INTERFACE) { + return commonSettings.BLANK_LINES_AROUND_FIELD_IN_INTERFACE; + } + else { + return commonSettings.BLANK_LINES_AROUND_FIELD; + } + } + else if (METHOD.equals(target.getType())) { + if (parent != null && parent.getType() == INTERFACE) { + return commonSettings.BLANK_LINES_AROUND_METHOD_IN_INTERFACE; + } + else { + return commonSettings.BLANK_LINES_AROUND_METHOD; + } + } + else if (CLASS.equals(target.getType())) { + return commonSettings.BLANK_LINES_AROUND_CLASS; + } + else { + return -1; } } - @Override - public boolean isEnabled(@NotNull ArrangementEntryType type, @Nullable ArrangementMatchCondition current) { - return SUPPORTED_TYPES.contains(type); + @NotNull + private static Set<ArrangementSettingsToken> getGroupingRules(@Nullable ArrangementSettings settings) { + Set<ArrangementSettingsToken> groupingRules = ContainerUtilRt.newHashSet(); + if (settings != null) { + for (ArrangementGroupingRule rule : settings.getGroupings()) { + groupingRules.add(rule.getGroupingType()); + } + } + return groupingRules; } + @NotNull @Override - public boolean isEnabled(@NotNull ArrangementModifier modifier, @Nullable ArrangementMatchCondition current) { - if (current == null) { - return SUPPORTED_MODIFIERS.contains(modifier); + public StdArrangementSettings getDefaultSettings() { + List<ArrangementGroupingRule> groupingRules = ContainerUtilRt.newArrayList(new ArrangementGroupingRule(GETTERS_AND_SETTERS)); + List<StdArrangementMatchRule> matchRules = ContainerUtilRt.newArrayList(); + ArrangementSettingsToken[] visibility = {PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE}; + for (ArrangementSettingsToken modifier : visibility) { + and(matchRules, FIELD, STATIC, FINAL, modifier); } - - final Ref<Object> typeRef = new Ref<Object>(); - current.invite(new ArrangementMatchConditionVisitor() { - @Override - public void visit(@NotNull ArrangementAtomMatchCondition setting) { - if (setting.getType() == ArrangementSettingType.TYPE) { - typeRef.set(setting.getValue()); - } - } - - @Override - public void visit(@NotNull ArrangementCompositeMatchCondition setting) { - for (ArrangementMatchCondition n : setting.getOperands()) { - if (typeRef.get() != null) { - return; - } - n.invite(this); - } - } - }); - Object key = typeRef.get() == null ? NO_TYPE : typeRef.get(); - Set<ArrangementModifier> modifiers = MODIFIERS_BY_TYPE.get(key); - return modifiers != null && modifiers.contains(modifier); + for (ArrangementSettingsToken modifier : visibility) { + and(matchRules, FIELD, STATIC, modifier); + } + for (ArrangementSettingsToken modifier : visibility) { + and(matchRules, FIELD, FINAL, modifier); + } + for (ArrangementSettingsToken modifier : visibility) { + and(matchRules, FIELD, modifier); + } + and(matchRules, FIELD); + and(matchRules, CONSTRUCTOR); + and(matchRules, METHOD, STATIC); + and(matchRules, METHOD); + and(matchRules, ENUM); + and(matchRules, INTERFACE); + and(matchRules, CLASS, STATIC); + and(matchRules, CLASS); + + return new StdArrangementSettings(groupingRules, matchRules); } - @NotNull + @Nullable @Override - public Collection<Set<?>> getMutexes() { - return MUTEXES; + public List<CompositeArrangementSettingsToken> getSupportedGroupingTokens() { + return ContainerUtilRt.newArrayList( + new CompositeArrangementSettingsToken(GETTERS_AND_SETTERS), + new CompositeArrangementSettingsToken(OVERRIDDEN_METHODS, BY_NAME, KEEP), + new CompositeArrangementSettingsToken(DEPENDENT_METHODS, BREADTH_FIRST, DEPTH_FIRST) + ); } - @NotNull + @Nullable @Override - public List<Set<ArrangementMatchCondition>> getGroupingConditions() { - return Collections.emptyList(); - //return UI_GROUPING_RULES; + public List<CompositeArrangementSettingsToken> getSupportedMatchingTokens() { + return ContainerUtilRt.newArrayList( + new CompositeArrangementSettingsToken(TYPE, SUPPORTED_TYPES), + new CompositeArrangementSettingsToken(MODIFIER, SUPPORTED_MODIFIERS), + new CompositeArrangementSettingsToken(StdArrangementTokens.Regexp.NAME), + new CompositeArrangementSettingsToken(ORDER, KEEP, BY_NAME) + ); } - @Nullable @Override - public StdArrangementSettings getDefaultSettings() { - return DEFAULT_SETTINGS; + public boolean isEnabled(@NotNull ArrangementSettingsToken token, @Nullable ArrangementMatchCondition current) { + if (SUPPORTED_TYPES.contains(token) || SUPPORTED_ORDERS.contains(token) || StdArrangementTokens.Regexp.NAME.equals(token)) { + return true; + } + ArrangementSettingsToken type = null; + if (current != null) { + type = ArrangementUtil.parseType(current); + } + if (type == null) { + type = NO_TYPE; + } + Set<ArrangementSettingsToken> modifiers = MODIFIERS_BY_TYPE.get(type); + return modifiers != null && modifiers.contains(token); } + @NotNull @Override - public boolean isNameFilterSupported() { - return true; + public ArrangementEntryMatcher buildMatcher(@NotNull ArrangementMatchCondition condition) throws IllegalArgumentException { + throw new IllegalArgumentException("Can't build a matcher for condition " + condition); } + @NotNull @Override - public boolean isEnabled(@NotNull ArrangementGroupingType groupingType, @Nullable ArrangementEntryOrderType orderType) { - Set<ArrangementEntryOrderType> orderTypes = GROUPING_RULES.get(groupingType); - if (orderTypes == null) { - return false; - } - return orderType == null || orderTypes.contains(orderType); + public Collection<Set<ArrangementSettingsToken>> getMutexes() { + return MUTEXES; } + private static void and(@NotNull List<StdArrangementMatchRule> matchRules, @NotNull ArrangementSettingsToken... conditions) { + if (conditions.length == 1) { + matchRules.add(new StdArrangementMatchRule(new StdArrangementEntryMatcher(new ArrangementAtomMatchCondition( + conditions[0], conditions[0] + )))); + return; + } + + ArrangementCompositeMatchCondition composite = new ArrangementCompositeMatchCondition(); + for (ArrangementSettingsToken condition : conditions) { + composite.addOperand(new ArrangementAtomMatchCondition(condition, condition)); + } + matchRules.add(new StdArrangementMatchRule(new StdArrangementEntryMatcher(composite))); + } + @Nullable @Override - public TextAttributes getTextAttributes(@NotNull EditorColorsScheme scheme, @NotNull ArrangementSettingType type, boolean selected) { + public TextAttributes getTextAttributes(@NotNull EditorColorsScheme scheme, @NotNull ArrangementSettingsToken token, boolean selected) { if (selected) { TextAttributes attributes = new TextAttributes(); attributes.setForegroundColor(scheme.getColor(EditorColors.SELECTION_FOREGROUND_COLOR)); attributes.setBackgroundColor(scheme.getColor(EditorColors.SELECTION_BACKGROUND_COLOR)); return attributes; } - if (type == ArrangementSettingType.MODIFIER) { + else if (SUPPORTED_TYPES.contains(token)) { return getAttributes(scheme, JavaHighlightingColors.KEYWORD); } - else if (type == ArrangementSettingType.TYPE) { - return getAttributes(scheme, CodeInsightColors.CLASS_NAME_ATTRIBUTES, CodeInsightColors.INTERFACE_NAME_ATTRIBUTES); + else if (SUPPORTED_MODIFIERS.contains(token)) { + getAttributes(scheme, JavaHighlightingColors.KEYWORD); } return null; } - + @Nullable private static TextAttributes getAttributes(@NotNull EditorColorsScheme scheme, @NotNull TextAttributesKey ... keys) { TextAttributes result = null; diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ReferenceAdjuster.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ReferenceAdjuster.java index f6150031f602..a25476a9af5b 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ReferenceAdjuster.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ReferenceAdjuster.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -20,24 +20,26 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl; import com.intellij.psi.impl.source.SourceJavaCodeReference; -import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.jsp.jspJava.JspClass; import com.intellij.psi.impl.source.tree.*; import com.intellij.psi.jsp.JspFile; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.List; public class ReferenceAdjuster { - private final boolean myUseFqClassnamesInJavadoc; + private final boolean myUseFqClassNamesInJavadoc; private final boolean myUseFqClassNames; public ReferenceAdjuster(boolean useFqInJavadoc, boolean useFqInCode) { - myUseFqClassnamesInJavadoc = useFqInJavadoc; + myUseFqClassNamesInJavadoc = useFqInJavadoc; myUseFqClassNames = useFqInCode; } @@ -49,17 +51,19 @@ public class ReferenceAdjuster { this(settings.USE_FQ_CLASS_NAMES_IN_JAVADOC, settings.USE_FQ_CLASS_NAMES); } - public TreeElement process(TreeElement element, boolean addImports, boolean uncompleteCode) { + public TreeElement process(TreeElement element, boolean addImports, boolean incompleteCode) { IElementType elementType = element.getElementType(); - if (elementType == JavaElementType.JAVA_CODE_REFERENCE || elementType == JavaElementType.REFERENCE_EXPRESSION) { - final IElementType parentElementType = element.getTreeParent().getElementType(); - if (elementType == JavaElementType.JAVA_CODE_REFERENCE || parentElementType == JavaElementType.REFERENCE_EXPRESSION || parentElementType == JavaElementType.METHOD_REF_EXPRESSION || uncompleteCode) { - final PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement)SourceTreeToPsiMap.treeElementToPsi(element); - final PsiReferenceParameterList parameterList = ref.getParameterList(); + if ((elementType == JavaElementType.JAVA_CODE_REFERENCE || elementType == JavaElementType.REFERENCE_EXPRESSION) && !isAnnotated(element)) { + IElementType parentType = element.getTreeParent().getElementType(); + if (elementType == JavaElementType.JAVA_CODE_REFERENCE || incompleteCode || + parentType == JavaElementType.REFERENCE_EXPRESSION || parentType == JavaElementType.METHOD_REF_EXPRESSION) { + PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement)element.getPsi(); + + PsiReferenceParameterList parameterList = ref.getParameterList(); if (parameterList != null) { - final PsiTypeElement[] typeParameters = parameterList.getTypeParameterElements(); + PsiTypeElement[] typeParameters = parameterList.getTypeParameterElements(); for (PsiTypeElement typeParameter : typeParameters) { - process((TreeElement)SourceTreeToPsiMap.psiElementToTree(typeParameter), addImports, uncompleteCode); + process((TreeElement)typeParameter.getNode(), addImports, incompleteCode); } } @@ -71,45 +75,50 @@ public class ReferenceAdjuster { if (rightKind) { boolean isInsideDocComment = TreeUtil.findParent(element, JavaDocElementType.DOC_COMMENT) != null; - boolean isShort = !((SourceJavaCodeReference)element).isQualified(); + boolean isShort = !ref.isQualified(); if (!makeFQ(isInsideDocComment)) { if (isShort) return element; // short name already, no need to change } + PsiElement refElement; - if (!uncompleteCode) { + if (!incompleteCode) { refElement = ref.resolve(); } else { PsiResolveHelper helper = JavaPsiFacade.getInstance(element.getManager().getProject()).getResolveHelper(); - refElement = helper.resolveReferencedClass(((SourceJavaCodeReference)element).getClassNameText(), SourceTreeToPsiMap.treeElementToPsi(element) - ); + refElement = helper.resolveReferencedClass(((SourceJavaCodeReference)element).getClassNameText(), ref); } + if (refElement instanceof PsiClass) { + PsiClass psiClass = (PsiClass)refElement; if (makeFQ(isInsideDocComment)) { - String qName = ((PsiClass)refElement).getQualifiedName(); + String qName = psiClass.getQualifiedName(); if (qName == null) return element; - PsiImportHolder file = (PsiImportHolder) SourceTreeToPsiMap.treeElementToPsi(element).getContainingFile(); - if (file instanceof PsiJavaFile && ImportHelper.isImplicitlyImported(qName, (PsiJavaFile) file)) { - if (isShort) return element; - return (TreeElement)makeShortReference((CompositeElement)element, (PsiClass)refElement, addImports); - } + + PsiFile file = ref.getContainingFile(); if (file instanceof PsiJavaFile) { + if (ImportHelper.isImplicitlyImported(qName, (PsiJavaFile)file)) { + if (isShort) return element; + return (TreeElement)makeShortReference((CompositeElement)element, psiClass, addImports); + } + String thisPackageName = ((PsiJavaFile)file).getPackageName(); if (ImportHelper.hasPackage(qName, thisPackageName)) { if (!isShort) { - return (TreeElement)makeShortReference((CompositeElement)element, (PsiClass)refElement, addImports); + return (TreeElement)makeShortReference((CompositeElement)element, psiClass, addImports); } } } - return (TreeElement)replaceReferenceWithFQ(element, (PsiClass)refElement); + + return (TreeElement)replaceReferenceWithFQ(element, psiClass); } else { int oldLength = element.getTextLength(); - TreeElement treeElement = (TreeElement)makeShortReference((CompositeElement)element, (PsiClass)refElement, addImports); - if (treeElement.getTextLength() == oldLength && ((PsiClass)refElement).getContainingClass() != null) { + TreeElement treeElement = (TreeElement)makeShortReference((CompositeElement)element, psiClass, addImports); + if (treeElement.getTextLength() == oldLength && psiClass.getContainingClass() != null) { PsiElement qualifier = ref.getQualifier(); if (qualifier instanceof PsiJavaCodeReferenceElement && ((PsiJavaCodeReferenceElement)qualifier).resolve() instanceof PsiClass) { - process((TreeElement)qualifier.getNode(), addImports, uncompleteCode); + process((TreeElement)qualifier.getNode(), addImports, incompleteCode); } } return treeElement; @@ -120,61 +129,75 @@ public class ReferenceAdjuster { } for (TreeElement child = element.getFirstChildNode(); child != null; child = child.getTreeNext()) { - child = process(child, addImports, uncompleteCode); + //noinspection AssignmentToForLoopParameter + child = process(child, addImports, incompleteCode); } return element; } - private boolean makeFQ(boolean isInsideDocComment) { - if (isInsideDocComment) { - return myUseFqClassnamesInJavadoc; + private static boolean isAnnotated(TreeElement element) { + PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement)element.getPsi(); + + PsiElement qualifier = ref.getQualifier(); + if (qualifier instanceof PsiJavaCodeReferenceElement && PsiTreeUtil.getChildOfType(qualifier, PsiAnnotation.class) != null) { + return true; } - else { - return myUseFqClassNames; + + PsiModifierList modifierList = PsiImplUtil.findNeighbourModifierList(ref); + if (modifierList != null) { + for (PsiAnnotation annotation : modifierList.getAnnotations()) { + if (PsiImplUtil.findApplicableTarget(annotation, PsiAnnotation.TargetType.TYPE_USE) != null) { + return true; + } + } } + + return false; + } + + private boolean makeFQ(boolean isInsideDocComment) { + return isInsideDocComment ? myUseFqClassNamesInJavadoc : myUseFqClassNames; } public void processRange(TreeElement element, int startOffset, int endOffset) { - ArrayList<ASTNode> array = new ArrayList<ASTNode>(); + List<ASTNode> array = new ArrayList<ASTNode>(); addReferencesInRange(array, element, startOffset, endOffset); for (ASTNode ref : array) { - if (SourceTreeToPsiMap.treeElementToPsi(ref).isValid()) { + if (ref.getPsi().isValid()) { process((TreeElement)ref, true, true); } } } - private static void addReferencesInRange(ArrayList<ASTNode> array, TreeElement parent, int startOffset, int endOffset) { + private static void addReferencesInRange(List<ASTNode> array, TreeElement parent, int startOffset, int endOffset) { if (parent.getElementType() == JavaElementType.JAVA_CODE_REFERENCE || parent.getElementType() == JavaElementType.REFERENCE_EXPRESSION) { array.add(parent); return; } - if (parent.getPsi() instanceof PsiFile && JspPsiUtil.isInJspFile(parent.getPsi())) { - final JspFile jspFile = JspPsiUtil.getJspFile(parent.getPsi()); - JspClass jspClass = (JspClass) jspFile.getJavaClass(); - addReferencesInRange(array, (TreeElement)jspClass.getNode(), startOffset, endOffset); - return; + if (parent.getPsi() instanceof PsiFile) { + JspFile jspFile = JspPsiUtil.getJspFile(parent.getPsi()); + if (jspFile != null) { + JspClass jspClass = (JspClass)jspFile.getJavaClass(); + addReferencesInRange(array, (TreeElement)jspClass.getNode(), startOffset, endOffset); + return; + } } addReferencesInRangeForComposite(array, parent, startOffset, endOffset); } - private static void addReferencesInRangeForComposite(final ArrayList<ASTNode> array, - final TreeElement parent, - final int startOffset, - final int endOffset) { + private static void addReferencesInRangeForComposite(List<ASTNode> array, TreeElement parent, int startOffset, int endOffset) { int offset = 0; for (TreeElement child = parent.getFirstChildNode(); child != null; child = child.getTreeNext()) { int length = child.getTextLength(); - if (startOffset <= offset + length && offset <= endOffset) { - final IElementType type = child.getElementType(); - + IElementType type = child.getElementType(); if (type == JavaElementType.JAVA_CODE_REFERENCE || type == JavaElementType.REFERENCE_EXPRESSION) { array.add(child); - } else { + } + else { addReferencesInRangeForComposite(array, child, startOffset - offset, endOffset - offset); } } @@ -210,7 +233,7 @@ public class ReferenceAdjuster { } } - if (addImports && !((PsiImportHolder) reference.getContainingFile()).importClass(refClass)) return null; + if (addImports && !((PsiImportHolder)reference.getContainingFile()).importClass(refClass)) return null; if (!isSafeToShortenReference(reference, refClass)) return null; return reference; } @@ -233,14 +256,14 @@ public class ReferenceAdjuster { @NotNull private static ASTNode replaceReferenceWithShort(PsiQualifiedReference reference) { - final ASTNode node = reference.getNode(); + ASTNode node = reference.getNode(); assert node != null; - dequalifyImpl((CompositeElement)node); + deQualifyImpl((CompositeElement)node); return node; } - private static void dequalifyImpl(@NotNull CompositeElement reference) { - final ASTNode qualifier = reference.findChildByRole(ChildRole.QUALIFIER); + private static void deQualifyImpl(@NotNull CompositeElement reference) { + ASTNode qualifier = reference.findChildByRole(ChildRole.QUALIFIER); if (qualifier != null) { ASTNode firstChildNode = qualifier.getFirstChildNode(); boolean markToReformatBefore = firstChildNode instanceof TreeElement && CodeEditUtil.isMarkedToReformatBefore((TreeElement)firstChildNode); @@ -255,8 +278,7 @@ public class ReferenceAdjuster { } private static ASTNode replaceReferenceWithFQ(ASTNode reference, PsiClass refClass) { - ((SourceJavaCodeReference)reference).fullyQualify(refClass); + ((SourceJavaCodeReference)reference).fullyQualify(refClass); return reference; } } - diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/StringLiteralManipulator.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/StringLiteralManipulator.java index aa7459248732..3e4abfc8e6af 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/StringLiteralManipulator.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/StringLiteralManipulator.java @@ -17,10 +17,7 @@ package com.intellij.psi.impl.source.resolve.reference.impl.manipulators; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.AbstractElementManipulator; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiLiteralExpression; +import com.intellij.psi.*; import com.intellij.util.IncorrectOperationException; /** @@ -29,10 +26,17 @@ import com.intellij.util.IncorrectOperationException; public class StringLiteralManipulator extends AbstractElementManipulator<PsiLiteralExpression> { @Override public PsiLiteralExpression handleContentChange(PsiLiteralExpression expr, TextRange range, String newContent) throws IncorrectOperationException { - final Object value = expr.getValue(); - if (!(value instanceof String)) throw new IncorrectOperationException("cannot handle content change for: "+ value+", expr: "+expr); String oldText = expr.getText(); - newContent = StringUtil.escapeStringCharacters(newContent); + if (oldText.startsWith("\"")) { + newContent = StringUtil.escapeStringCharacters(newContent); + } + else if (oldText.startsWith("'") && newContent.length() <= 1) { + newContent = newContent.length() == 1 && newContent.charAt(0) == '\''? "\\'" : newContent; + } + else { + throw new IncorrectOperationException("cannot handle content change for: " + oldText + ", expr: " + expr); + } + String newText = oldText.substring(0, range.getStartOffset()) + newContent + oldText.substring(range.getEndOffset()); final PsiExpression newExpr = JavaPsiFacade.getInstance(expr.getProject()).getElementFactory().createExpressionFromText(newText, null); return (PsiLiteralExpression)expr.replace(newExpr); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java index a2df081217de..30e55c110153 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -13,31 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.psi.impl.source.tree; -import com.intellij.lang.ASTFactory; import com.intellij.lang.ASTNode; import com.intellij.lang.PsiBuilder; import com.intellij.lang.java.parser.JavaParser; import com.intellij.lang.java.parser.JavaParserUtil; -import com.intellij.lexer.JavaLexer; -import com.intellij.lexer.Lexer; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.impl.GeneratedMarkerVisitor; -import com.intellij.psi.impl.light.LightTypeElement; import com.intellij.psi.impl.source.*; import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; -import com.intellij.psi.impl.source.parsing.ParseUtilBase; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiUtil; import com.intellij.util.CharTable; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -61,15 +54,16 @@ public class JavaTreeGenerator implements TreeGenerator { final String text = original.getText(); return createLeafFromText(text, table, manager, original, ((PsiJavaToken)original).getTokenType()); } + if (original instanceof PsiModifierList) { final String text = original.getText(); assert text != null : "Text is null for " + original + "; " + original.getClass(); final LanguageLevel level = PsiUtil.getLanguageLevel(original); final DummyHolder holder = DummyHolderFactory.createHolder(original.getManager(), new JavaDummyElement(text, MOD_LIST, level), null); final TreeElement modifierListElement = holder.getTreeElement().getFirstChildNode(); - if (CodeEditUtil.isNodeGenerated(original.getNode())) modifierListElement.acceptTree(new GeneratedMarkerVisitor()); - return modifierListElement; + return markGeneratedIfNeeded(original, modifierListElement); } + if (original instanceof PsiReferenceExpression) { TreeElement element = createReferenceExpression(original.getProject(), original.getText(), original); PsiElement refElement = ((PsiJavaCodeReferenceElement)original).resolve(); @@ -78,6 +72,7 @@ public class JavaTreeGenerator implements TreeGenerator { } return element; } + if (original instanceof PsiJavaCodeReferenceElement) { PsiElement refElement = ((PsiJavaCodeReferenceElement)original).resolve(); final boolean generated = refElement != null && CodeEditUtil.isNodeGenerated(refElement.getNode()); @@ -115,6 +110,7 @@ public class JavaTreeGenerator implements TreeGenerator { } return createReference(original.getProject(), original.getText(), generated); } + if (original instanceof PsiCompiledElement) { PsiElement sourceVersion = original.getNavigationElement(); if (sourceVersion != original) { @@ -123,84 +119,44 @@ public class JavaTreeGenerator implements TreeGenerator { ASTNode mirror = SourceTreeToPsiMap.psiElementToTree(((PsiCompiledElement)original).getMirror()); return ChangeUtil.generateTreeElement(SourceTreeToPsiMap.treeElementToPsi(mirror), table,manager); } + if (original instanceof PsiTypeElement) { - final boolean generated = CodeEditUtil.isNodeGenerated(original.getNode()); PsiTypeElement typeElement = (PsiTypeElement)original; PsiType type = typeElement.getType(); - if (type instanceof PsiEllipsisType) { - TreeElement componentTypeCopy = ChangeUtil.generateTreeElement( - new LightTypeElement(original.getManager(), ((PsiEllipsisType)type).getComponentType()), - table, - manager); - if (componentTypeCopy == null) return null; - CompositeElement element = ASTFactory.composite(JavaElementType.TYPE); - CodeEditUtil.setNodeGenerated(element, generated); - element.rawAddChildren(componentTypeCopy); - element.rawAddChildren(createLeafFromText("...", table, manager, original, JavaTokenType.ELLIPSIS)); - return element; - } - if (type instanceof PsiArrayType) { - TreeElement componentTypeCopy = ChangeUtil.generateTreeElement( - new LightTypeElement(original.getManager(), ((PsiArrayType)type).getComponentType()), - table, - manager); - if (componentTypeCopy == null) return null; - CompositeElement element = ASTFactory.composite(JavaElementType.TYPE); - CodeEditUtil.setNodeGenerated(element, generated); - element.rawAddChildren(componentTypeCopy); - element.rawAddChildren(createLeafFromText("[", table, manager, original, JavaTokenType.LBRACKET)); - element.rawAddChildren(createLeafFromText("]", table, manager, original, JavaTokenType.RBRACKET)); - return element; - } - if (type instanceof PsiPrimitiveType) { - @NonNls String text = typeElement.getText(); - if (text.equals("null")) return null; - Lexer lexer = new JavaLexer(LanguageLevel.JDK_1_3); - lexer.start(text); - TreeElement keyword = ParseUtilBase.createTokenElement(lexer, table); - CodeEditUtil.setNodeGenerated(keyword, generated); - CompositeElement element = ASTFactory.composite(JavaElementType.TYPE); - CodeEditUtil.setNodeGenerated(element, generated); - element.rawAddChildren(keyword); - return element; - } - if (type instanceof PsiWildcardType || type instanceof PsiCapturedWildcardType || type instanceof PsiDisjunctionType) { - final String originalText = original.getText(); - return createType(original.getProject(), originalText, null, generated); - } + if (type instanceof PsiIntersectionType) { - LightTypeElement te = new LightTypeElement(original.getManager(), ((PsiIntersectionType)type).getRepresentative()); - return ChangeUtil.generateTreeElement(te, table, manager); + type = ((PsiIntersectionType)type).getRepresentative(); } - if (type instanceof PsiMethodReferenceType || type instanceof PsiLambdaExpressionType) { + else if (type instanceof PsiMethodReferenceType || type instanceof PsiLambdaExpressionType) { type = PsiType.getJavaLangObject(manager, GlobalSearchScope.projectScope(manager.getProject())); } - PsiClassType classType = (PsiClassType)type; - - String text = classType.getPresentableText(); - final TreeElement element = createType(original.getProject(), text, original, false); - PsiTypeElementImpl result = SourceTreeToPsiMap.treeToPsiNotNull(element); + String text = type.getPresentableText(); + PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(original.getProject()).getParserFacade(); + TreeElement element = (TreeElement)parserFacade.createTypeElementFromText(text, original).getNode(); - CodeEditUtil.setNodeGenerated(result, generated); - if (generated) { - PsiJavaCodeReferenceElement ref = result.getInnermostComponentReferenceElement(); - if (ref != null) ((CompositeElement)ref.getNode()).acceptTree(new GeneratedMarkerVisitor()); + PsiTypeElementImpl result = (PsiTypeElementImpl)element.getPsi(); + markGeneratedIfNeeded(original, result); + if (type instanceof PsiClassType) { + encodeInfoInTypeElement(result, type); } - encodeInfoInTypeElement(result, classType); return result; } + return null; } - private static LeafElement createLeafFromText(final String text, - final CharTable table, - final PsiManager manager, - final PsiElement original, - final IElementType type) { + private static LeafElement createLeafFromText(String text, CharTable table, PsiManager manager, PsiElement original, IElementType type) { return Factory.createSingleLeafElement(type, text, 0, text.length(), table, manager, CodeEditUtil.isNodeGenerated(original.getNode())); } + private static TreeElement markGeneratedIfNeeded(PsiElement original, TreeElement copy) { + if (CodeEditUtil.isNodeGenerated(original.getNode())) { + copy.acceptTree(new GeneratedMarkerVisitor()); + } + return copy; + } + private static TreeElement createReference(final Project project, final String text, boolean mark) { final PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(project).getParserFacade(); final TreeElement element = (TreeElement)parserFacade.createReferenceFromText(text, null).getNode(); @@ -214,13 +170,6 @@ public class JavaTreeGenerator implements TreeGenerator { return (TreeElement)expression.getNode(); } - private static TreeElement createType(final Project project, final String text, final PsiElement context, final boolean mark) { - final PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(project).getParserFacade(); - final TreeElement element = (TreeElement)parserFacade.createTypeElementFromText(text, context).getNode(); - if (mark) element.acceptTree(new GeneratedMarkerVisitor()); - return element; - } - private static void encodeInfoInTypeElement(ASTNode typeElement, PsiType type) { if (type instanceof PsiPrimitiveType) return; LOG.assertTrue(typeElement.getElementType() == JavaElementType.TYPE); diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java index 522ea10336f8..6faaf8e509e8 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java @@ -121,7 +121,11 @@ public class JavaChangeSignatureDetector implements LanguageChangeSignatureDetec @Override public ChangeInfo createNextChangeInfo(String signature, @NotNull final ChangeInfo currentInfo, String initialName) { - final Project project = currentInfo.getMethod().getProject(); + final PsiElement currentInfoMethod = currentInfo.getMethod(); + if (currentInfoMethod == null) { + return null; + } + final Project project = currentInfoMethod.getProject(); if (currentInfo instanceof RenameChangeInfo) { return currentInfo; } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java index ea14d9734a99..e0e37ac89408 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java @@ -687,7 +687,7 @@ public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase<Paramet for (final ParameterTableModelItemBase<ParameterInfoImpl> item : myParametersTableModel.getItems()) { if (item.parameter.oldParameterIndex < 0) { if (StringUtil.isEmpty(item.defaultValueCodeFragment.getText())) - return new ValidationInfo("Default value is missing. In the method call, the new parameter value will be left blank"); + return new ValidationInfo("Default value is missing. Method calls will contain blanks instead of the new parameter value."); } } } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java index 872dfcafc0d8..aa27a6e024ca 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java @@ -23,6 +23,7 @@ package com.intellij.refactoring.changeSignature; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; @@ -156,7 +157,9 @@ public class ParameterInfoImpl implements JavaParameterInfo { @Nullable public PsiExpression getValue(final PsiCallExpression expr) throws IncorrectOperationException { if (StringUtil.isEmpty(defaultValue)) return null; - return JavaPsiFacade.getInstance(expr.getProject()).getElementFactory().createExpressionFromText(defaultValue, expr); + final PsiExpression expression = + JavaPsiFacade.getInstance(expr.getProject()).getElementFactory().createExpressionFromText(defaultValue, expr); + return (PsiExpression)JavaCodeStyleManager.getInstance(expr.getProject()).shortenClassReferences(expression); } public boolean isUseAnySingleVariable() { diff --git a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java index a0ebcbb65ca4..2b66afc2545e 100644 --- a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java @@ -76,7 +76,9 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase { Map<PsiFile, String> relativeMap) { final Map<PsiFile, PsiClass[]> result = new HashMap<PsiFile, PsiClass[]>(); for (PsiElement element : elements) { - final PsiFile containingFile = element.getNavigationElement().getContainingFile(); + final PsiElement navigationElement = element.getNavigationElement(); + LOG.assertTrue(navigationElement != null, element); + final PsiFile containingFile = navigationElement.getContainingFile(); if (!(containingFile instanceof PsiClassOwner && ProjectRootsUtil.isOutsideSourceRoot(containingFile))) { PsiClass[] topLevelClasses = getTopLevelClasses(element); diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java index b8fb07f71bd6..17a083c2f8e3 100644 --- a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -220,7 +220,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor { } @Override - public void inlineUsage(UsageInfo usage, PsiElement referenced) { + public void inlineUsage(@NotNull UsageInfo usage, @NotNull PsiElement referenced) { if (usage instanceof NonCodeUsageInfo) return; throw new UnsupportedOperationException( @@ -434,7 +434,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor { } else if (element instanceof PsiImportStaticReferenceElement) { imports2Delete.add(PsiTreeUtil.getParentOfType(element, PsiImportStaticStatement.class)); } - else { + else if (JavaLanguage.INSTANCE != element.getLanguage()) { GenericInlineHandler.inlineReference(usage, myMethod, myInliners); } } @@ -1028,6 +1028,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor { initializer.accept(canAllLocalsBeDeclaredFinal); if (!canAllLocalsBeDeclaredFinal.success) return false; } + if (initializer instanceof PsiMethodReferenceExpression) return true; if (initializer instanceof PsiReferenceExpression) { PsiVariable refVar = (PsiVariable)((PsiReferenceExpression)initializer).resolve(); if (refVar == null) { diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java index a4338d463cc3..990acc57ff58 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java @@ -75,15 +75,14 @@ public class IntroduceFieldHandler extends BaseExpressionToFieldHandler { final AbstractInplaceIntroducer activeIntroducer = AbstractInplaceIntroducer.getActiveIntroducer(editor); PsiLocalVariable localVariable = null; - if (expr instanceof PsiReferenceExpression) { + if (anchorElement instanceof PsiLocalVariable) { + localVariable = (PsiLocalVariable)anchorElement; + } else if (expr instanceof PsiReferenceExpression) { PsiElement ref = ((PsiReferenceExpression)expr).resolve(); if (ref instanceof PsiLocalVariable) { localVariable = (PsiLocalVariable)ref; } } - else if (anchorElement instanceof PsiLocalVariable) { - localVariable = (PsiLocalVariable)anchorElement; - } String enteredName = null; boolean replaceAll = false; diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/InplaceIntroduceParameterPopup.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/InplaceIntroduceParameterPopup.java index 7a376d15f7e6..79c9b1d243b3 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/InplaceIntroduceParameterPopup.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/InplaceIntroduceParameterPopup.java @@ -259,6 +259,9 @@ public class InplaceIntroduceParameterPopup extends AbstractJavaInplaceIntroduce buf.append(", "); } int startOffset = buf.length(); + if (myMustBeFinal || myPanel.isGenerateFinal()) { + buf.append("final "); + } buf.append(parameter.getType().getPresentableText()).append(" ").append(variable == parameter ? value : parameter.getName()); int endOffset = buf.length(); if (variable == parameter) { diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java index 09f26a481790..3423cca5bd30 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java @@ -197,9 +197,10 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase { PsiExpression expression = PsiTreeUtil.getParentOfType(elementAtCaret, PsiExpression.class); while (expression != null) { if (!expressions.contains(expression) && !(expression instanceof PsiParenthesizedExpression) && !(expression instanceof PsiSuperExpression) && expression.getType() != PsiType.VOID) { - if (!(expression instanceof PsiReferenceExpression && (expression.getParent() instanceof PsiMethodCallExpression || - ((PsiReferenceExpression)expression).resolve() instanceof PsiClass)) - && !(expression instanceof PsiAssignmentExpression)) { + if (expression instanceof PsiMethodReferenceExpression || + !(expression instanceof PsiReferenceExpression && + (expression.getParent() instanceof PsiMethodCallExpression || ((PsiReferenceExpression)expression).resolve() instanceof PsiClass)) && + !(expression instanceof PsiAssignmentExpression)) { expressions.add(expression); } } @@ -840,7 +841,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase { declaration = (PsiDeclarationStatement)JavaCodeStyleManager.getInstance(project).shortenClassReferences(declaration); PsiVariable var = (PsiVariable) declaration.getDeclaredElements()[0]; PsiUtil.setModifierProperty(var, PsiModifier.FINAL, settings.isDeclareFinal()); - variable.set(SmartPointerManager.getInstance(project).createLazyPointer(var)); + variable.set(SmartPointerManager.getInstance(project).createSmartPsiElementPointer(var)); fieldConflictsResolver.fix(); } catch (IncorrectOperationException e) { LOG.error(e); diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/DestinationFolderComboBox.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/DestinationFolderComboBox.java index 291a49df5b00..8ce4f9fd3e0c 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/DestinationFolderComboBox.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/DestinationFolderComboBox.java @@ -167,7 +167,7 @@ public abstract class DestinationFolderComboBox extends ComboboxWithBrowseButton final PsiDirectory selectedPsiDirectory = selectedItem.getDirectory(); VirtualFile selectedDestination = selectedPsiDirectory.getVirtualFile(); if (showChooserWhenDefault && - Comparing.equal(selectedDestination, myInitialTargetDirectory.getVirtualFile()) && + myInitialTargetDirectory != null && Comparing.equal(selectedDestination, myInitialTargetDirectory.getVirtualFile()) && mySourceRoots.length > 1) { selectedDestination = MoveClassesOrPackagesUtil.chooseSourceRoot(targetPackage, mySourceRoots, myInitialTargetDirectory); } diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveClassesOrPackagesHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveClassesOrPackagesHandler.java index 5e5283947a43..38fa2e663c20 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveClassesOrPackagesHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveClassesOrPackagesHandler.java @@ -22,7 +22,7 @@ import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; @@ -133,10 +133,18 @@ public class JavaMoveClassesOrPackagesHandler extends MoveHandlerDelegate { return; } } - if (tryDirectoryMove ( project, elements, targetContainer, callback)) { - return; + final PsiElement[] adjustedElements = MoveClassesOrPackagesImpl.adjustForMove(project, elements, targetContainer); + if (adjustedElements == null) return; + + if (targetContainer instanceof PsiDirectory) { + if (CommonRefactoringUtil.checkReadOnlyStatusRecursively(project, Arrays.asList(adjustedElements), true)) { + if (!packageHasMultipleDirectoriesInModule(project, (PsiDirectory)targetContainer)) { + new MoveClassesOrPackagesToNewDirectoryDialog((PsiDirectory)targetContainer, adjustedElements, callback).show(); + return; + } + } } - MoveClassesOrPackagesImpl.doMove(project, elements, targetContainer, callback); + MoveClassesOrPackagesImpl.doMove(project, adjustedElements, targetContainer, callback); } private static void moveDirectoriesLibrariesSafe(Project project, @@ -254,22 +262,13 @@ public class JavaMoveClassesOrPackagesHandler extends MoveHandlerDelegate { return super.adjustTargetForMove(dataContext, targetContainer); } - private static boolean tryDirectoryMove(Project project, final PsiElement[] sourceElements, final PsiElement targetElement, final MoveCallback callback) { - if (targetElement instanceof PsiDirectory) { - final PsiElement[] adjustedElements = MoveClassesOrPackagesImpl.adjustForMove(project, sourceElements, targetElement); - if (adjustedElements != null) { - if ( CommonRefactoringUtil.checkReadOnlyStatusRecursively(project, Arrays.asList(adjustedElements),true) ) { - final PsiPackage psiPackage = JavaDirectoryService.getInstance().getPackage((PsiDirectory)targetElement); - if (psiPackage != null) { - final Module module = ModuleUtil.findModuleForFile(((PsiDirectory)targetElement).getVirtualFile(), project); - if (module != null) { - if (psiPackage.getDirectories(GlobalSearchScope.moduleScope(module)).length > 1) return false; - } - } - new MoveClassesOrPackagesToNewDirectoryDialog((PsiDirectory)targetElement, adjustedElements, callback).show(); - } + public static boolean packageHasMultipleDirectoriesInModule(Project project, PsiDirectory targetElement) { + final PsiPackage psiPackage = JavaDirectoryService.getInstance().getPackage(targetElement); + if (psiPackage != null) { + final Module module = ModuleUtilCore.findModuleForFile(targetElement.getVirtualFile(), project); + if (module != null) { + if (psiPackage.getDirectories(GlobalSearchScope.moduleScope(module)).length > 1) return true; } - return true; } return false; } @@ -442,7 +441,12 @@ public class JavaMoveClassesOrPackagesHandler extends MoveHandlerDelegate { if (isReferenceInAnonymousClass(reference)) return false; if (!invalid4Move(element)) { - MoveClassesOrPackagesImpl.doMove(project, new PsiElement[]{element}, LangDataKeys.TARGET_PSI_ELEMENT.getData(dataContext), null); + final PsiElement initialTargetElement = LangDataKeys.TARGET_PSI_ELEMENT.getData(dataContext); + PsiElement[] adjustedElements = adjustForMove(project, new PsiElement[]{element}, initialTargetElement); + if (adjustedElements == null) { + return true; + } + MoveClassesOrPackagesImpl.doMove(project, adjustedElements, initialTargetElement, null); return true; } return false; diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java index 8e7fc3be5114..83851b3ac2d1 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java @@ -227,7 +227,7 @@ public class MoveClassesOrPackagesDialog extends RefactoringDialog { public void setData(PsiElement[] psiElements, String targetPackageName, - final PsiDirectory initialTargetDirectory, + PsiDirectory initialTargetDirectory, boolean isTargetDirectoryFixed, boolean suggestToMoveToAnotherRoot, boolean searchInComments, @@ -268,6 +268,10 @@ public class MoveClassesOrPackagesDialog extends RefactoringDialog { myCbSearchInComments.setSelected(searchInComments); myCbSearchTextOccurences.setSelected(searchForTextOccurences); + if (initialTargetDirectory != null && + JavaMoveClassesOrPackagesHandler.packageHasMultipleDirectoriesInModule(myProject, initialTargetDirectory)) { + initialTargetDirectory = null; + } ((DestinationFolderComboBox)myDestinationFolderCB).setData(myProject, initialTargetDirectory, new Pass<String>() { @Override diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java index cc1658f63a71..e55aba9953d2 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java @@ -53,33 +53,28 @@ public class MoveClassesOrPackagesImpl { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesImpl"); public static void doMove(final Project project, - PsiElement[] elements, + PsiElement[] adjustedElements, PsiElement initialTargetElement, final MoveCallback moveCallback) { - final PsiElement[] psiElements = adjustForMove(project, elements, initialTargetElement); - if (psiElements == null) { + if (!CommonRefactoringUtil.checkReadOnlyStatusRecursively(project, Arrays.asList(adjustedElements), true)) { return; } - if (!CommonRefactoringUtil.checkReadOnlyStatusRecursively(project, Arrays.asList(psiElements), true)) { - return; - } - - final String initialTargetPackageName = getInitialTargetPackageName(initialTargetElement, psiElements); - final PsiDirectory initialTargetDirectory = getInitialTargetDirectory(initialTargetElement, psiElements); + final String initialTargetPackageName = getInitialTargetPackageName(initialTargetElement, adjustedElements); + final PsiDirectory initialTargetDirectory = getInitialTargetDirectory(initialTargetElement, adjustedElements); final boolean isTargetDirectoryFixed = initialTargetDirectory == null; boolean searchTextOccurences = false; - for (int i = 0; i < psiElements.length && !searchTextOccurences; i++) { - PsiElement psiElement = psiElements[i]; + for (int i = 0; i < adjustedElements.length && !searchTextOccurences; i++) { + PsiElement psiElement = adjustedElements[i]; searchTextOccurences = TextOccurrencesUtil.isSearchTextOccurencesEnabled(psiElement); } final MoveClassesOrPackagesDialog moveDialog = - new MoveClassesOrPackagesDialog(project, searchTextOccurences, psiElements, initialTargetElement, moveCallback); + new MoveClassesOrPackagesDialog(project, searchTextOccurences, adjustedElements, initialTargetElement, moveCallback); boolean searchInComments = JavaRefactoringSettings.getInstance().MOVE_SEARCH_IN_COMMENTS; boolean searchForTextOccurences = JavaRefactoringSettings.getInstance().MOVE_SEARCH_FOR_TEXT; - moveDialog.setData(psiElements, initialTargetPackageName, initialTargetDirectory, isTargetDirectoryFixed, initialTargetElement == null, searchInComments, - searchForTextOccurences, HelpID.getMoveHelpID(psiElements[0])); + moveDialog.setData(adjustedElements, initialTargetPackageName, initialTargetDirectory, isTargetDirectoryFixed, initialTargetElement == null, searchInComments, + searchForTextOccurences, HelpID.getMoveHelpID(adjustedElements[0])); moveDialog.show(); } diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java index 85e01e2c19a4..f59ce428a75a 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java @@ -244,7 +244,7 @@ public class MoveJavaMemberHandler implements MoveMemberHandler { @Override @Nullable - public PsiElement getAnchor(@NotNull final PsiMember member, @NotNull final PsiClass targetClass) { + public PsiElement getAnchor(@NotNull final PsiMember member, @NotNull final PsiClass targetClass, final Set<PsiMember> membersToMove) { if (member instanceof PsiField && member.hasModifierProperty(PsiModifier.STATIC)) { final List<PsiField> afterFields = new ArrayList<PsiField>(); final PsiExpression psiExpression = ((PsiField)member).getInitializer(); @@ -256,7 +256,7 @@ public class MoveJavaMemberHandler implements MoveMemberHandler { final PsiElement psiElement = expression.resolve(); if (psiElement instanceof PsiField) { final PsiField psiField = (PsiField)psiElement; - if (psiField.getContainingClass() == targetClass && !afterFields.contains(psiField)) { + if ((psiField.getContainingClass() == targetClass || membersToMove.contains(psiField))&& !afterFields.contains(psiField)) { afterFields.add(psiField); } } diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMemberHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMemberHandler.java index ce028217ec3e..bbac32d6b593 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMemberHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMemberHandler.java @@ -50,7 +50,7 @@ public interface MoveMemberHandler { @NotNull MultiMap<PsiElement, String> conflicts); @Nullable - PsiElement getAnchor(@NotNull PsiMember member, @NotNull PsiClass targetClass); + PsiElement getAnchor(@NotNull PsiMember member, @NotNull PsiClass targetClass, Set<PsiMember> membersToMove); boolean changeExternalUsage(@NotNull MoveMembersOptions options, @NotNull MoveMembersProcessor.MoveMembersUsageInfo usage); diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java index fa93b183892a..4efd85f9dd78 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java @@ -157,11 +157,16 @@ public class MoveMembersProcessor extends BaseRefactoringProcessor { // collect anchors to place moved members at final Map<PsiMember, SmartPsiElementPointer<PsiElement>> anchors = new HashMap<PsiMember, SmartPsiElementPointer<PsiElement>>(); + final Map<PsiMember, PsiMember> anchorsInSourceClass = new HashMap<PsiMember, PsiMember>(); for (PsiMember member : myMembersToMove) { final MoveMemberHandler handler = MoveMemberHandler.EP_NAME.forLanguage(member.getLanguage()); if (handler != null) { - final PsiElement anchor = handler.getAnchor(member, targetClass); - anchors.put(member, anchor == null ? null : SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(anchor)); + final PsiElement anchor = handler.getAnchor(member, targetClass, myMembersToMove); + if (anchor instanceof PsiMember && myMembersToMove.contains((PsiMember)anchor)) { + anchorsInSourceClass.put(member, (PsiMember)anchor); + } else { + anchors.put(member, anchor == null ? null : SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(anchor)); + } } } @@ -178,6 +183,7 @@ public class MoveMembersProcessor extends BaseRefactoringProcessor { } // correct references inside moved members and outer references to Inner Classes + final Map<PsiMember, PsiMember> movedMembers = new HashMap<PsiMember, PsiMember>(); for (PsiMember member : myMembersToMove) { ArrayList<PsiReference> refsToBeRebind = new ArrayList<PsiReference>(); for (Iterator<MoveMembersUsageInfo> iterator = otherUsages.iterator(); iterator.hasNext();) { @@ -193,8 +199,21 @@ public class MoveMembersProcessor extends BaseRefactoringProcessor { final RefactoringElementListener elementListener = getTransaction().getElementListener(member); final MoveMemberHandler handler = MoveMemberHandler.EP_NAME.forLanguage(member.getLanguage()); if (handler != null) { - final SmartPsiElementPointer<PsiElement> pointer = anchors.get(member); - PsiMember newMember = handler.doMove(myOptions, member, pointer != null ? pointer.getElement() : null, targetClass); + + final PsiElement anchor; + if (anchorsInSourceClass.containsKey(member)) { + final PsiMember memberInSourceClass = anchorsInSourceClass.get(member); + //anchor should be already moved as myMembersToMove contains members in order they appear in source class + anchor = memberInSourceClass != null ? movedMembers.get(memberInSourceClass) : null; + } + else { + final SmartPsiElementPointer<PsiElement> pointer = anchors.get(member); + anchor = pointer != null ? pointer.getElement() : null; + } + + PsiMember newMember = handler.doMove(myOptions, member, anchor, targetClass); + + movedMembers.put(member, newMember); elementListener.elementMoved(newMember); fixModifierList(member, newMember, usages); diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java index bf80d601c81b..b9496f0e263c 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -500,10 +500,10 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor { public TypeView(@NotNull PsiExpression expr) { PsiType exprType = expr.getType(); exprType = exprType instanceof PsiEllipsisType ? ((PsiEllipsisType)exprType).toArrayType() : exprType; - myOriginType = exprType != null ? GenericsUtil.getVariableTypeByExpressionType(exprType) : null; + myOriginType = GenericsUtil.getVariableTypeByExpressionType(exprType); PsiType type = myTypeEvaluator.evaluateType(expr); type = type instanceof PsiEllipsisType ? ((PsiEllipsisType)type).toArrayType() : type; - myType = type != null ? GenericsUtil.getVariableTypeByExpressionType(type) : null; + myType = GenericsUtil.getVariableTypeByExpressionType(type); myChanged = (myOriginType == null || myType == null) ? false : !myType.equals(myOriginType); } diff --git a/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java b/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java index cb62f4d47492..e9f0888a3050 100644 --- a/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java +++ b/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -18,8 +18,8 @@ package com.intellij.testIntegration; import com.intellij.codeInsight.CodeInsightActionHandler; import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.codeInsight.generation.GenerateMembersUtil; -import com.intellij.codeInsight.generation.GenerationInfo; -import com.intellij.codeInsight.generation.GenerationInfoBase; +import com.intellij.codeInsight.generation.OverrideImplementUtil; +import com.intellij.codeInsight.generation.PsiGenerationInfo; import com.intellij.codeInsight.generation.actions.BaseGenerateAction; import com.intellij.codeInsight.hint.HintManager; import com.intellij.openapi.application.ApplicationManager; @@ -38,7 +38,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class BaseGenerateTestSupportMethodAction extends BaseGenerateAction { @@ -164,30 +164,18 @@ public class BaseGenerateTestSupportMethodAction extends BaseGenerateAction { } @Nullable - private PsiMethod generateDummyMethod(Editor editor, PsiFile file) throws IncorrectOperationException { - List<GenerationInfo> members = new ArrayList<GenerationInfo>(); - + private static PsiMethod generateDummyMethod(Editor editor, PsiFile file) throws IncorrectOperationException { final PsiMethod method = TestIntegrationUtils.createDummyMethod(file); - final PsiMethod[] result = new PsiMethod[1]; - - members.add(new GenerationInfoBase() { - @NotNull - public PsiMember getPsiMember() { - return method; - } - - public void insert(PsiClass aClass, PsiElement anchor, boolean before) throws IncorrectOperationException { - result[0] = (PsiMethod)GenerateMembersUtil.insert(aClass, method, anchor, before); - } - }); + final PsiGenerationInfo<PsiMethod> info = OverrideImplementUtil.createGenerationInfo(method); int offset = findOffsetToInsertMethodTo(editor, file); + GenerateMembersUtil.insertMembersAtOffset(file, offset, Collections.singletonList(info)); - GenerateMembersUtil.insertMembersAtOffset(file, offset, members); - return result[0] != null ? CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(result[0]) : null; + final PsiMethod member = info.getPsiMember(); + return member != null ? CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(member) : null; } - private int findOffsetToInsertMethodTo(Editor editor, PsiFile file) { + private static int findOffsetToInsertMethodTo(Editor editor, PsiFile file) { int result = editor.getCaretModel().getOffset(); PsiClass classAtCursor = PsiTreeUtil.getParentOfType(file.findElementAt(result), PsiClass.class, false); diff --git a/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java b/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java index d4f579084216..8a2ed8be9d12 100644 --- a/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java +++ b/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java @@ -33,9 +33,11 @@ import org.jetbrains.annotations.Nullable; public class PsiClassConverter extends Converter<PsiClass> implements CustomReferenceConverter<PsiClass> { public PsiClass fromString(final String s, final ConvertContext context) { + if (StringUtil.isEmptyOrSpaces(s)) return null; + final DomElement element = context.getInvocationElement(); final GlobalSearchScope scope = element instanceof GenericDomValue ? getScope(context) : null; - return DomJavaUtil.findClass(s, context.getFile(), context.getModule(), scope); + return DomJavaUtil.findClass(s.trim(), context.getFile(), context.getModule(), scope); } @Nullable |