summaryrefslogtreecommitdiff
path: root/java/java-impl/src/com/intellij
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2013-08-07 11:11:08 -0700
committerTor Norbye <tnorbye@google.com>2013-08-07 11:11:08 -0700
commit6739a8f0977b70ddc8a8283b169902da3f2eecb3 (patch)
tree5c5573c2ac01544f02d9318671aa558769726289 /java/java-impl/src/com/intellij
parentc1ace1f7e1e49c81bb4b75377c99f07be340abfe (diff)
downloadidea-6739a8f0977b70ddc8a8283b169902da3f2eecb3.tar.gz
Snapshot af729d01433bb5bbd6ca93c0fdf9778b36d624ce from master branch of git://git.jetbrains.org/idea/community.git
Change-Id: I214dd066d0d27444a26166c0eae1a5aaf3705d49
Diffstat (limited to 'java/java-impl/src/com/intellij')
-rw-r--r--java/java-impl/src/com/intellij/application/options/ImportLayoutPanel.java1
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java15
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/ExcludeFromCompletionLookupActionProvider.java6
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java4
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java15
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java7
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java14
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java4
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java7
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java84
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java (renamed from java/java-impl/src/com/intellij/codeInsight/completion/JavaOverrideCompletionContributor.java)93
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java5
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java9
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java4
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java4
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/ChainCompletionStringUtil.java94
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/Constants.java20
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/CompletionContributorPatternUtil.java33
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsCompletionContributor.java206
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsWeigher.java36
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContext.java156
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContextStringUtil.java36
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantStaticMethod.java45
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantVariableGetter.java31
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextUtil.java245
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionLookupElementUtil.java53
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionMethodCallLookupElement.java88
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionNewVariableLookupElement.java79
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/WeightableChainLookupElement.java22
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/GetterLookupSubLookupElement.java35
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/StaticMethodSubLookupElement.java51
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/SubLookupElement.java13
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/VariableSubLookupElement.java25
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedNotDeprecatedMethodsResolver.java36
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedRelevantStaticMethodSearcher.java122
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainRelevance.java91
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainsSearcher.java206
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchService.java93
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchUtil.java80
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChain.java160
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChainLookupRangingHelper.java230
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/SearchInitializer.java128
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/WeightAware.java29
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/service/OverridenMethodsService.java65
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/service/SingletonService.java89
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java8
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java38
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/RemoveSuppressWarningAction.java193
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java19
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java45
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java11
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java95
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java51
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java15
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java151
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java242
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BringVariableIntoScopeFix.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java4
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java65
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java10
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterSetterPropertyFromUsageFix.java5
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java7
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java3
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java56
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceInaccessibleFieldWithGetterSetterFix.java3
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java18
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java3
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableParameterizedTypeFix.java7
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandler.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/editorActions/JavadocTypedHandler.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java3
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/DocTagSelectioner.java12
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java8
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java14
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/generation/GenerateFieldOrPropertyHandler.java77
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java59
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java31
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java13
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java4
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveFieldAssignmentToInitializerAction.java48
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java4
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/lookup/PackageLookupItem.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java4
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java332
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalAnnotator.java218
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java310
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java13
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsEP.java36
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java9
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java11
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/deadCode/RefEntryPointFilter.java3
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java50
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java53
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java820
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java28
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/emptyMethod/EmptyMethodInspection.java8
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java386
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/inconsistentLanguageLevel/InconsistentLanguageLevelInspection.java9
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicCompletionContributor.java4
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java18
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java564
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java199
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java97
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java285
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/reference/RefJavaFileImpl.java30
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java9
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java418
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java687
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/reference/RefPackageImpl.java86
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/reference/RefParameterImpl.java203
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/sameReturnValue/SameReturnValueInspection.java100
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java4
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java34
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyAnnotator.java50
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyInspection.java119
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java311
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/unusedImport/UnusedImportLocalInspection.java4
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/unusedLibraries/UnusedLibrariesInspection.java270
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java11
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/unusedReturnValue/UnusedReturnValue.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java12
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/util/RefFilter.java44
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityExtension.java24
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java600
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/ArrayListKeyDescriptor.java50
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashMapKeyDescriptor.java54
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashSetKeyDescriptor.java54
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/AsmUtil.java129
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/CompilerOutputFilesUtil.java64
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/FileVisitorService.java53
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java141
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexUtil.java21
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java360
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/ClassFileData.java116
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/CompilerOutputBaseGramsIndex.java47
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/GuavaHashMultiSetExternalizer.java56
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignature.java183
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignatureChain.java44
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodsUsageIndex.java91
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/UsageIndexValue.java69
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/Bigram.java22
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/BigramMethodsUsageIndex.java86
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/SimpleBigramsExtractor.java55
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/CallingLocation.java71
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodCallingLocationExtractor.java157
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodCallingLocationIndex.java94
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodNameAndQualifier.java81
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/VariableType.java15
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickInheritanceIndex.java96
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickMethodsIndex.java103
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickOverrideUtil.java23
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/MethodShortSignature.java71
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/MethodShortSignatureWithWeight.java53
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/ParamsInMethodOccurrencesIndex.java116
-rw-r--r--java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/TwinVariablesIndex.java137
-rw-r--r--java/java-impl/src/com/intellij/externalSystem/JavaProjectData.java9
-rw-r--r--java/java-impl/src/com/intellij/ide/actions/JavaCreateTemplateInPackageAction.java4
-rw-r--r--java/java-impl/src/com/intellij/ide/actions/JavaQualifiedNameProvider.java47
-rw-r--r--java/java-impl/src/com/intellij/ide/scopeView/ClassesScopeTreeStructureExpander.java2
-rw-r--r--java/java-impl/src/com/intellij/jarFinder/FindJarFix.java301
-rw-r--r--java/java-impl/src/com/intellij/jarFinder/FindJarQuickFixProvider.java22
-rw-r--r--java/java-impl/src/com/intellij/jarFinder/JavaFindJarFix.java78
-rw-r--r--java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java70
-rw-r--r--java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java87
-rw-r--r--java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java77
-rw-r--r--java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java8
-rw-r--r--java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java4
-rw-r--r--java/java-impl/src/com/intellij/lang/java/JavaLiteralEscaper.java45
-rw-r--r--java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java19
-rw-r--r--java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java24
-rw-r--r--java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java6
-rw-r--r--java/java-impl/src/com/intellij/openapi/roots/impl/JavaLanguageLevelPusher.java13
-rw-r--r--java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java3
-rw-r--r--java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java4
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java6
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfoFactory.java3
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/codeStyle/FormatCommentsProcessor.java82
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java7
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/CommentFormatter.java81
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDComment.java15
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java26
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/GenericReference.java3
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java4
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java10
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PackagePrefixFileSystemItemImpl.java (renamed from java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PackagePrefixFileSystemItem.java)19
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiPackageReference.java7
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/tree/injected/JavaConcatenationInjectorManager.java28
-rw-r--r--java/java-impl/src/com/intellij/psi/resolve/JavaMethodResolveHelper.java28
-rw-r--r--java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java3
-rw-r--r--java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java4
-rw-r--r--java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java2
-rw-r--r--java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsDialog.java5
-rw-r--r--java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java3
-rw-r--r--java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java5
-rw-r--r--java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java4
-rw-r--r--java/java-impl/src/com/intellij/refactoring/introduceparameterobject/usageInfo/AppendAccessorsUsageInfo.java6
-rw-r--r--java/java-impl/src/com/intellij/refactoring/removemiddleman/RemoveMiddlemanProcessor.java3
-rw-r--r--java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticTestRenamerFactory.java41
-rw-r--r--java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java25
-rw-r--r--java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteOverrideAnnotation.java43
-rw-r--r--java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeletePrivatizeMethod.java13
-rw-r--r--java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java2
-rw-r--r--java/java-impl/src/com/intellij/unscramble/ThreadDumpConsoleFactory.java40
-rw-r--r--java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java8
-rw-r--r--java/java-impl/src/com/intellij/usages/impl/rules/ClassGroupingRule.java2
-rw-r--r--java/java-impl/src/com/intellij/util/xml/CanonicalPsiTypeConverterImpl.java2
209 files changed, 7379 insertions, 7366 deletions
diff --git a/java/java-impl/src/com/intellij/application/options/ImportLayoutPanel.java b/java/java-impl/src/com/intellij/application/options/ImportLayoutPanel.java
index d82d51f56b6e..e7d0082155db 100644
--- a/java/java-impl/src/com/intellij/application/options/ImportLayoutPanel.java
+++ b/java/java-impl/src/com/intellij/application/options/ImportLayoutPanel.java
@@ -18,7 +18,6 @@ package com.intellij.application.options;
import com.intellij.ide.highlighter.JavaHighlightingColors;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationBundle;
-import com.intellij.openapi.editor.SyntaxHighlighterColors;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.psi.codeStyle.PackageEntry;
import com.intellij.psi.codeStyle.PackageEntryTable;
diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java
index 6a3d3f69df01..89b606e85324 100644
--- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java
@@ -940,7 +940,7 @@ public class ExpectedTypesProvider {
}
ParameterTypeInferencePolicy policy = forCompletion ? CompletionParameterTypeInferencePolicy.INSTANCE : DefaultParameterTypeInferencePolicy.INSTANCE;
-
+
Set<ExpectedTypeInfo> array = new LinkedHashSet<ExpectedTypeInfo>();
for (CandidateInfo candidateInfo : methodCandidates) {
PsiMethod method = (PsiMethod)candidateInfo.getElement();
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java
index ac8297def978..1bdedafa4219 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java
@@ -140,9 +140,10 @@ public class AllClassesGetter {
}
};
- public static void processJavaClasses(final CompletionParameters parameters,
- final PrefixMatcher prefixMatcher, final boolean filterByScope,
- final Consumer<PsiClass> consumer) {
+ public static void processJavaClasses(@NotNull final CompletionParameters parameters,
+ @NotNull final PrefixMatcher prefixMatcher,
+ final boolean filterByScope,
+ @NotNull final Consumer<PsiClass> consumer) {
final PsiElement context = parameters.getPosition();
final Project project = context.getProject();
final GlobalSearchScope scope = filterByScope ? context.getContainingFile().getResolveScope() : GlobalSearchScope.allScope(project);
@@ -167,10 +168,10 @@ public class AllClassesGetter {
processJavaClasses(prefixMatcher, project, scope, processor);
}
- public static void processJavaClasses(final PrefixMatcher prefixMatcher,
- Project project,
- GlobalSearchScope scope,
- Processor<PsiClass> processor) {
+ public static void processJavaClasses(@NotNull final PrefixMatcher prefixMatcher,
+ @NotNull Project project,
+ @NotNull GlobalSearchScope scope,
+ @NotNull Processor<PsiClass> processor) {
AllClassesSearch.search(scope, project, new Condition<String>() {
@Override
public boolean value(String s) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeFromCompletionLookupActionProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeFromCompletionLookupActionProvider.java
index 0440a33aed22..bc00fa223385 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeFromCompletionLookupActionProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeFromCompletionLookupActionProvider.java
@@ -16,13 +16,13 @@
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.daemon.impl.actions.AddImportAction;
-import com.intellij.codeInsight.daemon.impl.quickfix.StaticImportMethodFix;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupActionProvider;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementAction;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
+import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.Nullable;
@@ -39,12 +39,12 @@ public class ExcludeFromCompletionLookupActionProvider implements LookupActionPr
} else if (o instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)o;
if (method.hasModifierProperty(PsiModifier.STATIC)) {
- addExcludes(consumer, method, StaticImportMethodFix.getMemberQualifiedName(method));
+ addExcludes(consumer, method, PsiUtil.getMemberQualifiedName(method));
}
} else if (o instanceof PsiField) {
final PsiField field = (PsiField)o;
if (field.hasModifierProperty(PsiModifier.STATIC)) {
- addExcludes(consumer, field, StaticImportMethodFix.getMemberQualifiedName(field));
+ addExcludes(consumer, field, PsiUtil.getMemberQualifiedName(field));
}
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java
index eb19c574c872..f7140fea80eb 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java
@@ -17,7 +17,7 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.*;
import com.intellij.diagnostic.LogMessageEx;
-import com.intellij.diagnostic.errordialog.Attachment;
+import com.intellij.diagnostic.AttachmentFactory;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.ClassConditionKey;
@@ -120,7 +120,7 @@ public class JavaChainLookupElement extends LookupElementDecorator<LookupElement
"atTail=" + atTail + "\n" +
"offset=" + context.getTailOffset() + "\n" +
DebugUtil.currentStackTrace(),
- new Attachment(context.getDocument())));
+ AttachmentFactory.createAttachment(context.getDocument())));
}
document.replaceString(context.getTailOffset() - 1, context.getTailOffset(), ".");
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 a25001065d11..71360e7ba348 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java
@@ -30,9 +30,11 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.patterns.PsiJavaPatterns;
+import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtil;
public class JavaCharFilter extends CharFilter {
@@ -67,9 +69,16 @@ public class JavaCharFilter extends CharFilter {
if (c == ':') {
PsiFile file = lookup.getPsiFile();
PsiDocumentManager.getInstance(file.getProject()).commitDocument(lookup.getEditor().getDocument());
- PsiElement element = lookup.getPsiElement();
- if (PsiTreeUtil.getParentOfType(element, PsiSwitchLabelStatement.class) != null ||
- PsiTreeUtil.getParentOfType(element, PsiConditionalExpression.class) != null) {
+ PsiElement leaf = file.findElementAt(lookup.getEditor().getCaretModel().getOffset() - 1);
+ if (PsiUtil.getLanguageLevel(file).isAtLeast(LanguageLevel.JDK_1_8)) {
+ PsiStatement statement = PsiTreeUtil.getParentOfType(leaf, PsiStatement.class);
+ if (statement == null ||
+ statement.getTextRange().getStartOffset() != leaf.getTextRange().getStartOffset()) { // not typing a statement label
+ return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
+ }
+ }
+ if (PsiTreeUtil.getParentOfType(leaf, PsiSwitchLabelStatement.class) != null ||
+ PsiTreeUtil.getParentOfType(leaf, PsiConditionalExpression.class) != null) {
return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
}
return Result.HIDE_LOOKUP;
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java
index d1166c749091..df113a5a77a1 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java
@@ -30,6 +30,7 @@ import com.intellij.psi.*;
import com.intellij.psi.filters.ClassFilter;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.filters.TrueFilter;
+import com.intellij.psi.filters.classes.AnnotationTypeFilter;
import com.intellij.psi.filters.element.ExcludeDeclaredFilter;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
@@ -78,14 +79,16 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
return false;
}
- public static void addAllClasses(CompletionParameters parameters,
+ public static void addAllClasses(@NotNull CompletionParameters parameters,
final boolean filterByScope,
@NotNull final PrefixMatcher matcher,
@NotNull final Consumer<LookupElement> consumer) {
final PsiElement insertedElement = parameters.getPosition();
final ElementFilter filter =
- IN_TYPE_PARAMETER.accepts(insertedElement) ? new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class)) : TrueFilter.INSTANCE;
+ IN_TYPE_PARAMETER.accepts(insertedElement) ? new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class)) :
+ JavaCompletionContributor.ANNOTATION_NAME.accepts(insertedElement) ? new AnnotationTypeFilter() :
+ TrueFilter.INSTANCE;
final boolean inJavaContext = parameters.getPosition() instanceof PsiIdentifier;
final boolean afterNew = AFTER_NEW.accepts(insertedElement);
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 083649aeb1a6..3ce6050837b7 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java
@@ -39,6 +39,7 @@ import com.intellij.patterns.PsiNameValuePairPattern;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.filters.*;
+import com.intellij.psi.filters.classes.AnnotationTypeFilter;
import com.intellij.psi.filters.classes.AssignableFromContextFilter;
import com.intellij.psi.filters.element.ExcludeDeclaredFilter;
import com.intellij.psi.filters.element.ModifierFilter;
@@ -75,6 +76,9 @@ public class JavaCompletionContributor extends CompletionContributor {
ourCompletionData.put(LanguageLevel.JDK_1_3, new JavaCompletionData());
}
+ public static final ElementPattern<PsiElement> ANNOTATION_NAME = psiElement().
+ withParents(PsiJavaCodeReferenceElement.class, PsiAnnotation.class).afterLeaf("@");
+
private static JavaCompletionData getCompletionData(LanguageLevel level) {
final Set<Map.Entry<LanguageLevel, JavaCompletionData>> entries = ourCompletionData.entrySet();
for (Map.Entry<LanguageLevel, JavaCompletionData> entry : entries) {
@@ -113,6 +117,10 @@ public class JavaCompletionContributor extends CompletionContributor {
return new AndFilter(ElementClassFilter.CLASS, new NotFilter(new AssignableFromContextFilter()));
}
+ if (ANNOTATION_NAME.accepts(position)) {
+ return new AnnotationTypeFilter();
+ }
+
if (JavaCompletionData.DECLARATION_START.accepts(position) ||
JavaCompletionData.isInsideParameterList(position) ||
psiElement().inside(psiElement(PsiJavaCodeReferenceElement.class).withParent(psiAnnotation())).accepts(position)) {
@@ -223,10 +231,10 @@ public class JavaCompletionContributor extends CompletionContributor {
result.addElement(LookupElementBuilder.create("*"));
}
- Set<String> usedWords = addReferenceVariants(parameters, result, inheritors);
-
addKeywords(parameters, result);
+ Set<String> usedWords = addReferenceVariants(parameters, result, inheritors);
+
if (psiElement().inside(PsiLiteralExpression.class).accepts(position)) {
PsiReference reference = position.getContainingFile().findReferenceAt(parameters.getOffset());
if (reference == null || reference.isSoft()) {
@@ -234,7 +242,7 @@ public class JavaCompletionContributor extends CompletionContributor {
}
}
- JavaOverrideCompletionContributor.fillCompletionVariants(parameters, result);
+ JavaGenerateMemberCompletionContributor.fillCompletionVariants(parameters, result);
addAllClasses(parameters, result, inheritors);
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 1de9f59cc67a..f9405ad0afc8 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java
@@ -68,7 +68,7 @@ public class JavaCompletionSorting {
CompletionSorter sorter = CompletionSorter.defaultSorter(parameters, result.getPrefixMatcher());
if (!smart && afterNew) {
sorter = sorter.weighBefore("liftShorter", new PreferExpected(true, expectedTypes));
- } else {
+ } else if (PsiTreeUtil.getParentOfType(position, PsiReferenceList.class) == null) {
sorter = ((CompletionSorterImpl)sorter).withClassifier("liftShorterClasses", true, new LiftShorterClasses(position));
}
if (smart) {
@@ -124,7 +124,7 @@ public class JavaCompletionSorting {
public Comparable weigh(@NotNull LookupElement element) {
final Object o = element.getObject();
if (o instanceof PsiKeyword) return -3;
- if (!(o instanceof PsiMember) || element.getUserData(JavaOverrideCompletionContributor.OVERRIDE_ELEMENT) != null) {
+ if (!(o instanceof PsiMember) || element.getUserData(JavaGenerateMemberCompletionContributor.GENERATE_ELEMENT) != null) {
return 0;
}
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 163b2c6ca3bf..6dc59284748f 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java
@@ -20,7 +20,6 @@ import com.intellij.codeInsight.completion.impl.CamelHumpMatcher;
import com.intellij.codeInsight.completion.scope.CompletionElement;
import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
-import com.intellij.codeInsight.daemon.impl.quickfix.StaticImportMethodFix;
import com.intellij.codeInsight.guess.GuessManager;
import com.intellij.codeInsight.lookup.*;
import com.intellij.lang.StdLanguages;
@@ -125,7 +124,7 @@ public class JavaCompletionUtil {
}
public static boolean isInExcludedPackage(@NotNull final PsiMember member, boolean allowInstanceInnerClasses) {
- final String name = StaticImportMethodFix.getMemberQualifiedName(member);
+ final String name = PsiUtil.getMemberQualifiedName(member);
if (name == null) return false;
if (!member.hasModifierProperty(PsiModifier.STATIC)) {
@@ -362,6 +361,7 @@ public class JavaCompletionUtil {
PsiElement ctx = createContextWithXxxVariable(element, composite);
javaReference = (PsiReferenceExpression) JavaPsiFacade.getElementFactory(element.getProject()).createExpressionFromText("xxx.xxx", ctx);
qualifierType = runtimeQualifier;
+ processor.setQualifierType(qualifierType);
}
javaReference.processVariants(processor);
@@ -620,6 +620,9 @@ public class JavaCompletionUtil {
if (element instanceof PsiJavaCodeReferenceElement) {
return mayHaveSideEffects(((PsiJavaCodeReferenceElement)element).getQualifier());
}
+ if (element instanceof PsiParenthesizedExpression) {
+ return mayHaveSideEffects(((PsiParenthesizedExpression)element).getExpression());
+ }
return true;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
index 9e18f7bf8448..2259d2bcf23c 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
@@ -18,16 +18,15 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.completion.scope.CompletionElement;
import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
+import com.intellij.codeInsight.editorActions.wordSelection.DocTagSelectioner;
import com.intellij.codeInsight.lookup.*;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.SuppressionUtil;
import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.CaretModel;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.EditorModificationUtil;
-import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.editor.*;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.PsiJavaPatterns;
@@ -38,20 +37,20 @@ import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.filters.TrueFilter;
import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
+import com.intellij.psi.impl.source.javadoc.PsiDocParamRef;
import com.intellij.psi.javadoc.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.ProcessingContext;
-import com.intellij.util.Processor;
-import com.intellij.util.SystemProperties;
+import com.intellij.util.*;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import java.util.StringTokenizer;
/**
@@ -113,13 +112,80 @@ public class JavaDocCompletionContributor extends CompletionContributor {
});
}
+ private static PsiParameter getDocTagParam(PsiElement tag) {
+ if (tag instanceof PsiDocTag && "param".equals(((PsiDocTag)tag).getName())) {
+ PsiDocTagValue value = ((PsiDocTag)tag).getValueElement();
+ if (value instanceof PsiDocParamRef) {
+ final PsiReference psiReference = value.getReference();
+ PsiElement target = psiReference != null ? psiReference.resolve() : null;
+ if (target instanceof PsiParameter) {
+ return (PsiParameter)target;
+ }
+ }
+ }
+ return null;
+ }
+
@Override
public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
- if (PsiJavaPatterns.psiElement(JavaDocTokenType.DOC_COMMENT_DATA).accepts(parameters.getPosition())) return;
+
+ PsiElement position = parameters.getPosition();
+ if (PsiJavaPatterns.psiElement(JavaDocTokenType.DOC_COMMENT_DATA).accepts(position)) {
+ final PsiParameter param = getDocTagParam(position.getParent());
+ if (param != null) {
+ suggestSimilarParameterDescriptions(result, position, param);
+ }
+
+ return;
+ }
super.fillCompletionVariants(parameters, result);
}
+ private static void suggestSimilarParameterDescriptions(CompletionResultSet result, PsiElement position, final PsiParameter param) {
+ final Set<String> descriptions = ContainerUtil.newHashSet();
+ position.getContainingFile().accept(new PsiRecursiveElementWalkingVisitor() {
+ @Override
+ public void visitElement(PsiElement element) {
+ PsiParameter param1 = getDocTagParam(element);
+ if (param1 != null && param1 != param &&
+ Comparing.equal(param1.getName(), param.getName()) && Comparing.equal(param1.getType(), param.getType())) {
+ String text = "";
+ for (PsiElement psiElement : ((PsiDocTag)element).getDataElements()) {
+ if (psiElement != ((PsiDocTag)element).getValueElement()) {
+ text += psiElement.getText();
+ }
+ }
+ text = text.trim();
+ if (text.contains(" ")) {
+ descriptions.add(text);
+ }
+ }
+
+ super.visitElement(element);
+ }
+ });
+ for (String description : descriptions) {
+ result.addElement(LookupElementBuilder.create(description).withInsertHandler(new InsertHandler<LookupElement>() {
+ @Override
+ public void handleInsert(InsertionContext context, LookupElement item) {
+ if (context.getCompletionChar() != Lookup.REPLACE_SELECT_CHAR) return;
+
+ context.commitDocument();
+ PsiDocTag docTag = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiDocTag.class, false);
+ if (docTag != null) {
+ Document document = context.getDocument();
+ int tagEnd = DocTagSelectioner.getDocTagRange(docTag, document.getCharsSequence(), 0).getEndOffset();
+ int tail = context.getTailOffset();
+ if (tail < tagEnd) {
+ document.deleteString(tail, tagEnd);
+ }
+ }
+ }
+ }));
+ }
+ }
+
private static class TagChooser extends CompletionProvider<CompletionParameters> {
@Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaOverrideCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java
index 7467edc91687..ee7a96a1dd4f 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaOverrideCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java
@@ -22,6 +22,7 @@ import com.intellij.codeInsight.generation.PsiGenerationInfo;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.icons.AllIcons;
+import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
@@ -29,7 +30,10 @@ import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.psi.util.PsiFormatUtilBase;
import com.intellij.ui.RowIcon;
import com.intellij.util.VisibilityUtil;
+import com.intellij.util.containers.ContainerUtil;
+import javax.swing.*;
+import java.util.Arrays;
import java.util.List;
import static com.intellij.patterns.PlatformPatterns.psiElement;
@@ -37,8 +41,8 @@ import static com.intellij.patterns.PlatformPatterns.psiElement;
/**
* @author peter
*/
-public class JavaOverrideCompletionContributor {
- static final Key<Boolean> OVERRIDE_ELEMENT = Key.create("OVERRIDE_ELEMENT");
+public class JavaGenerateMemberCompletionContributor {
+ static final Key<Boolean> GENERATE_ELEMENT = Key.create("GENERATE_ELEMENT");
public static void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result) {
if (parameters.getCompletionType() != CompletionType.BASIC && parameters.getCompletionType() != CompletionType.SMART) {
@@ -51,6 +55,7 @@ public class JavaOverrideCompletionContributor {
andNot(psiElement().afterLeaf(psiElement().inside(PsiModifierList.class))).accepts(position)) {
final PsiClass parent = CompletionUtil.getOriginalElement((PsiClass)position.getParent().getParent().getParent());
if (parent != null) {
+ addGetterSetterElements(result, parent);
addSuperSignatureElements(parent, true, result);
addSuperSignatureElements(parent, false, result);
}
@@ -58,9 +63,38 @@ public class JavaOverrideCompletionContributor {
}
+ private static void addGetterSetterElements(CompletionResultSet result, PsiClass parent) {
+ List<PsiMethod> prototypes = ContainerUtil.newArrayList();
+ for (PsiField field : parent.getFields()) {
+ if (!(field instanceof PsiEnumConstant)) {
+ prototypes.add(GenerateMembersUtil.generateGetterPrototype(field));
+ prototypes.add(GenerateMembersUtil.generateSetterPrototype(field));
+ }
+ }
+ for (final PsiMethod prototype : prototypes) {
+ if (parent.findMethodBySignature(prototype, false) == null) {
+ Icon icon = prototype.getIcon(Iconable.ICON_FLAG_VISIBILITY);
+ result.addElement(createGenerateMethodElement(prototype, PsiSubstitutor.EMPTY, icon, "", new InsertHandler<LookupElement>() {
+ @Override
+ public void handleInsert(InsertionContext context, LookupElement item) {
+ removeLookupString(context);
+
+ insertGenerationInfos(context, Arrays.asList(new PsiGenerationInfo<PsiMethod>(prototype)));
+ }
+ }));
+ }
+ }
+ }
+
+ private static void removeLookupString(InsertionContext context) {
+ context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
+ context.commitDocument();
+ }
+
private static void addSuperSignatureElements(final PsiClass parent, boolean implemented, CompletionResultSet result) {
for (CandidateInfo candidate : OverrideImplementExploreUtil.getMethodsToOverrideImplement(parent, implemented)) {
PsiMethod baseMethod = (PsiMethod)candidate.getElement();
+ assert baseMethod != null;
PsiClass baseClass = baseMethod.getContainingClass();
if (!baseMethod.isConstructor() && baseClass != null) {
result.addElement(createOverridingLookupElement(parent, implemented, baseMethod, baseClass, candidate.getSubstitutor()));
@@ -72,39 +106,48 @@ public class JavaOverrideCompletionContributor {
boolean implemented,
final PsiMethod baseMethod,
PsiClass baseClass, PsiSubstitutor substitutor) {
- String methodName = baseMethod.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(baseMethod, substitutor, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_NAME);
+ RowIcon icon = new RowIcon(2);
+ icon.setIcon(baseMethod.getIcon(0), 0);
+ icon.setIcon(implemented ? AllIcons.Gutter.ImplementingMethod : AllIcons.Gutter.OverridingMethod, 1);
- InsertHandler<LookupElement> insertHandler = new InsertHandler<LookupElement>() {
+ return createGenerateMethodElement(baseMethod, substitutor, icon, baseClass.getName(), new InsertHandler<LookupElement>() {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
- context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
- context.commitDocument();
+ removeLookupString(context);
List<PsiMethod> prototypes = OverrideImplementUtil.overrideOrImplementMethod(parent, baseMethod, false);
- List<PsiGenerationInfo<PsiMethod>> infos = OverrideImplementUtil.convert2GenerationInfos(prototypes);
- List<PsiGenerationInfo<PsiMethod>> newInfos = GenerateMembersUtil.insertMembersAtOffset(context.getFile(), context.getStartOffset(), infos);
- if (!newInfos.isEmpty()) {
- newInfos.get(0).positionCaret(context.getEditor(), true);
- }
+ insertGenerationInfos(context, OverrideImplementUtil.convert2GenerationInfos(prototypes));
}
- };
+ });
+ }
- RowIcon icon = new RowIcon(2);
- icon.setIcon(baseMethod.getIcon(0), 0);
- icon.setIcon(implemented ? AllIcons.Gutter.ImplementingMethod : AllIcons.Gutter.OverridingMethod, 1);
+ private static void insertGenerationInfos(InsertionContext context, List<PsiGenerationInfo<PsiMethod>> infos) {
+ List<PsiGenerationInfo<PsiMethod>> newInfos = GenerateMembersUtil
+ .insertMembersAtOffset(context.getFile(), context.getStartOffset(), infos);
+ if (!newInfos.isEmpty()) {
+ newInfos.get(0).positionCaret(context.getEditor(), true);
+ }
+ }
+
+ private static LookupElementBuilder createGenerateMethodElement(PsiMethod prototype,
+ PsiSubstitutor substitutor,
+ Icon icon,
+ String typeText, InsertHandler<LookupElement> insertHandler) {
+ String methodName = prototype.getName();
+
+ String visibility = VisibilityUtil.getVisibilityModifier(prototype.getModifierList());
+ String modifiers = (visibility == PsiModifier.PACKAGE_LOCAL ? "" : visibility + " ");
+
+ PsiType type = substitutor.substitute(prototype.getReturnType());
+ String signature = modifiers + (type == null ? "" : type.getPresentableText() + " ") + methodName;
+
+ String parameters = PsiFormatUtil.formatMethod(prototype, substitutor, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_NAME);
- LookupElementBuilder element = LookupElementBuilder.create(baseMethod, signature).withLookupString(methodName).
+ LookupElementBuilder element = LookupElementBuilder.create(prototype, signature).withLookupString(methodName).
withLookupString(signature).withInsertHandler(insertHandler).
- appendTailText(parameters, false).appendTailText(" {...}", true).withTypeText(baseClass.getName()).withIcon(icon);
- element.putUserData(OVERRIDE_ELEMENT, true);
+ appendTailText(parameters, false).appendTailText(" {...}", true).withTypeText(typeText).withIcon(icon);
+ element.putUserData(GENERATE_ELEMENT, true);
return element;
}
}
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 b2896f336a9a..d995a9e3d475 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java
@@ -17,6 +17,7 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
import com.intellij.codeInsight.lookup.*;
+import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
@@ -66,6 +67,10 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor {
return;
}
+ if (parameters.getInvocationCount() == 0 && TemplateManagerImpl.getTemplateState(parameters.getEditor()) != null) {
+ return;
+ }
+
PsiElement position = parameters.getPosition();
final Set<LookupElement> lookupSet = new THashSet<LookupElement>();
if (psiElement(PsiIdentifier.class).andNot(INSIDE_TYPE_PARAMS_PATTERN).withParent(
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 e099338792e3..c28c80767326 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java
@@ -51,14 +51,13 @@ public class JavaNoVariantsDelegator extends CompletionContributor {
if (empty) {
delegate(parameters, JavaCompletionSorting.addJavaSorting(parameters, result));
- } else if (Registry.is("ide.completion.show.all.classes") || Registry.is("ide.completion.show.better.matching.classes")) {
- if (parameters.getInvocationCount() <= 1 &&
+ } else if (Registry.is("ide.completion.show.better.matching.classes")) {
+ if (parameters.getCompletionType() == CompletionType.BASIC &&
+ parameters.getInvocationCount() <= 1 &&
JavaCompletionContributor.mayStartClassName(result) &&
JavaCompletionContributor.isClassNamePossible(parameters) &&
!JavaSmartCompletionContributor.AFTER_NEW.accepts(parameters.getPosition())) {
- if (Registry.is("ide.completion.show.better.matching.classes")) {
- result = result.withPrefixMatcher(new BetterPrefixMatcher(result.getPrefixMatcher(), BetterPrefixMatcher.getBestMatchingDegree(plainResults)));
- }
+ result = result.withPrefixMatcher(new BetterPrefixMatcher(result.getPrefixMatcher(), BetterPrefixMatcher.getBestMatchingDegree(plainResults)));
suggestNonImportedClasses(parameters, result);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java
index 5e7af80e7d0d..9710f7550c99 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java
@@ -474,10 +474,10 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
return;
}
if (parent instanceof PsiParenthesizedExpression) {
- context.setDummyIdentifier("xxx)yyy "); // to handle type cast
+ context.setDummyIdentifier(CompletionUtil.DUMMY_IDENTIFIER_TRIMMED + ")" + CompletionUtil.DUMMY_IDENTIFIER_TRIMMED + " "); // to handle type cast
return;
}
}
- context.setDummyIdentifier("xxx");
+ context.setDummyIdentifier(CompletionUtil.DUMMY_IDENTIFIER_TRIMMED);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java
index f316b0a92ed2..f4adccc7140d 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java
@@ -284,7 +284,9 @@ public class ReferenceExpressionCompletionContributor {
final PsiType expectedType = parameters.getExpectedType();
if (!OBJECT_METHOD_PATTERN.accepts(object) || allowGetClass(object, parameters)) {
if (parameters.getParameters().getInvocationCount() >= 3 || !itemType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
- addChainedCallVariants(element, baseItem, result, itemType, expectedType, parameters);
+ if (!(object instanceof PsiMethod && ((PsiMethod)object).getParameterList().getParametersCount() > 0)) {
+ addChainedCallVariants(element, baseItem, result, itemType, expectedType, parameters);
+ }
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/ChainCompletionStringUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/ChainCompletionStringUtil.java
new file mode 100644
index 000000000000..688fadaf613c
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/ChainCompletionStringUtil.java
@@ -0,0 +1,94 @@
+package com.intellij.codeInsight.completion.methodChains;
+
+import com.intellij.openapi.util.text.StringUtilRt;
+import com.intellij.psi.CommonClassNames;
+import com.intellij.psi.PsiPrimitiveType;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class ChainCompletionStringUtil {
+ private ChainCompletionStringUtil() {}
+
+ public static boolean isPrimitiveOrArray(final @Nullable String typeQName) {
+ return typeQName != null && (typeQName.endsWith("[]") || PRIMITIVES_NAMES.contains(typeQName));
+ }
+
+ /**
+ * CAUTION: isPrimitiveOrArrayOfPrimitives("java.lang.String") == true,
+ * isPrimitiveOrArrayOfPrimitives("java.lang.Object") == true
+ * isPrimitiveOrArrayOfPrimitives("java.lang.Class") == true
+ */
+ public static boolean isPrimitiveOrArrayOfPrimitives(final String typeQName) {
+ if (typeQName == null) {
+ return false;
+ }
+ return PRIMITIVES_NAMES.contains(deleteArraySigns(typeQName));
+ }
+
+ public static boolean isShortNamePrimitiveOrArrayOfPrimitives(final @Nullable String shortName) {
+ if (shortName == null) {
+ return false;
+ }
+ return PRIMITIVES_SHORT_NAMES.contains(deleteArraySigns(shortName));
+ }
+
+ private static String deleteArraySigns(final @NotNull String typeName) {
+ String nameWithoutArraySign = typeName;
+ while (nameWithoutArraySign.endsWith("[]")) {
+ nameWithoutArraySign = nameWithoutArraySign.substring(0, nameWithoutArraySign.length() - 2);
+ }
+ return nameWithoutArraySign;
+ }
+
+ private static final Set<String> PRIMITIVES_NAMES = new HashSet<String>();
+
+ static {
+ fillPrimitivesNames(PsiType.BOOLEAN);
+ fillPrimitivesNames(PsiType.INT);
+ fillPrimitivesNames(PsiType.LONG);
+ fillPrimitivesNames(PsiType.DOUBLE);
+ fillPrimitivesNames(PsiType.FLOAT);
+ fillPrimitivesNames(PsiType.SHORT);
+ fillPrimitivesNames(PsiType.CHAR);
+ fillPrimitivesNames(PsiType.BYTE);
+ fillPrimitivesNames(PsiType.VOID);
+ PRIMITIVES_NAMES.add(CommonClassNames.JAVA_LANG_STRING);
+ PRIMITIVES_NAMES.add(CommonClassNames.JAVA_LANG_OBJECT);
+ PRIMITIVES_NAMES.add(CommonClassNames.JAVA_LANG_CLASS);
+ }
+
+ private static void fillPrimitivesNames(final PsiPrimitiveType type) {
+ PRIMITIVES_NAMES.add(type.getBoxedTypeName());
+ PRIMITIVES_NAMES.add(type.getCanonicalText());
+ }
+
+ private static final Set<String> PRIMITIVES_SHORT_NAMES = new HashSet<String>();
+
+ static {
+ fillPrimitivesShortNames(PsiType.BOOLEAN);
+ fillPrimitivesShortNames(PsiType.INT);
+ fillPrimitivesShortNames(PsiType.LONG);
+ fillPrimitivesShortNames(PsiType.DOUBLE);
+ fillPrimitivesShortNames(PsiType.FLOAT);
+ fillPrimitivesShortNames(PsiType.SHORT);
+ fillPrimitivesShortNames(PsiType.CHAR);
+ fillPrimitivesShortNames(PsiType.BYTE);
+ fillPrimitivesShortNames(PsiType.VOID);
+ PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(CommonClassNames.JAVA_LANG_STRING));
+ PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(CommonClassNames.JAVA_LANG_OBJECT));
+ PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(CommonClassNames.JAVA_LANG_CLASS));
+ }
+
+ private static void fillPrimitivesShortNames(final PsiPrimitiveType type) {
+ PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(type.getBoxedTypeName()));
+ PRIMITIVES_SHORT_NAMES.add(type.getCanonicalText());
+ }
+
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/Constants.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/Constants.java
new file mode 100644
index 000000000000..7a326a70d4c7
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/Constants.java
@@ -0,0 +1,20 @@
+package com.intellij.codeInsight.completion.methodChains;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class Constants {
+
+ private Constants() {
+ }
+
+ /**
+ * magic numbers
+ */
+ public static final int SINGLETON_MAGIC_RATIO = 100;
+
+ public static final int SINGLETON_MAGIC_RATIO2 = 5;
+
+ public static final int CHAIN_SEARCH_MAGIC_RATIO = 12;
+
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/CompletionContributorPatternUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/CompletionContributorPatternUtil.java
new file mode 100644
index 000000000000..f020afa18141
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/CompletionContributorPatternUtil.java
@@ -0,0 +1,33 @@
+package com.intellij.codeInsight.completion.methodChains.completion;
+
+import com.intellij.codeInsight.completion.CompletionInitializationContext;
+import com.intellij.patterns.ElementPattern;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.tree.java.PsiMethodCallExpressionImpl;
+
+import static com.intellij.patterns.PsiJavaPatterns.psiElement;
+import static com.intellij.patterns.StandardPatterns.or;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public final class CompletionContributorPatternUtil {
+
+ private CompletionContributorPatternUtil() {}
+
+ @SuppressWarnings("unchecked")
+ public static ElementPattern<PsiElement> patternForVariableAssignment() {
+ final ElementPattern<PsiElement> patternForParent = or(psiElement().withText(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED)
+ .afterSiblingSkipping(psiElement(PsiWhiteSpace.class),
+ psiElement(PsiJavaToken.class).withText("=")));
+
+ return psiElement().withParent(patternForParent).withSuperParent(2, or(psiElement(PsiAssignmentExpression.class),
+ psiElement(PsiLocalVariable.class)
+ .inside(PsiDeclarationStatement.class)))
+ .inside(PsiMethod.class);
+ }
+
+ public static ElementPattern<PsiElement> patternForMethodParameter() {
+ return psiElement().withSuperParent(3, PsiMethodCallExpressionImpl.class);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsCompletionContributor.java
new file mode 100644
index 000000000000..27c63a0c2a50
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsCompletionContributor.java
@@ -0,0 +1,206 @@
+package com.intellij.codeInsight.completion.methodChains.completion;
+
+import com.intellij.codeInsight.completion.*;
+import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
+import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
+import com.intellij.codeInsight.completion.methodChains.completion.context.ContextUtil;
+import com.intellij.codeInsight.completion.methodChains.search.ChainsSearcher;
+import com.intellij.codeInsight.completion.methodChains.search.MethodChainsSearchService;
+import com.intellij.codeInsight.completion.methodChains.search.MethodsChain;
+import com.intellij.codeInsight.completion.methodChains.search.MethodsChainLookupRangingHelper;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.patterns.ElementPattern;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.ProcessingContext;
+import com.intellij.util.Processor;
+import com.intellij.util.SmartList;
+import com.intellij.util.containers.FactoryMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+import static com.intellij.patterns.PsiJavaPatterns.or;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodsChainsCompletionContributor extends CompletionContributor {
+ public static final int INVOCATIONS_THRESHOLD = 3;
+
+ private final static int MAX_SEARCH_RESULT_SIZE = 20;
+ private final static int MAX_CHAIN_SIZE = 4;
+ private final static int FILTER_RATIO = 10;
+
+ @Override
+ public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
+ if (parameters.getInvocationCount() >= INVOCATIONS_THRESHOLD && CompilerOutputIndexer.getInstance(parameters.getPosition().getProject()).isEnabled()) {
+ super.fillCompletionVariants(parameters, result);
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ result.stopHere();
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public MethodsChainsCompletionContributor() {
+ final ElementPattern<PsiElement> pattern =
+ or(CompletionContributorPatternUtil.patternForMethodParameter(), CompletionContributorPatternUtil.patternForVariableAssignment());
+ extend(CompletionType.BASIC, pattern, new CompletionProvider<CompletionParameters>() {
+ @Override
+ protected void addCompletions(final @NotNull CompletionParameters parameters,
+ final ProcessingContext context,
+ final @NotNull CompletionResultSet result) {
+
+ final ChainCompletionContext completionContext = extractContext(parameters);
+ if (completionContext == null) return;
+
+
+ final String targetClassQName = completionContext.getTargetQName();
+ final Set<String> contextTypesKeysSet = completionContext.getContextTypes();
+ final Set<String> contextRelevantTypes = new HashSet<String>(contextTypesKeysSet.size() + 1);
+ for (final String type : contextTypesKeysSet) {
+ if (!ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(type)) {
+ contextRelevantTypes.add(type);
+ }
+ }
+ contextRelevantTypes.remove(targetClassQName);
+
+ final List<LookupElement> foundedElements = searchForLookups(targetClassQName, contextRelevantTypes, completionContext);
+ result.addAllElements(foundedElements);
+ }
+ });
+ }
+
+ private static List<LookupElement> searchForLookups(final String targetClassQName,
+ final Set<String> contextRelevantTypes,
+ final ChainCompletionContext completionContext) {
+ final MethodChainsSearchService searchService = new MethodChainsSearchService(completionContext.getProject());
+ final List<MethodsChain> searchResult =
+ searchChains(targetClassQName, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE, completionContext, searchService);
+ if (searchResult.size() < MAX_SEARCH_RESULT_SIZE) {
+ final PsiClass aClass = JavaPsiFacade.getInstance(completionContext.getProject())
+ .findClass(targetClassQName, GlobalSearchScope.allScope(completionContext.getProject()));
+ if (aClass != null) {
+ DirectClassInheritorsSearch.search(aClass).forEach(new Processor<PsiClass>() {
+ @Override
+ public boolean process(final PsiClass psiClass) {
+ final String inheritorQName = psiClass.getQualifiedName();
+ if (!StringUtil.isEmpty(inheritorQName)) {
+ final List<MethodsChain> inheritorFilteredSearchResult = new SmartList<MethodsChain>();
+ //noinspection ConstantConditions
+ for (final MethodsChain chain : searchChains(inheritorQName, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE,
+ completionContext, searchService)) {
+ boolean insert = true;
+ for (final MethodsChain baseChain : searchResult) {
+ if (baseChain.weakContains(chain)) {
+ insert = false;
+ break;
+ }
+ }
+ if (insert) {
+ inheritorFilteredSearchResult.add(chain);
+ }
+ }
+ searchResult.addAll(inheritorFilteredSearchResult);
+ }
+ return true;
+ }
+ });
+ }
+ }
+ return MethodsChainLookupRangingHelper.chainsToWeightableLookupElements(filterTailAndGetSumLastMethodOccurrence(searchResult),
+ completionContext);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Nullable
+ private static ChainCompletionContext extractContext(final CompletionParameters parameters) {
+ final PsiElement parent = PsiTreeUtil
+ .getParentOfType(parameters.getPosition(), PsiAssignmentExpression.class, PsiLocalVariable.class, PsiMethodCallExpression.class);
+ if (parent == null) {
+ return null;
+ }
+
+ if (parent instanceof PsiAssignmentExpression) {
+ return tryExtractContextFromAssignment((PsiAssignmentExpression)parent);
+ }
+ if (parent instanceof PsiLocalVariable) {
+ final PsiLocalVariable localVariable = (PsiLocalVariable)parent;
+ return ContextUtil.createContext(localVariable.getType(), localVariable.getName(),
+ PsiTreeUtil.getParentOfType(parent, PsiDeclarationStatement.class));
+ }
+ final PsiMethod method = ((PsiMethodCallExpression)parent).resolveMethod();
+ if (method == null) return null;
+ final PsiExpression expression = PsiTreeUtil.getParentOfType(parameters.getPosition(), PsiExpression.class);
+ final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(parameters.getPosition(), PsiExpressionList.class);
+ if (expressionList == null) return null;
+ final int exprPosition = Arrays.asList(expressionList.getExpressions()).indexOf(expression);
+ final PsiParameter[] methodParameters = method.getParameterList().getParameters();
+ if (exprPosition < methodParameters.length) {
+ final PsiParameter methodParameter = methodParameters[exprPosition];
+ return ContextUtil
+ .createContext(methodParameter.getType(), null, PsiTreeUtil.getParentOfType(expression, PsiDeclarationStatement.class));
+ }
+ return null;
+ }
+
+ @Nullable
+ private static ChainCompletionContext tryExtractContextFromAssignment(final PsiAssignmentExpression assignmentExpression) {
+ final PsiType type = assignmentExpression.getLExpression().getType();
+ final PsiIdentifier identifier = PsiTreeUtil.getChildOfType(assignmentExpression.getLExpression(), PsiIdentifier.class);
+ if (identifier == null) return null;
+ final String identifierText = identifier.getText();
+ return ContextUtil.createContext(type, identifierText, assignmentExpression);
+ }
+
+ private static List<MethodsChain> filterTailAndGetSumLastMethodOccurrence(final List<MethodsChain> chains) {
+ int maxWeight = 0;
+ for (final MethodsChain chain : chains) {
+ final int chainWeight = chain.getChainWeight();
+ if (chainWeight > maxWeight) {
+ maxWeight = chainWeight;
+ }
+ }
+
+ final List<MethodsChain> filteredResult = new ArrayList<MethodsChain>();
+ for (final MethodsChain chain : chains) {
+ final int chainWeight = chain.getChainWeight();
+ if (chainWeight * FILTER_RATIO >= maxWeight) {
+ filteredResult.add(chain);
+ }
+ }
+ return filteredResult;
+ }
+
+ private static List<MethodsChain> searchChains(final String targetQName,
+ final Set<String> contextVarsQNames,
+ final int maxResultSize,
+ final int maxChainSize,
+ final ChainCompletionContext context,
+ final MethodChainsSearchService searchService) {
+ return ChainsSearcher.search(searchService, targetQName, contextVarsQNames, maxResultSize, maxChainSize,
+ createNotDeprecatedMethodsResolver(JavaPsiFacade.getInstance(context.getProject()),
+ context.getResolveScope()),
+ context.getExcludedQNames(), context.getContextMethodName());
+ }
+
+ private static FactoryMap<MethodIncompleteSignature, PsiMethod[]> createNotDeprecatedMethodsResolver(final JavaPsiFacade javaPsiFacade,
+ final GlobalSearchScope scope) {
+ return new FactoryMap<MethodIncompleteSignature, PsiMethod[]>() {
+ @Nullable
+ @Override
+ protected PsiMethod[] create(final MethodIncompleteSignature signature) {
+ return signature.resolveNotDeprecated(javaPsiFacade, scope);
+ }
+ };
+ }
+
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsWeigher.java
new file mode 100644
index 000000000000..57293cae1e12
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsWeigher.java
@@ -0,0 +1,36 @@
+/*
+ * 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.methodChains.completion;
+
+import com.intellij.codeInsight.completion.CompletionLocation;
+import com.intellij.codeInsight.completion.CompletionWeigher;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.WeightableChainLookupElement;
+import com.intellij.codeInsight.completion.methodChains.search.ChainRelevance;
+import com.intellij.codeInsight.lookup.LookupElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodsChainsWeigher extends CompletionWeigher {
+ @Override
+ public Comparable weigh(@NotNull final LookupElement element, @NotNull final CompletionLocation location) {
+ if (element instanceof WeightableChainLookupElement) {
+ return ((WeightableChainLookupElement)element).getChainRelevance();
+ }
+ return ChainRelevance.LOWEST;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContext.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContext.java
new file mode 100644
index 000000000000..bb8d92d0839f
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContext.java
@@ -0,0 +1,156 @@
+package com.intellij.codeInsight.completion.methodChains.completion.context;
+
+import com.intellij.codeInsight.completion.methodChains.search.CachedRelevantStaticMethodSearcher;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.NotNullLazyValue;
+import com.intellij.openapi.util.UserDataHolder;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiVariable;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.containers.MultiMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ChainCompletionContext {
+ private final NotNullLazyValue<String> myContextMethodName = new NotNullLazyValue<String>() {
+ @NotNull
+ @Override
+ protected String compute() {
+ return myContextMethod.getName();
+ }
+ };
+ private final PsiMethod myContextMethod;
+ private final String myTargetQName;
+ private final Set<String> myContainingClassQNames;
+ private final MultiMap<String, PsiVariable> myContextVars;
+ private final MultiMap<String, PsiMethod> myContainingClassGetters;
+ private final MultiMap<String, ContextRelevantVariableGetter> myContextVarsGetters;
+ private final Map<String, PsiVariable> myStringVars;
+ private final CachedRelevantStaticMethodSearcher myStaticMethodSearcher;
+ private final Set<String> myExcludedQNames;
+ private final GlobalSearchScope myResolveScope;
+ private final Project myProject;
+
+ private final NotNullLazyValue<Set<String>> contextTypesQNames = new NotNullLazyValue<Set<String>>() {
+ @SuppressWarnings("unchecked")
+ @NotNull
+ @Override
+ protected Set<String> compute() {
+ return unionToHashSet(myContainingClassQNames, myContextVars.keySet(), myContainingClassGetters.keySet(),
+ myContextVarsGetters.keySet());
+ }
+ };
+
+ public Set<String> getExcludedQNames() {
+ return myExcludedQNames;
+ }
+
+ ChainCompletionContext(final PsiMethod contextMethod,
+ final String targetQName,
+ final Set<String> containingClassQNames,
+ final MultiMap<String, PsiVariable> contextVars,
+ final MultiMap<String, PsiMethod> containingClassGetters,
+ final MultiMap<String, ContextRelevantVariableGetter> contextVarsGetters,
+ final Map<String, PsiVariable> stringVars,
+ final Set<String> excludedQNames,
+ final Project project,
+ final GlobalSearchScope resolveScope) {
+ myContextMethod = contextMethod;
+ myTargetQName = targetQName;
+ myContainingClassQNames = containingClassQNames;
+ myContextVars = contextVars;
+ myContainingClassGetters = containingClassGetters;
+ myContextVarsGetters = contextVarsGetters;
+ myStringVars = stringVars;
+ myExcludedQNames = excludedQNames;
+ myResolveScope = resolveScope;
+ myProject = project;
+ myStaticMethodSearcher = new CachedRelevantStaticMethodSearcher(project, resolveScope);
+ }
+
+ public PsiMethod getContextMethod() {
+ return myContextMethod;
+ }
+
+ public String getContextMethodName() {
+ return myContextMethodName.getValue();
+ }
+
+ public String getTargetQName() {
+ return myTargetQName;
+ }
+
+ @Nullable
+ public PsiVariable findRelevantStringInContext(@Nullable final String stringParamName) {
+ if (stringParamName == null) {
+ return null;
+ }
+ for (final Map.Entry<String, PsiVariable> e : myStringVars.entrySet()) {
+ if (ChainCompletionContextStringUtil.isSimilar(e.getKey(), stringParamName)) {
+ return e.getValue();
+ }
+ }
+ return null;
+ }
+
+ public Set<String> getContainingClassQNames() {
+ return myContainingClassQNames;
+ }
+
+ public Collection<PsiVariable> getVariables(final String typeQName) {
+ return myContextVars.get(typeQName);
+ }
+
+ public Collection<PsiMethod> getContainingClassMethods(final String typeQName) {
+ return myContainingClassGetters.get(typeQName);
+ }
+
+ public Collection<ContextRelevantStaticMethod> getRelevantStaticMethods(final String typeQName, final int weight) {
+ return myStaticMethodSearcher.getRelevantStaticMethods(typeQName, weight, this);
+ }
+
+ public Collection<ContextRelevantVariableGetter> getRelevantVariablesGetters(final String typeQName) {
+ return myContextVarsGetters.get(typeQName);
+ }
+
+ public Collection<?> getContextRefElements(final String typeQName) {
+ final Collection<PsiVariable> variables = getVariables(typeQName);
+ final Collection<PsiMethod> containingClassMethods = getContainingClassMethods(typeQName);
+ final Collection<UserDataHolder> refElements = new ArrayList<UserDataHolder>(variables.size() + containingClassMethods.size());
+ refElements.addAll(variables);
+ refElements.addAll(containingClassMethods);
+ for (final ContextRelevantVariableGetter contextRelevantVariableGetter : getRelevantVariablesGetters(typeQName)) {
+ refElements.add(contextRelevantVariableGetter.createLookupElement());
+ }
+ return refElements;
+ }
+
+ public boolean contains(@Nullable final String typeQualifierName) {
+ return typeQualifierName != null && contextTypesQNames.getValue().contains(typeQualifierName);
+ }
+
+ public Set<String> getContextTypes() {
+ return contextTypesQNames.getValue();
+ }
+
+ public GlobalSearchScope getResolveScope() {
+ return myResolveScope;
+ }
+
+ public Project getProject() {
+ return myProject;
+ }
+
+ private static <T> HashSet<T> unionToHashSet(final Collection<T>... collections) {
+ final HashSet<T> res = new HashSet<T>();
+ for (final Collection<T> set : collections) {
+ res.addAll(set);
+ }
+ return res;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContextStringUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContextStringUtil.java
new file mode 100644
index 000000000000..a9b1903ea803
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContextStringUtil.java
@@ -0,0 +1,36 @@
+package com.intellij.codeInsight.completion.methodChains.completion.context;
+
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich
+ */
+class ChainCompletionContextStringUtil {
+
+ private ChainCompletionContextStringUtil(){}
+
+ private final static int COMMON_PART_MIN_LENGTH = 3;
+
+ public static boolean isSimilar(@NotNull final String varName,
+ @NotNull final String parameterName) {
+ final String sanitizedParamName = sanitizedToLowerCase(parameterName);
+ if (StringUtil.commonPrefix(varName, sanitizedParamName).length() >= COMMON_PART_MIN_LENGTH) {
+ return true;
+ }
+ final String suffix = StringUtil.commonSuffix(varName, sanitizedParamName);
+ return suffix.length() >= COMMON_PART_MIN_LENGTH;
+ }
+
+ @NotNull
+ public static String sanitizedToLowerCase(@NotNull final String name) {
+ final StringBuilder result = new StringBuilder();
+ for (int i = 0; i < name.length(); i++) {
+ final char ch = name.charAt(i);
+ if (Character.isLetter(ch)) {
+ result.append(Character.toLowerCase(ch));
+ }
+ }
+ return result.toString();
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantStaticMethod.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantStaticMethod.java
new file mode 100644
index 000000000000..23b1c26be7f4
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantStaticMethod.java
@@ -0,0 +1,45 @@
+package com.intellij.codeInsight.completion.methodChains.completion.context;
+
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.StaticMethodSubLookupElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.VariableSubLookupElement;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiVariable;
+import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TIntObjectProcedure;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ContextRelevantStaticMethod {
+ private final PsiMethod psiMethod;
+ @Nullable
+ private final TIntObjectHashMap<SubLookupElement> parameters;
+
+ public ContextRelevantStaticMethod(final PsiMethod psiMethod, @Nullable final TIntObjectHashMap<PsiVariable> parameters) {
+ this.psiMethod = psiMethod;
+ if (parameters == null) {
+ this.parameters = null;
+ } else {
+ this.parameters = new TIntObjectHashMap<SubLookupElement>(parameters.size());
+ parameters.forEachEntry(new TIntObjectProcedure<PsiVariable>() {
+ @SuppressWarnings("ConstantConditions")
+ @Override
+ public boolean execute(final int pos, final PsiVariable var) {
+ ContextRelevantStaticMethod.this.parameters.put(pos, new VariableSubLookupElement(var));
+ return false;
+ }
+ });
+ }
+ }
+
+ private SubLookupElement cachedLookupElement;
+
+ public SubLookupElement createLookupElement() {
+ if (cachedLookupElement == null) {
+ cachedLookupElement = new StaticMethodSubLookupElement(psiMethod, parameters);
+ }
+ return cachedLookupElement;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantVariableGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantVariableGetter.java
new file mode 100644
index 000000000000..fec1cfd6b61e
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantVariableGetter.java
@@ -0,0 +1,31 @@
+package com.intellij.codeInsight.completion.methodChains.completion.context;
+
+import com.intellij.codeInsight.completion.JavaChainLookupElement;
+import com.intellij.codeInsight.completion.JavaMethodCallElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.GetterLookupSubLookupElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.VariableLookupItem;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiVariable;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class ContextRelevantVariableGetter {
+ private final PsiVariable myVariable;
+ private final PsiMethod myMethod;
+
+ public ContextRelevantVariableGetter(final PsiVariable variable, final PsiMethod method) {
+ myVariable = variable;
+ myMethod = method;
+ }
+
+ public SubLookupElement createSubLookupElement() {
+ return new GetterLookupSubLookupElement(myVariable.getName(), myMethod.getName());
+ }
+
+ public LookupElement createLookupElement() {
+ return new JavaChainLookupElement(new VariableLookupItem(myVariable), new JavaMethodCallElement(myMethod));
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextUtil.java
new file mode 100644
index 000000000000..481c5f87ac63
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextUtil.java
@@ -0,0 +1,245 @@
+package com.intellij.codeInsight.completion.methodChains.completion.context;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.SmartList;
+import com.intellij.util.containers.MultiMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ContextUtil {
+ @Nullable
+ public static ChainCompletionContext createContext(final @Nullable PsiType variableType,
+ final @Nullable String variableName,
+ final @Nullable PsiElement containingElement) {
+ if (variableType == null || containingElement == null) {
+ return null;
+ }
+ if (variableType instanceof PsiClassType) {
+ final PsiClass aClass = ((PsiClassType)variableType).resolve();
+ if (aClass != null) {
+ if (aClass.hasTypeParameters()) {
+ return null;
+ }
+ }
+ else {
+ return null;
+ }
+ }
+
+ final String targetQName = variableType.getCanonicalText();
+ if (targetQName == null || targetQName.endsWith("[]")) {
+ return null;
+ }
+
+ final PsiMethod method = PsiTreeUtil.getParentOfType(containingElement, PsiMethod.class);
+ if (method == null) {
+ return null;
+ }
+ final PsiClass aClass = method.getContainingClass();
+ if (aClass == null) {
+ return null;
+ }
+ final Set<String> containingClassQNames = resolveSupersNamesRecursively(aClass);
+
+ final List<PsiVariable> contextVars = new SmartList<PsiVariable>();
+ for (final PsiField field : aClass.getFields()) {
+ final PsiClass containingClass = field.getContainingClass();
+ if (containingClass != null) {
+ if ((field.hasModifierProperty(PsiModifier.PUBLIC) ||
+ field.hasModifierProperty(PsiModifier.PROTECTED) ||
+ ((field.hasModifierProperty(PsiModifier.PRIVATE) || field.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) &&
+ aClass.isEquivalentTo(containingClass))) && !field.getName().equals(variableName)) {
+ contextVars.add(field);
+ }
+ }
+ }
+ Collections.addAll(contextVars, method.getParameterList().getParameters());
+
+ final PsiCodeBlock methodBody = method.getBody();
+ assert methodBody != null;
+ boolean processMethodTail = false;
+ final List<PsiElement> afterElements = new ArrayList<PsiElement>();
+ for (final PsiElement element : methodBody.getChildren()) {
+ if (element.isEquivalentTo(containingElement)) {
+ if (variableType instanceof PsiClassType) {
+ processMethodTail = true;
+ continue;
+ }
+ else {
+ break;
+ }
+ }
+ if (element instanceof PsiDeclarationStatement) {
+ if (processMethodTail) {
+ afterElements.add(element);
+ }
+ else {
+ for (final PsiElement declaredElement : ((PsiDeclarationStatement)element).getDeclaredElements()) {
+ if (declaredElement instanceof PsiLocalVariable &&
+ (variableName == null || !variableName.equals(((PsiLocalVariable)declaredElement).getName()))) {
+ contextVars.add((PsiVariable)declaredElement);
+ }
+ }
+ }
+ }
+ }
+
+ final Set<String> excludedQNames = processMethodTail
+ ? generateExcludedQNames(afterElements, ((PsiClassType)variableType).resolve(), variableName,
+ contextVars)
+ : Collections.<String>emptySet();
+
+ final List<PsiMethod> contextMethods = new ArrayList<PsiMethod>();
+ for (final PsiMethod psiMethod : aClass.getMethods()) {
+ if ((psiMethod.hasModifierProperty(PsiModifier.PROTECTED) || psiMethod.hasModifierProperty(PsiModifier.PRIVATE)) &&
+ psiMethod.getParameterList().getParametersCount() == 0) {
+ contextMethods.add(psiMethod);
+ }
+ }
+
+ return create(method, targetQName, contextVars, contextMethods, containingClassQNames, containingElement.getProject(),
+ containingElement.getResolveScope(), excludedQNames);
+ }
+
+ private static Set<String> generateExcludedQNames(final List<PsiElement> tailElements,
+ final @Nullable PsiClass psiClass,
+ final @Nullable String varName,
+ final List<PsiVariable> contextVars) {
+ if (psiClass == null) {
+ return Collections.emptySet();
+ }
+ final String classQName = psiClass.getQualifiedName();
+ if (classQName == null) {
+ return Collections.emptySet();
+ }
+
+ final Set<String> excludedQNames = new HashSet<String>();
+ if (!tailElements.isEmpty()) {
+ final Set<String> contextVarTypes = new HashSet<String>();
+ final Map<String, PsiVariable> contextVarNamesToVar = new HashMap<String, PsiVariable>();
+ for (final PsiVariable var : contextVars) {
+ contextVarTypes.add(var.getType().getCanonicalText());
+ contextVarNamesToVar.put(var.getName(), var);
+ }
+ for (final PsiElement element : tailElements) {
+ final Collection<PsiMethodCallExpression> methodCallExpressions =
+ PsiTreeUtil.findChildrenOfType(element, PsiMethodCallExpression.class);
+ for (final PsiMethodCallExpression methodCallExpression : methodCallExpressions) {
+ final PsiExpressionList args = methodCallExpression.getArgumentList();
+ final PsiMethod resolvedMethod = methodCallExpression.resolveMethod();
+ if (resolvedMethod != null) {
+ final PsiType returnType = resolvedMethod.getReturnType();
+ if (returnType != null) {
+ final String returnTypeAsString = returnType.getCanonicalText();
+ for (final PsiExpression expression : args.getExpressions()) {
+ final String qVarName = expression.getText();
+ if (qVarName != null) {
+ if (contextVarNamesToVar.containsKey(qVarName) || qVarName.equals(varName)) {
+ excludedQNames.add(returnTypeAsString);
+ }
+ }
+ }
+ if (!contextVarTypes.contains(returnTypeAsString)) {
+ excludedQNames.add(returnTypeAsString);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return excludedQNames;
+ }
+
+ @Nullable
+ private static ChainCompletionContext create(final PsiMethod contextMethod,
+ final String targetQName,
+ final List<PsiVariable> contextVars,
+ final List<PsiMethod> contextMethods,
+ final Set<String> containingClassQNames,
+ final Project project,
+ final GlobalSearchScope resolveScope,
+ final Set<String> excludedQNames) {
+ final MultiMap<String, PsiVariable> classQNameToVariable = new MultiMap<String, PsiVariable>();
+ final MultiMap<String, PsiMethod> containingClassGetters = new MultiMap<String, PsiMethod>();
+ final MultiMap<String, ContextRelevantVariableGetter> contextVarsGetters = new MultiMap<String, ContextRelevantVariableGetter>();
+ final Map<String, PsiVariable> stringVars = new HashMap<String, PsiVariable>();
+
+ for (final PsiMethod method : contextMethods) {
+ final String returnTypeQName = method.getReturnType().getCanonicalText();
+ if (returnTypeQName != null) {
+ containingClassGetters.putValue(returnTypeQName, method);
+ }
+ }
+
+ for (final PsiVariable var : contextVars) {
+ final PsiType type = var.getType();
+ final Set<String> classQNames = new HashSet<String>();
+ if (type instanceof PsiClassType) {
+ if (JAVA_LANG_STRING_SHORT_NAME.equals(((PsiClassType)type).getClassName())) {
+ final String varName = var.getName();
+ if (varName != null) {
+ stringVars.put(ChainCompletionContextStringUtil.sanitizedToLowerCase(varName), var);
+ continue;
+ }
+ }
+
+ final PsiClass aClass = ((PsiClassType)type).resolve();
+ if (aClass != null) {
+ final String classQName = type.getCanonicalText();
+ if (!targetQName.equals(classQName)) {
+ classQNames.add(classQName);
+ classQNames.addAll(resolveSupersNamesRecursively(aClass));
+ for (final PsiMethod method : aClass.getAllMethods()) {
+ if (method.getParameterList().getParametersCount() == 0 && method.getName().startsWith("get")) {
+ final String getterReturnTypeQName = method.getReturnType().getCanonicalText();
+ if (getterReturnTypeQName != null) {
+ contextVarsGetters.putValue(getterReturnTypeQName, new ContextRelevantVariableGetter(var, method));
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ final String classQName = type.getCanonicalText();
+ if (classQName != null) {
+ classQNames.add(classQName);
+ }
+ }
+ for (final String qName : classQNames) {
+ classQNameToVariable.putValue(qName, var);
+ }
+ }
+ return new ChainCompletionContext(contextMethod, targetQName, containingClassQNames, classQNameToVariable, containingClassGetters,
+ contextVarsGetters, stringVars, excludedQNames, project, resolveScope);
+ }
+
+ @NotNull
+ private static Set<String> resolveSupersNamesRecursively(@Nullable final PsiClass psiClass) {
+ final Set<String> result = new HashSet<String>();
+ if (psiClass != null) {
+ for (final PsiClass superClass : psiClass.getSupers()) {
+ final String qualifiedName = superClass.getQualifiedName();
+ if (!CommonClassNames.JAVA_LANG_OBJECT.equals(qualifiedName)) {
+ if (qualifiedName != null) {
+ result.add(qualifiedName);
+ }
+ result.addAll(resolveSupersNamesRecursively(superClass));
+ }
+ }
+ }
+ return result;
+ }
+
+ private final static String JAVA_LANG_STRING_SHORT_NAME = StringUtil.getShortName(CommonClassNames.JAVA_LANG_STRING);
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionLookupElementUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionLookupElementUtil.java
new file mode 100644
index 000000000000..65be8928c5d9
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionLookupElementUtil.java
@@ -0,0 +1,53 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup;
+
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.psi.PsiKeyword;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiModifier;
+import com.intellij.psi.PsiParameter;
+import gnu.trove.TIntObjectHashMap;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class ChainCompletionLookupElementUtil {
+ private ChainCompletionLookupElementUtil() {
+ }
+
+ public static LookupElement createLookupElement(final PsiMethod method,
+ final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements) {
+ if (method.isConstructor()) {
+ //noinspection ConstantConditions
+ return LookupElementBuilder.create(String.format("%s %s", PsiKeyword.NEW, method.getContainingClass().getName()));
+ } else if (method.hasModifierProperty(PsiModifier.STATIC)) {
+ return new ChainCompletionMethodCallLookupElement(method, replaceElements, false, true);
+ } else {
+ return new ChainCompletionMethodCallLookupElement(method, replaceElements);
+ }
+ }
+
+ public static String fillMethodParameters(final PsiMethod method, @Nullable final TIntObjectHashMap<SubLookupElement> replaceElements) {
+ final TIntObjectHashMap<SubLookupElement> notNullReplaceElements = replaceElements == null ?
+ new TIntObjectHashMap<SubLookupElement>(0) :
+ replaceElements;
+
+ final PsiParameter[] parameters = method.getParameterList().getParameters();
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < parameters.length; i++) {
+ if (i != 0) {
+ sb.append(", ");
+ }
+ final PsiParameter parameter = parameters[i];
+ final SubLookupElement replaceElement = notNullReplaceElements.get(i);
+ if (replaceElement != null) {
+ sb.append(replaceElement.getInsertString());
+ } else {
+ sb.append(parameter.getName());
+ }
+ }
+ return sb.toString();
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionMethodCallLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionMethodCallLookupElement.java
new file mode 100644
index 000000000000..f7a62d6ccc02
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionMethodCallLookupElement.java
@@ -0,0 +1,88 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup;
+
+import com.intellij.codeInsight.completion.InsertionContext;
+import com.intellij.codeInsight.completion.JavaMethodCallElement;
+import com.intellij.codeInsight.completion.StaticallyImportable;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
+import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiJavaFile;
+import com.intellij.psi.PsiMethod;
+import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TObjectProcedure;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ChainCompletionMethodCallLookupElement extends JavaMethodCallElement implements StaticallyImportable {
+ public static final String PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION = "methods.chain.completion.autoCompletion";
+
+ private final PsiMethod myMethod;
+ @Nullable
+ private final TIntObjectHashMap<SubLookupElement> myReplaceElements;
+ private final boolean myMergedOverloads;
+
+ public ChainCompletionMethodCallLookupElement(final PsiMethod method,
+ final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements,
+ final boolean shouldImportStatic,
+ final boolean mergedOverloads) {
+ super(method, shouldImportStatic, mergedOverloads);
+ myMethod = method;
+ myReplaceElements = replaceElements;
+ myMergedOverloads = mergedOverloads;
+ configureAutoCompletionPolicy();
+ }
+
+ public ChainCompletionMethodCallLookupElement(final PsiMethod method,
+ final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements) {
+ super(method);
+ myMethod = method;
+ myReplaceElements = replaceElements;
+ myMergedOverloads = true;
+ configureAutoCompletionPolicy();
+ }
+
+ private void configureAutoCompletionPolicy() {
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ if (PropertiesComponent.getInstance(myMethod.getProject()).getBoolean(PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION, false)) {
+ setAutoCompletionPolicy(AutoCompletionPolicy.GIVE_CHANCE_TO_OVERWRITE);
+ }
+ }
+ }
+
+ @Override
+ public void handleInsert(final InsertionContext context) {
+ super.handleInsert(context);
+ if (!myMergedOverloads || isUniqueMethod(myMethod)) {
+ context.commitDocument();
+ context.getDocument()
+ .insertString(context.getTailOffset() - 1, ChainCompletionLookupElementUtil.fillMethodParameters(myMethod, myReplaceElements));
+ final PsiFile file = context.getFile();
+ assert file instanceof PsiJavaFile;
+ final PsiJavaFile javaFile = (PsiJavaFile)file;
+ if (myReplaceElements != null) {
+ myReplaceElements.forEachValue(new TObjectProcedure<SubLookupElement>() {
+ @Override
+ public boolean execute(final SubLookupElement subLookupElement) {
+ subLookupElement.doImport(javaFile);
+ return true;
+ }
+ });
+ }
+ context.commitDocument();
+ context.getEditor().getCaretModel().moveToOffset(context.getTailOffset());
+ context.commitDocument();
+ }
+ }
+
+
+ private static boolean isUniqueMethod(@NotNull final PsiMethod method) {
+ final PsiClass containingClass = method.getContainingClass();
+ return containingClass == null || containingClass.findMethodsByName(method.getName(), true).length == 1;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionNewVariableLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionNewVariableLookupElement.java
new file mode 100644
index 000000000000..53dc9bc9eed5
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionNewVariableLookupElement.java
@@ -0,0 +1,79 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup;
+
+import com.intellij.codeInsight.completion.InsertionContext;
+import com.intellij.codeInsight.lookup.LookupElementPresentation;
+import com.intellij.codeInsight.lookup.LookupItem;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
+import com.intellij.psi.codeStyle.SuggestedNameInfo;
+import com.intellij.psi.codeStyle.VariableKind;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class ChainCompletionNewVariableLookupElement extends LookupItem<PsiClass> {
+
+ private final PsiClass psiClass;
+ private final String newVarName;
+
+ public ChainCompletionNewVariableLookupElement(final PsiClass psiClass, final String newVarName) {
+ super(psiClass, newVarName);
+ this.newVarName = newVarName;
+ this.psiClass = psiClass;
+ }
+
+ public static ChainCompletionNewVariableLookupElement create(final PsiClass psiClass) {
+ final Project project = psiClass.getProject();
+ final SuggestedNameInfo suggestedNameInfo = JavaCodeStyleManager.getInstance(project).suggestVariableName(VariableKind.LOCAL_VARIABLE, null, null, JavaPsiFacade .getElementFactory( project).createType(psiClass));
+ return new ChainCompletionNewVariableLookupElement(psiClass, chooseLongest(suggestedNameInfo.names));
+ }
+
+ @Override
+ public void handleInsert(final InsertionContext context) {
+ final PsiFile file = context.getFile();
+ ((PsiJavaFile) file).importClass(psiClass);
+ final PsiStatement statement = PsiTreeUtil.getParentOfType(file.findElementAt(context.getEditor().getCaretModel().getOffset()), PsiStatement.class);
+ final PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(statement, PsiCodeBlock.class);
+ assert codeBlock != null;
+ final Project project = context.getProject();
+ new WriteCommandAction.Simple(project, file) {
+ @Override
+ protected void run() throws Throwable {
+ codeBlock.addBefore(
+ JavaPsiFacade.getElementFactory(
+ project).
+ createStatementFromText(String.format("%s %s = null;", psiClass.getName(), newVarName), null), statement);
+ }
+ }.execute();
+ PsiDocumentManager.getInstance(context.getProject()).doPostponedOperationsAndUnblockDocument(context.getDocument());
+ }
+
+ @NotNull
+ @Override
+ public String getLookupString() {
+ return newVarName;
+ }
+
+ @Override
+ public void renderElement(final LookupElementPresentation presentation) {
+ super.renderElement(presentation);
+ presentation.setItemText(newVarName);
+ }
+
+ private static String chooseLongest(final String[] names) {
+ String longestWord = names[0];
+ int maxLength = longestWord.length();
+ for (int i = 1; i < names.length; i++) {
+ final int length = names[i].length();
+ if (length > maxLength) {
+ maxLength = length;
+ longestWord = names[i];
+ }
+ }
+ return longestWord;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/WeightableChainLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/WeightableChainLookupElement.java
new file mode 100644
index 000000000000..e58d2c84e7df
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/WeightableChainLookupElement.java
@@ -0,0 +1,22 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup;
+
+import com.intellij.codeInsight.completion.methodChains.search.ChainRelevance;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementDecorator;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class WeightableChainLookupElement extends LookupElementDecorator<LookupElement> {
+ private final ChainRelevance myChainRelevance;
+
+ public WeightableChainLookupElement(final @NotNull LookupElement delegate, final ChainRelevance relevance) {
+ super(delegate);
+ myChainRelevance = relevance;
+ }
+
+ public ChainRelevance getChainRelevance() {
+ return myChainRelevance;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/GetterLookupSubLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/GetterLookupSubLookupElement.java
new file mode 100644
index 000000000000..e6b84107c6be
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/GetterLookupSubLookupElement.java
@@ -0,0 +1,35 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
+
+import com.intellij.psi.PsiJavaFile;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class GetterLookupSubLookupElement implements SubLookupElement {
+ private final String myVariableName;
+ private final String myMethodName;
+
+ public GetterLookupSubLookupElement(final String methodName) {
+ this(null, methodName);
+ }
+
+ public GetterLookupSubLookupElement(@Nullable final String variableName, final String methodName) {
+ myVariableName = variableName;
+ myMethodName = methodName;
+ }
+
+ @Override
+ public void doImport(final PsiJavaFile javaFile) {
+ }
+
+ @Override
+ public String getInsertString() {
+ final StringBuilder sb = new StringBuilder();
+ if (myVariableName != null) {
+ sb.append(myVariableName).append(".");
+ }
+ sb.append(myMethodName).append("()");
+ return sb.toString();
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/StaticMethodSubLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/StaticMethodSubLookupElement.java
new file mode 100644
index 000000000000..88d8b01529c0
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/StaticMethodSubLookupElement.java
@@ -0,0 +1,51 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
+
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.ChainCompletionLookupElementUtil;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiJavaFile;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiModifier;
+import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TObjectProcedure;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class StaticMethodSubLookupElement implements SubLookupElement {
+
+ private final PsiMethod myMethod;
+ private final TIntObjectHashMap<SubLookupElement> myReplaceElements;
+
+ public StaticMethodSubLookupElement(final PsiMethod method, @Nullable final TIntObjectHashMap<SubLookupElement> replaceElements) {
+ assert method.hasModifierProperty(PsiModifier.STATIC);
+ myReplaceElements = replaceElements;
+ myMethod = method;
+ }
+
+ @Override
+ public void doImport(final PsiJavaFile javaFile) {
+ final PsiClass containingClass = myMethod.getContainingClass();
+ if (containingClass != null) {
+ if (javaFile.findImportReferenceTo(containingClass) == null) {
+ javaFile.importClass(containingClass);
+ }
+ }
+ if (myReplaceElements != null) {
+ myReplaceElements.forEachValue(new TObjectProcedure<SubLookupElement>() {
+ @Override
+ public boolean execute(final SubLookupElement subLookupElement) {
+ subLookupElement.doImport(javaFile);
+ return false;
+ }
+ });
+ }
+ }
+
+ @Override
+ public String getInsertString() {
+ //noinspection ConstantConditions
+ return String.format("%s.%s(%s)", myMethod.getContainingClass().getName(), myMethod.getName(),
+ ChainCompletionLookupElementUtil.fillMethodParameters(myMethod, myReplaceElements));
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/SubLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/SubLookupElement.java
new file mode 100644
index 000000000000..7046012d4017
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/SubLookupElement.java
@@ -0,0 +1,13 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
+
+import com.intellij.psi.PsiJavaFile;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public interface SubLookupElement {
+
+ void doImport(final PsiJavaFile javaFile);
+
+ String getInsertString();
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/VariableSubLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/VariableSubLookupElement.java
new file mode 100644
index 000000000000..894f10b8d15d
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/VariableSubLookupElement.java
@@ -0,0 +1,25 @@
+package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
+
+import com.intellij.psi.PsiJavaFile;
+import com.intellij.psi.PsiVariable;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class VariableSubLookupElement implements SubLookupElement {
+
+ private final String myVarName;
+
+ public VariableSubLookupElement(final PsiVariable variable) {
+ myVarName = variable.getName();
+ }
+
+ @Override
+ public void doImport(final PsiJavaFile javaFile) {
+ }
+
+ @Override
+ public String getInsertString() {
+ return myVarName;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedNotDeprecatedMethodsResolver.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedNotDeprecatedMethodsResolver.java
new file mode 100644
index 000000000000..018065a7ed56
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedNotDeprecatedMethodsResolver.java
@@ -0,0 +1,36 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class CachedNotDeprecatedMethodsResolver {
+ private final Map<MethodIncompleteSignature, PsiMethod[]> myResolveLocalCache = new HashMap<MethodIncompleteSignature, PsiMethod[]>();
+ private final JavaPsiFacade myJavaPsiFacade;
+ private final GlobalSearchScope myScope;
+
+ public CachedNotDeprecatedMethodsResolver(final Project project, final GlobalSearchScope scope) {
+ myScope = scope;
+ myJavaPsiFacade = JavaPsiFacade.getInstance(project);
+ }
+
+ @NotNull
+ public PsiMethod[] resolveNotDeprecated(@NotNull final MethodIncompleteSignature methodInvocation) {
+ final PsiMethod[] cached = myResolveLocalCache.get(methodInvocation);
+ if (cached != null) {
+ return cached;
+ }
+ final PsiMethod[] methods = methodInvocation.resolveNotDeprecated(myJavaPsiFacade, myScope);
+ myResolveLocalCache.put(methodInvocation, methods);
+ return methods;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedRelevantStaticMethodSearcher.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedRelevantStaticMethodSearcher.java
new file mode 100644
index 000000000000..ef11e727c959
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedRelevantStaticMethodSearcher.java
@@ -0,0 +1,122 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
+import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
+import com.intellij.codeInsight.completion.methodChains.completion.context.ContextRelevantStaticMethod;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.compilerOutputIndex.impl.MethodsUsageIndex;
+import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.SmartList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class CachedRelevantStaticMethodSearcher {
+ private final HashMap<MethodIncompleteSignature, PsiMethod> myCachedResolveResults = new HashMap<MethodIncompleteSignature, PsiMethod>();
+ private final MethodsUsageIndex myIndex;
+ private final JavaPsiFacade myJavaPsiFacade;
+ private final GlobalSearchScope myAllScope;
+ private final GlobalSearchScope myResolveScope;
+
+ public CachedRelevantStaticMethodSearcher(final Project project, final GlobalSearchScope resolveScope) {
+ myIndex = MethodsUsageIndex.getInstance(project);
+ myJavaPsiFacade = JavaPsiFacade.getInstance(project);
+ myAllScope = GlobalSearchScope.allScope(project);
+ myResolveScope = resolveScope;
+ }
+
+ @NotNull
+ public List<ContextRelevantStaticMethod> getRelevantStaticMethods(final String resultQualifiedClassName,
+ final int minOccurrence,
+ final ChainCompletionContext completionContext) {
+ if (resultQualifiedClassName == null ||
+ ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(resultQualifiedClassName) ||
+ completionContext.getTargetQName().equals(resultQualifiedClassName)) {
+ return Collections.emptyList();
+ }
+ final TreeSet<UsageIndexValue> indexValues = myIndex.getValues(resultQualifiedClassName);
+ if (indexValues != null) {
+ int occurrences = 0;
+ final List<ContextRelevantStaticMethod> relevantMethods = new ArrayList<ContextRelevantStaticMethod>();
+ for (final UsageIndexValue indexValue : extractStaticMethods(indexValues)) {
+ final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
+ final PsiMethod method;
+ if (myCachedResolveResults.containsKey(methodInvocation)) {
+ method = myCachedResolveResults.get(methodInvocation);
+ }
+ else {
+ final PsiMethod[] methods = methodInvocation.resolveNotDeprecated(myJavaPsiFacade, myAllScope);
+ method = MethodChainsSearchUtil
+ .getMethodWithMinNotPrimitiveParameters(methods, Collections.singleton(completionContext.getTargetQName()));
+ myCachedResolveResults.put(methodInvocation, method);
+ if (method == null) {
+ return Collections.emptyList();
+ }
+ }
+ if (method == null) {
+ return Collections.emptyList();
+ }
+ if (method.hasModifierProperty(PsiModifier.PUBLIC)) {
+ if (isMethodValid(method, completionContext, resultQualifiedClassName)) {
+ occurrences += indexValue.getOccurrences();
+ if (myResolveScope.contains(method.getContainingFile().getVirtualFile())) {
+ relevantMethods.add(new ContextRelevantStaticMethod(method, null));
+ }
+ if (occurrences >= minOccurrence) {
+ return relevantMethods;
+ }
+ }
+ }
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ private static List<UsageIndexValue> extractStaticMethods(final TreeSet<UsageIndexValue> indexValues) {
+ final List<UsageIndexValue> relevantStaticMethods = new SmartList<UsageIndexValue>();
+ for (final UsageIndexValue indexValue : indexValues) {
+ if (indexValue.getMethodIncompleteSignature().isStatic()) {
+ relevantStaticMethods.add(indexValue);
+ }
+ }
+ return relevantStaticMethods;
+ }
+
+ private static boolean isMethodValid(final @Nullable PsiMethod method,
+ final ChainCompletionContext completionContext,
+ final String targetTypeShortName) {
+ if (method == null) return false;
+ for (final PsiParameter parameter : method.getParameterList().getParameters()) {
+ final PsiType type = parameter.getType();
+ final String shortClassName = typeAsString(type);
+ if (targetTypeShortName.equals(shortClassName)) return false;
+ if (!ChainCompletionStringUtil.isShortNamePrimitiveOrArrayOfPrimitives(shortClassName) &&
+ !completionContext.contains(type.getCanonicalText())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ @Nullable
+ public static String typeAsString(final PsiType type) {
+ if (type instanceof PsiClassType)
+ return ((PsiClassType) type).getClassName();
+ else if (type instanceof PsiPrimitiveType)
+ return type.getCanonicalText();
+ else if (type instanceof PsiArrayType) {
+ final String componentTypeAsString = typeAsString(((PsiArrayType) type).getComponentType());
+ if (componentTypeAsString == null) return null;
+ return String.format("%s[]", componentTypeAsString);
+ }
+ return null;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainRelevance.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainRelevance.java
new file mode 100644
index 000000000000..09e008a7aa4b
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainRelevance.java
@@ -0,0 +1,91 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.TestOnly;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class ChainRelevance implements Comparable<ChainRelevance> {
+ public static final ChainRelevance LOWEST = new ChainRelevance(Integer.MAX_VALUE, 0, Integer.MAX_VALUE, Integer.MAX_VALUE, false, false);
+
+ private final int myChainSize;
+ private final int myLastMethodOccurrences;
+ private final int myUnreachableParametersCount;
+ private final int myNotMatchedStringVars;
+ private final boolean myHasCallingVariableInContext;
+ private final boolean myFirstMethodStatic;
+
+ public ChainRelevance(final int chainSize,
+ final int lastMethodOccurrences,
+ final int unreachableParametersCount,
+ final int notMatchedStringVars,
+ final boolean hasCallingVariableInContext,
+ final boolean firstMethodStatic) {
+ myChainSize = chainSize;
+ myLastMethodOccurrences = lastMethodOccurrences;
+ myUnreachableParametersCount = unreachableParametersCount;
+ myNotMatchedStringVars = notMatchedStringVars;
+ myHasCallingVariableInContext = hasCallingVariableInContext;
+ myFirstMethodStatic = firstMethodStatic;
+ }
+
+ @TestOnly
+ public boolean hasCallingVariableInContext() {
+ return myHasCallingVariableInContext;
+ }
+
+ @TestOnly
+ public int getChainSize() {
+ return myChainSize;
+ }
+
+ @TestOnly
+ public int getLastMethodOccurrences() {
+ return myLastMethodOccurrences;
+ }
+
+ @TestOnly
+ public int getUnreachableParametersCount() {
+ return myUnreachableParametersCount;
+ }
+
+ @TestOnly
+ public int getNotMatchedStringVars() {
+ return myNotMatchedStringVars;
+ }
+
+ @TestOnly
+ public boolean isFirstMethodStatic() {
+ return myFirstMethodStatic;
+ }
+
+ @Override
+ public int compareTo(@NotNull final ChainRelevance that) {
+ if (myFirstMethodStatic && !that.myFirstMethodStatic) {
+ return -1;
+ }
+ if (that.myFirstMethodStatic && !myFirstMethodStatic) {
+ return 1;
+ }
+ if (myHasCallingVariableInContext && !that.myHasCallingVariableInContext) {
+ return 1;
+ }
+ if (that.myHasCallingVariableInContext && !myHasCallingVariableInContext) {
+ return -1;
+ }
+ int sub = myLastMethodOccurrences - that.myLastMethodOccurrences;
+ if (sub != 0) return sub;
+ sub = myUnreachableParametersCount - that.myUnreachableParametersCount;
+ if (sub != 0) return -sub;
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return (myFirstMethodStatic ? "1" : "0") +
+ (myHasCallingVariableInContext ? "1" : "0") + "_" +
+ myLastMethodOccurrences + "_" +
+ myUnreachableParametersCount;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainsSearcher.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainsSearcher.java
new file mode 100644
index 000000000000..b47095a096f4
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainsSearcher.java
@@ -0,0 +1,206 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.codeInsight.completion.methodChains.Constants;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.psi.PsiMethod;
+import com.intellij.util.containers.FactoryMap;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ChainsSearcher {
+
+ public static List<MethodsChain> search(final MethodChainsSearchService searchService,
+ final String targetQName,
+ final Set<String> contextQNames,
+ final int maxResultSize,
+ final int pathMaximalLength,
+ final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
+ final String contextMethodName) {
+ return search(searchService, targetQName, contextQNames, maxResultSize, pathMaximalLength, resolver,
+ Collections.<String>singleton(targetQName), contextMethodName);
+ }
+
+ public static List<MethodsChain> search(final MethodChainsSearchService searchService,
+ final String targetQName,
+ final Set<String> contextQNames,
+ final int maxResultSize,
+ final int pathMaximalLength,
+ final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
+ final Set<String> excludedParamsTypesQNames,
+ final String contextMethodName) {
+ final SearchInitializer initializer = createInitializer(targetQName, resolver, searchService, excludedParamsTypesQNames);
+ final ArrayList<MethodsChain> methodsChains = new ArrayList<MethodsChain>(maxResultSize);
+ final MethodsChain firstBestMethodsChain =
+ search(searchService, initializer, contextQNames, Collections.<String>emptySet(), pathMaximalLength, resolver, targetQName,
+ excludedParamsTypesQNames, contextMethodName);
+ if (firstBestMethodsChain != null) {
+ methodsChains.add(firstBestMethodsChain);
+ Set<Set<String>> excludedCombinations = MethodsChain.edgeCombinations(Collections.<Set<String>>emptySet(), firstBestMethodsChain);
+ while (methodsChains.size() <= maxResultSize) {
+ final Set<Set<String>> localExcludedCombinations = excludedCombinations;
+ boolean allLocalsIsNull = true;
+ final int beforeStepChainsCount = methodsChains.size();
+ for (final Set<String> excludedEdges : localExcludedCombinations) {
+ final MethodsChain local =
+ search(searchService, initializer, contextQNames, excludedEdges, pathMaximalLength, resolver, targetQName,
+ excludedParamsTypesQNames, contextMethodName);
+ if (local != null) {
+ allLocalsIsNull = false;
+ }
+ else {
+ continue;
+ }
+ boolean add = true;
+ for (int i = 0; i < methodsChains.size(); i++) {
+ final MethodsChain chain = methodsChains.get(i);
+ final MethodsChain.CompareResult compareResult = MethodsChain.compare(local, chain);
+ if (compareResult == MethodsChain.CompareResult.EQUAL || compareResult == MethodsChain.CompareResult.RIGHT_CONTAINS_LEFT) {
+ add = false;
+ break;
+ }
+ else if (compareResult == MethodsChain.CompareResult.LEFT_CONTAINS_RIGHT) {
+ methodsChains.set(i, local);
+ add = false;
+ break;
+ }
+ }
+ if (add) {
+ methodsChains.add(local);
+ if (methodsChains.size() >= maxResultSize) {
+ return methodsChains;
+ }
+ excludedCombinations = MethodsChain.edgeCombinations(excludedCombinations, local);
+ }
+ }
+ if (allLocalsIsNull || beforeStepChainsCount == methodsChains.size()) {
+ return methodsChains;
+ }
+ }
+ }
+ return methodsChains;
+ }
+
+ private static SearchInitializer createInitializer(final String targetQName,
+ final FactoryMap<MethodIncompleteSignature, PsiMethod[]> context,
+ final MethodChainsSearchService searchService,
+ final Set<String> excludedParamsTypesQNames) {
+ return new SearchInitializer(searchService.getMethods(targetQName), context, targetQName, excludedParamsTypesQNames);
+ }
+
+ @Nullable
+ private static MethodsChain search(final MethodChainsSearchService searchService,
+ final SearchInitializer initializer,
+ final Set<String> toSet,
+ final Set<String> excludedEdgeNames,
+ final int pathMaximalLength,
+ final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
+ final String targetQName,
+ final Set<String> excludedParamsTypesQNames,
+ final String contextMethodName) {
+ final Set<String> allExcludedNames = MethodChainsSearchUtil.unionToHashSet(excludedParamsTypesQNames, targetQName);
+ ProgressManager.checkCanceled();
+ final SearchInitializer.InitResult initResult = initializer.init(excludedEdgeNames, toSet, searchService, contextMethodName);
+ final Map<MethodIncompleteSignature, MethodsChain> knownDistance = initResult.getChains();
+ final PriorityQueue<WeightAware<MethodIncompleteSignature>> q =
+ new PriorityQueue<WeightAware<MethodIncompleteSignature>>(initResult.getVertexes());
+ MethodsChain result = initResult.getCurrentBestTargetChain();
+
+ int maxWeight = 0;
+ for (final MethodsChain methodsChain : knownDistance.values()) {
+ if (methodsChain.getChainWeight() > maxWeight) {
+ maxWeight = methodsChain.getChainWeight();
+ }
+ }
+
+ final WeightAware<MethodIncompleteSignature> maxVertex = q.peek();
+ final int maxDistance;
+ if (maxVertex != null) {
+ maxDistance = maxVertex.getWeight();
+ }
+ else {
+ return null;
+ }
+
+ while (!q.isEmpty()) {
+ final WeightAware<MethodIncompleteSignature> currentVertex = q.poll();
+ final int currentVertexDistance = currentVertex.getWeight();
+ if (currentVertexDistance * Constants.CHAIN_SEARCH_MAGIC_RATIO < maxDistance) {
+ return result;
+ }
+ final MethodIncompleteSignature currentVertexUnderlying = currentVertex.getUnderlying();
+ final MethodsChain currentVertexMethodsChain = knownDistance.get(currentVertexUnderlying);
+ if (currentVertexDistance != currentVertexMethodsChain.getChainWeight()) {
+ continue;
+ }
+ final SortedSet<UsageIndexValue> bigrams = searchService.getBigram(currentVertexUnderlying);
+ int bigramsSumWeight = 0;
+ int maxUpdatedWeight = 0;
+ for (final UsageIndexValue indexValue : bigrams) {
+ final MethodIncompleteSignature vertex = indexValue.getMethodIncompleteSignature();
+ final int occurrences = indexValue.getOccurrences();
+ bigramsSumWeight += occurrences;
+ final boolean canBeResult = vertex.isStatic() || toSet.contains(vertex.getOwner());
+ if (!vertex.getOwner().equals(targetQName) || canBeResult) {
+ final int vertexDistance = Math.min(currentVertexDistance, occurrences);
+ final MethodsChain knownVertexMethodsChain = knownDistance.get(vertex);
+ if ((knownVertexMethodsChain == null || knownVertexMethodsChain.getChainWeight() < vertexDistance) &&
+ (result == null || result.getChainWeight() < vertexDistance)) {
+ if (occurrences * Constants.CHAIN_SEARCH_MAGIC_RATIO >= currentVertexMethodsChain.getChainWeight()) {
+ final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
+ final PsiMethod[] psiMethods = resolver.get(methodInvocation);
+
+ if (psiMethods.length != 0 && MethodChainsSearchUtil.checkParametersForTypesQNames(psiMethods, allExcludedNames)) {
+ final MethodsChain newBestMethodsChain = currentVertexMethodsChain.addEdge(psiMethods);
+ if (canBeResult) {
+ result = newBestMethodsChain;
+ }
+ else if (newBestMethodsChain.size() < pathMaximalLength - 1) {
+ maxUpdatedWeight = Math.max(maxUpdatedWeight, newBestMethodsChain.getChainWeight());
+ q.add(new WeightAware<MethodIncompleteSignature>(indexValue.getMethodIncompleteSignature(),
+ newBestMethodsChain.getChainWeight()));
+ }
+ knownDistance.put(vertex, newBestMethodsChain);
+ }
+ }
+ else if (!allExcludedNames.contains(currentVertexMethodsChain.getFirstQualifierClass().getQualifiedName()) &&
+ searchService.isSingleton(currentVertexMethodsChain.getFirstQualifierClass(), contextMethodName) &&
+ (searchService.isRelevantMethodForNotOverriden(currentVertexMethodsChain.getFirstQualifierClass().getQualifiedName(),
+ currentVertexMethodsChain.getOneOfFirst().getName()) ||
+ searchService.isRelevantMethodForField(currentVertexMethodsChain.getFirstQualifierClass().getQualifiedName(),
+ currentVertexMethodsChain.getOneOfFirst().getName()))) {
+ result = currentVertexMethodsChain;
+ }
+ }
+ }
+ }
+ //if ((result == null || maxUpdatedWeight * Constants.CHAIN_SEARCH_MAGIC_RATIO2 <= bigramsSumWeight)
+ // && bigramsSumWeight * Constants.CHAIN_SEARCH_MAGIC_RATIO >= currentVertexMethodsChain.getChainWeight()) {
+ // return currentVertexMethodsChain;
+ //}
+
+ if ((currentVertexMethodsChain.isStaticChain() ||
+ !allExcludedNames.contains(currentVertexMethodsChain.getFirstQualifierClass().getQualifiedName())) &&
+ bigramsSumWeight * Constants.CHAIN_SEARCH_MAGIC_RATIO <= currentVertexDistance &&
+ (result == null || result.getChainWeight() < currentVertexDistance) &&
+ (currentVertexMethodsChain.isStaticChain() ||
+ searchService.isSingleton(currentVertexMethodsChain.getFirstQualifierClass(), contextMethodName) &&
+ (searchService.isRelevantMethodForNotOverriden(currentVertexMethodsChain.getFirstQualifierClass().getQualifiedName(),
+ currentVertexMethodsChain.getOneOfFirst().getName()) ||
+ searchService.isRelevantMethodForField(currentVertexMethodsChain.getFirstQualifierClass().getQualifiedName(),
+ currentVertexMethodsChain.getOneOfFirst().getName())))) {
+ result = currentVertexMethodsChain;
+ }
+ }
+
+ if (result != null && result.getChainWeight() * Constants.CHAIN_SEARCH_MAGIC_RATIO >= maxWeight) {
+ return result;
+ }
+ return null;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchService.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchService.java
new file mode 100644
index 000000000000..0bc1991c715a
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchService.java
@@ -0,0 +1,93 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.compilerOutputIndex.impl.MethodsUsageIndex;
+import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
+import com.intellij.compilerOutputIndex.impl.bigram.BigramMethodsUsageIndex;
+import com.intellij.compilerOutputIndex.impl.callingLocation.MethodNameAndQualifier;
+import com.intellij.codeInsight.completion.methodChains.search.service.OverridenMethodsService;
+import com.intellij.codeInsight.completion.methodChains.search.service.SingletonService;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiClass;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class MethodChainsSearchService {
+ private final static SortedSet EMPTY_SORTED_SET = new TreeSet();
+
+ private final MethodsUsageIndex myMethodsUsageIndex;
+ private final BigramMethodsUsageIndex myBigramMethodsUsageIndex;
+ private final SingletonService mySingletonService;
+ private final OverridenMethodsService myOverridenMethodsService;
+ private final Project myProject;
+ private final Map<String, Boolean> mySingletonLocalCache;
+
+ public MethodChainsSearchService(final Project project) {
+ myOverridenMethodsService = new OverridenMethodsService(project);
+ myMethodsUsageIndex = MethodsUsageIndex.getInstance(project);
+ myBigramMethodsUsageIndex = BigramMethodsUsageIndex.getInstance(project);
+ mySingletonService = new SingletonService(project);
+ myProject = project;
+
+ mySingletonLocalCache = new HashMap<String, Boolean>();
+ mySingletonLocalCache.put(null, false);
+ }
+
+ public Project getProject() {
+ return myProject;
+ }
+
+ @NotNull
+ @SuppressWarnings("unchecked")
+ public SortedSet<UsageIndexValue> getBigram(final MethodIncompleteSignature methodIncompleteSignature) {
+ final TreeSet<UsageIndexValue> value = myBigramMethodsUsageIndex.getValues(methodIncompleteSignature);
+ if (value != null) {
+ return value;
+ }
+ return EMPTY_SORTED_SET;
+ }
+
+ @NotNull
+ @SuppressWarnings("unchecked")
+ public SortedSet<UsageIndexValue> getMethods(final String targetQName) {
+ final TreeSet<UsageIndexValue> value = myMethodsUsageIndex.getValues(targetQName);
+ if (value != null) {
+ return value;
+ }
+ return EMPTY_SORTED_SET;
+ }
+
+ public boolean isSingleton(@NotNull final PsiClass psiClass, final String contextMethodName) {
+ return isSingleton(psiClass.getQualifiedName(), contextMethodName);
+ }
+
+ public boolean isSingleton(@Nullable final String typeQName, final String methodName) {
+ Boolean isSingleton = mySingletonLocalCache.get(typeQName);
+ if (isSingleton == null) {
+ isSingleton = mySingletonService.isSingleton(typeQName, methodName);
+ mySingletonLocalCache.put(typeQName, isSingleton);
+ }
+ return isSingleton;
+ }
+
+ public boolean isRelevantMethodForField(@NotNull final String className, @NotNull final String methodName) {
+ final Pair<Integer, Integer> occurrences =
+ myOverridenMethodsService.getMethodUsageInFieldContext(new MethodNameAndQualifier(methodName, className));
+ return occurrences.getFirst() > occurrences.getSecond();
+ }
+
+ public boolean isRelevantMethodForNotOverriden(@NotNull final String className, @NotNull final String methodName) {
+ final Pair<Integer, Integer> occurrences =
+ myOverridenMethodsService.getMethodsUsageInOverridenContext(new MethodNameAndQualifier(methodName, className));
+ return occurrences.getFirst() < occurrences.getSecond();
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchUtil.java
new file mode 100644
index 000000000000..ae0df9554dc4
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchUtil.java
@@ -0,0 +1,80 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiParameter;
+import com.intellij.psi.PsiParameterList;
+import com.intellij.psi.PsiPrimitiveType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class MethodChainsSearchUtil {
+ private MethodChainsSearchUtil() {
+ }
+
+ @Nullable
+ public static PsiMethod getMethodWithMinNotPrimitiveParameters(final @NotNull PsiMethod[] methods,
+ final Set<String> excludedParamsQNames) {
+ PsiMethod minMethod = null;
+ int minParametersCount = Integer.MAX_VALUE;
+ for (final PsiMethod method : methods) {
+ final PsiParameterList parameterList = method.getParameterList();
+ boolean doContinue = false;
+ int parametersCount = parameterList.getParametersCount();
+ for (final PsiParameter p : parameterList.getParameters()) {
+ if (!(p.getType() instanceof PsiPrimitiveType)) {
+ if (excludedParamsQNames.contains(p.getType().getCanonicalText())) {
+ doContinue = true;
+ break;
+ }
+ parametersCount++;
+ }
+ }
+ if (doContinue) {
+ continue;
+ }
+ if (parametersCount < minParametersCount) {
+ if (parametersCount == 0) {
+ return method;
+ }
+ minParametersCount = parametersCount;
+ minMethod = method;
+ }
+ }
+ return minMethod;
+ }
+
+ public static boolean checkParametersForTypesQNames(final PsiMethod[] psiMethods, final Set<String> excludedTypesQNames) {
+ if (psiMethods.length == 0) {
+ return true;
+ }
+ for (final PsiMethod method : psiMethods) {
+ boolean hasTargetInParams = false;
+ for (final PsiParameter param : method.getParameterList().getParameters()) {
+ final String paramType = param.getType().getCanonicalText();
+ if (excludedTypesQNames.contains(paramType)) {
+ hasTargetInParams = true;
+ break;
+ }
+ }
+ if (!hasTargetInParams) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static <T> HashSet<T> unionToHashSet(final Collection<T> collection, final T... items) {
+ final HashSet<T> result = new HashSet<T>();
+ result.addAll(collection);
+ Collections.addAll(result, items);
+ return result;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChain.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChain.java
new file mode 100644
index 000000000000..c7f11c3af979
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChain.java
@@ -0,0 +1,160 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+import static com.intellij.util.containers.ContainerUtil.reverse;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodsChain {
+ private final List<PsiMethod[]> myRevertedPath;
+ private final int myWeight;
+
+ public MethodsChain(final PsiMethod[] methods, final int weight) {
+ this(ContainerUtil.<PsiMethod[]>newArrayList(methods), weight);
+ }
+
+ public MethodsChain(final List<PsiMethod[]> revertedPath, final int weight) {
+ myRevertedPath = revertedPath;
+ myWeight = weight;
+ }
+
+ public int size() {
+ return myRevertedPath.size();
+ }
+
+ public boolean isStaticChain() {
+ return myRevertedPath.get(myRevertedPath.size() - 1)[0].hasModifierProperty(PsiModifier.STATIC);
+ }
+
+ @Nullable
+ public PsiClass getFirstQualifierClass() {
+ return myRevertedPath.isEmpty() ? null : myRevertedPath.get(myRevertedPath.size() - 1)[0].getContainingClass();
+ }
+
+ @Nullable
+ public PsiMethod getOneOfFirst() {
+ return (myRevertedPath.isEmpty() || myRevertedPath.get(0).length == 0) ? null : myRevertedPath.get(myRevertedPath.size() - 1)[0];
+ }
+
+ public List<PsiMethod[]> getPath() {
+ return reverse(myRevertedPath);
+ }
+
+ public int getChainWeight() {
+ return myWeight;
+ }
+
+ public MethodsChain addEdge(final PsiMethod[] psiMethods) {
+ final List<PsiMethod[]> newRevertedPath = new ArrayList<PsiMethod[]>(myRevertedPath.size() + 1);
+ newRevertedPath.addAll(myRevertedPath);
+ newRevertedPath.add(psiMethods);
+ return new MethodsChain(newRevertedPath, myWeight);
+ }
+
+ /**
+ * checking only method names
+ */
+ public boolean weakContains(final MethodsChain otherChain) {
+ if (otherChain.myRevertedPath.isEmpty()) {
+ return true;
+ }
+ if (myRevertedPath.isEmpty()) {
+ return false;
+ }
+ final Iterator<PsiMethod[]> otherChainIterator = otherChain.myRevertedPath.iterator();
+ String otherChainCurrentName = otherChainIterator.next()[0].getName();
+ boolean checkingStarted = false;
+ for (final PsiMethod[] methods : myRevertedPath) {
+ final String thisCurrentName = methods[0].getName();
+ if (!checkingStarted && thisCurrentName.equals(otherChainCurrentName)) {
+ checkingStarted = true;
+ }
+ if (checkingStarted) {
+ if (otherChainIterator.hasNext()) {
+ otherChainCurrentName = otherChainIterator.next()[0].getName();
+ if (!otherChainCurrentName.equals(thisCurrentName)) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ }
+ return !otherChainIterator.hasNext();
+ }
+
+ @Override
+ public String toString() {
+ return StringUtil.join(myRevertedPath, "<-");
+ }
+
+ public static Set<Set<String>> edgeCombinations(final Set<Set<String>> oldCombinations,
+ final MethodsChain methodsChain) {
+ if (oldCombinations.isEmpty()) {
+ final Set<Set<String>> result = new HashSet<Set<String>>(methodsChain.myRevertedPath.size());
+ for (final PsiMethod[] e : methodsChain.myRevertedPath) {
+ final Set<String> set = new HashSet<String>();
+ set.add(e[0].getName());
+ result.add(set);
+ }
+ return result;
+ } else {
+ final Set<Set<String>> newTail = new HashSet<Set<String>>(oldCombinations.size() * methodsChain.size());
+ for (final PsiMethod[] e : methodsChain.myRevertedPath) {
+ final String methodName = e[0].getName();
+ for (final Set<String> tailSet : oldCombinations) {
+ final Set<String> newSet = new HashSet<String>(tailSet);
+ newSet.add(methodName);
+ if (!oldCombinations.contains(newSet)) {
+ newTail.add(newSet);
+ }
+ }
+ }
+ return newTail;
+ }
+ }
+
+ @SuppressWarnings("ConstantConditions")
+ public static CompareResult compare(final MethodsChain left, final MethodsChain right) {
+ if (left.size() == 0) {
+ return CompareResult.RIGHT_CONTAINS_LEFT;
+ }
+ if (right.size() == 0) {
+ return CompareResult.LEFT_CONTAINS_RIGHT;
+ }
+ final Iterator<PsiMethod[]> leftIterator = left.myRevertedPath.iterator();
+ final Iterator<PsiMethod[]> rightIterator = right.myRevertedPath.iterator();
+
+ final PsiManager psiManager = PsiManager.getInstance(left.getFirstQualifierClass().getProject());
+ while (leftIterator.hasNext() && rightIterator.hasNext()) {
+ final PsiMethod thisNext = leftIterator.next()[0];
+ final PsiMethod thatNext = rightIterator.next()[0];
+ if (((thisNext.isConstructor() != thatNext.isConstructor()))
+ || !thisNext.getName().equals(thatNext.getName())
+ || !psiManager.areElementsEquivalent(thisNext.getContainingClass(), thatNext.getContainingClass())) {
+ return CompareResult.NOT_EQUAL;
+ }
+ }
+ if (leftIterator.hasNext() && !rightIterator.hasNext()) {
+ return CompareResult.LEFT_CONTAINS_RIGHT;
+ }
+ if (!leftIterator.hasNext() && rightIterator.hasNext()) {
+ return CompareResult.RIGHT_CONTAINS_LEFT;
+ }
+ return CompareResult.EQUAL;
+ }
+
+ public enum CompareResult {
+ LEFT_CONTAINS_RIGHT,
+ RIGHT_CONTAINS_LEFT,
+ EQUAL,
+ NOT_EQUAL
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChainLookupRangingHelper.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChainLookupRangingHelper.java
new file mode 100644
index 000000000000..58a76937b801
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChainLookupRangingHelper.java
@@ -0,0 +1,230 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.codeInsight.NullableNotNullManager;
+import com.intellij.codeInsight.completion.JavaChainLookupElement;
+import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
+import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
+import com.intellij.codeInsight.completion.methodChains.completion.context.ContextRelevantStaticMethod;
+import com.intellij.codeInsight.completion.methodChains.completion.context.ContextRelevantVariableGetter;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.ChainCompletionNewVariableLookupElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.WeightableChainLookupElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.GetterLookupSubLookupElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
+import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.VariableSubLookupElement;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.VariableLookupItem;
+import com.intellij.psi.*;
+import com.intellij.util.containers.ContainerUtil;
+import gnu.trove.TIntObjectHashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static com.intellij.codeInsight.completion.methodChains.completion.lookup.ChainCompletionLookupElementUtil.createLookupElement;
+import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class MethodsChainLookupRangingHelper {
+
+ public static List<LookupElement> chainsToWeightableLookupElements(final List<MethodsChain> chains,
+ final ChainCompletionContext context) {
+ final List<LookupElement> lookupElements = new ArrayList<LookupElement>(chains.size());
+ for (final MethodsChain chain : chains) {
+ final LookupElement lookupElement = chainToWeightableLookupElement(chain, context);
+ if (lookupElement != null) {
+ lookupElements.add(lookupElement);
+ }
+ }
+ return lookupElements;
+ }
+
+ @SuppressWarnings("ConstantConditions")
+ @Nullable
+ private static WeightableChainLookupElement chainToWeightableLookupElement(final MethodsChain chain,
+ final ChainCompletionContext context) {
+ final int chainSize = chain.size();
+ assert chainSize != 0;
+ final int lastMethodWeight = chain.getChainWeight();
+ int unreachableParametersCount = 0;
+ int notMatchedStringVars = 0;
+ Boolean isFirstMethodStatic = null;
+ Boolean hasCallingVariableInContext = null;
+ LookupElement chainLookupElement = null;
+
+ final NullableNotNullManager nullableNotNullManager = NullableNotNullManager.getInstance(context.getProject());
+
+ for (final PsiMethod[] psiMethods : chain.getPath()) {
+ final PsiMethod method =
+ MethodChainsSearchUtil.getMethodWithMinNotPrimitiveParameters(psiMethods, Collections.singleton(context.getTargetQName()));
+ if (method == null) {
+ return null;
+ }
+ if (isFirstMethodStatic == null) {
+ isFirstMethodStatic = psiMethods[0].hasModifierProperty(PsiModifier.STATIC);
+ }
+ final MethodProcResult procResult =
+ processMethod(method, context, lastMethodWeight, chainLookupElement == null, nullableNotNullManager);
+ if (procResult == null) {
+ return null;
+ }
+ if (hasCallingVariableInContext == null) {
+ hasCallingVariableInContext = procResult.hasCallingVariableInContext();
+ }
+ unreachableParametersCount += procResult.getUnreachableParametersCount();
+ notMatchedStringVars += procResult.getNotMatchedStringVars();
+ chainLookupElement = chainLookupElement == null
+ ? procResult.getLookupElement()
+ : new JavaChainLookupElement(chainLookupElement, procResult.getLookupElement());
+ }
+
+ final ChainRelevance relevance = new ChainRelevance(chainSize,
+ lastMethodWeight,
+ unreachableParametersCount,
+ notMatchedStringVars,
+ hasCallingVariableInContext,
+ isFirstMethodStatic);
+
+ return new WeightableChainLookupElement(chainLookupElement, relevance);
+ }
+
+
+ private static MethodProcResult processMethod(@NotNull final PsiMethod method,
+ final ChainCompletionContext context,
+ final int weight,
+ final boolean isHeadMethod,
+ final NullableNotNullManager nullableNotNullManager) {
+ int unreachableParametersCount = 0;
+ int notMatchedStringVars = 0;
+ boolean hasCallingVariableInContext = false;
+ final PsiParameterList parameterList = method.getParameterList();
+ final TIntObjectHashMap<SubLookupElement> parametersMap = new TIntObjectHashMap<SubLookupElement>(parameterList.getParametersCount());
+ final PsiParameter[] parameters = parameterList.getParameters();
+ for (int i = 0; i < parameters.length; i++) {
+ final PsiParameter parameter = parameters[i];
+ final String typeQName = parameter.getType().getCanonicalText();
+ if (typeQName != null) {
+ if (JAVA_LANG_STRING.equals(typeQName)) {
+ final PsiVariable relevantStringVar = context.findRelevantStringInContext(parameter.getName());
+ if (relevantStringVar == null) {
+ notMatchedStringVars++;
+ }
+ else {
+ parametersMap.put(i, new VariableSubLookupElement(relevantStringVar));
+ }
+ }
+ else if (!ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(typeQName)) {
+ final Collection<PsiVariable> contextVariables = context.getVariables(typeQName);
+ final PsiVariable contextVariable = ContainerUtil.getFirstItem(contextVariables, null);
+ if (contextVariable != null) {
+ if (contextVariables.size() == 1) parametersMap.put(i, new VariableSubLookupElement(contextVariable));
+ continue;
+ }
+ final Collection<ContextRelevantVariableGetter> relevantVariablesGetters = context.getRelevantVariablesGetters(typeQName);
+ final ContextRelevantVariableGetter contextVariableGetter = ContainerUtil.getFirstItem(relevantVariablesGetters, null);
+ if (contextVariableGetter != null) {
+ if (relevantVariablesGetters.size() == 1) parametersMap.put(i, contextVariableGetter.createSubLookupElement());
+ continue;
+ }
+ final Collection<PsiMethod> containingClassMethods = context.getContainingClassMethods(typeQName);
+ final PsiMethod contextRelevantGetter = ContainerUtil.getFirstItem(containingClassMethods, null);
+ if (contextRelevantGetter != null) {
+ if (containingClassMethods.size() == 1) parametersMap.put(i, new GetterLookupSubLookupElement(method.getName()));
+ continue;
+ }
+ final ContextRelevantStaticMethod contextRelevantStaticMethod =
+ ContainerUtil.getFirstItem(context.getRelevantStaticMethods(typeQName, weight), null);
+ if (contextRelevantStaticMethod != null) {
+ //
+ // In most cases it is not really relevant
+ //
+ //parametersMap.put(i, contextRelevantStaticMethod.createLookupElement());
+ continue;
+ }
+ if (!nullableNotNullManager.isNullable(parameter, true)) {
+ unreachableParametersCount++;
+ }
+ }
+ }
+ }
+ final LookupElement lookupElement;
+ if (isHeadMethod) {
+ if (method.hasModifierProperty(PsiModifier.STATIC)) {
+ lookupElement = createLookupElement(method, parametersMap);
+ }
+ else if (method.isConstructor()) {
+ return null;
+ }
+ else {
+ final PsiClass containingClass = method.getContainingClass();
+ final String classQName = containingClass.getQualifiedName();
+ if (classQName == null) return null;
+ final Object e = ContainerUtil.getFirstItem(context.getContextRefElements(classQName), null);
+ if (e != null) {
+ final LookupElement firstChainElement;
+ if (e instanceof PsiVariable) {
+ hasCallingVariableInContext = true;
+ firstChainElement = new VariableLookupItem((PsiVariable)e);
+ }
+ else if (e instanceof PsiMethod) {
+ firstChainElement = createLookupElement((PsiMethod)e, null);
+ }
+ else if (e instanceof LookupElement) {
+ firstChainElement = (LookupElement)e;
+ }
+ else {
+ throw new AssertionError();
+ }
+ lookupElement = new JavaChainLookupElement(firstChainElement, createLookupElement(method, parametersMap));
+ }
+ else lookupElement = context.getContainingClassQNames().contains(classQName)
+ ? createLookupElement(method, parametersMap)
+ : new JavaChainLookupElement(ChainCompletionNewVariableLookupElement.create(containingClass),
+ createLookupElement(method, parametersMap));
+ }
+ }
+ else {
+ lookupElement = createLookupElement(method, parametersMap);
+ }
+ return new MethodProcResult(lookupElement, unreachableParametersCount, notMatchedStringVars, hasCallingVariableInContext);
+ }
+
+ private static class MethodProcResult {
+ private final LookupElement myMethodLookup;
+ private final int myUnreachableParametersCount;
+ private final int myNotMatchedStringVars;
+ private final boolean myHasCallingVariableInContext;
+
+ private MethodProcResult(final LookupElement methodLookup,
+ final int unreachableParametersCount,
+ final int notMatchedStringVars,
+ final boolean hasCallingVariableInContext) {
+ myMethodLookup = methodLookup;
+ myUnreachableParametersCount = unreachableParametersCount;
+ myNotMatchedStringVars = notMatchedStringVars;
+ myHasCallingVariableInContext = hasCallingVariableInContext;
+ }
+
+ private boolean hasCallingVariableInContext() {
+ return myHasCallingVariableInContext;
+ }
+
+ private LookupElement getLookupElement() {
+ return myMethodLookup;
+ }
+
+ private int getUnreachableParametersCount() {
+ return myUnreachableParametersCount;
+ }
+
+ private int getNotMatchedStringVars() {
+ return myNotMatchedStringVars;
+ }
+ }
+}
+
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/SearchInitializer.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/SearchInitializer.java
new file mode 100644
index 000000000000..1f9831361299
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/SearchInitializer.java
@@ -0,0 +1,128 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import com.intellij.codeInsight.completion.methodChains.Constants;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiModifier;
+import com.intellij.util.containers.FactoryMap;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class SearchInitializer {
+ private final List<WeightAware<MethodIncompleteSignature>> myVertexes;
+ private final LinkedHashMap<MethodIncompleteSignature, MethodsChain> myChains;
+ private final Map<MethodIncompleteSignature, Integer> myOccurrencesMap;
+ private final FactoryMap<MethodIncompleteSignature, PsiMethod[]> myResolver;
+
+ public SearchInitializer(final SortedSet<UsageIndexValue> indexValues,
+ final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
+ final String targetQName,
+ final Set<String> excludedParamsTypesQNames) {
+ myResolver = resolver;
+ final int size = indexValues.size();
+ myVertexes = new ArrayList<WeightAware<MethodIncompleteSignature>>(size);
+ myChains = new LinkedHashMap<MethodIncompleteSignature, MethodsChain>(size);
+ myOccurrencesMap = new HashMap<MethodIncompleteSignature, Integer>(size);
+ add(indexValues, MethodChainsSearchUtil.unionToHashSet(excludedParamsTypesQNames, targetQName));
+ }
+
+ private void add(final Collection<UsageIndexValue> indexValues, final Set<String> excludedParamsTypesQNames) {
+ int bestOccurrences = -1;
+ for (final UsageIndexValue indexValue : indexValues) {
+ if (add(indexValue, excludedParamsTypesQNames)) {
+ final int occurrences = indexValue.getOccurrences();
+ if (bestOccurrences == -1) {
+ bestOccurrences = occurrences;
+ } else if (bestOccurrences > occurrences * Constants.CHAIN_SEARCH_MAGIC_RATIO) {
+ return;
+ }
+ }
+ }
+ }
+
+ private boolean add(final UsageIndexValue indexValue, final Set<String> excludedParamsTypesQNames) {
+ final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
+ final PsiMethod[] psiMethods = myResolver.get(methodInvocation);
+ if (psiMethods.length != 0 && MethodChainsSearchUtil.checkParametersForTypesQNames(psiMethods, excludedParamsTypesQNames)) {
+ final int occurrences = indexValue.getOccurrences();
+ final MethodsChain methodsChain = new MethodsChain(psiMethods, occurrences);
+ myChains.put(methodInvocation, methodsChain);
+ myVertexes.add(new WeightAware<MethodIncompleteSignature>(methodInvocation, occurrences));
+ myOccurrencesMap.put(methodInvocation, occurrences);
+ return true;
+ }
+ return false;
+ }
+
+ public InitResult init(final Set<String> excludedEdgeNames,
+ final Set<String> contextQNames,
+ final MethodChainsSearchService searchService,
+ final String contextMethodName) {
+ final int size = myVertexes.size();
+ int bestOccurrences = 0;
+ MethodsChain bestTargetMethodChain = null;
+ final List<WeightAware<MethodIncompleteSignature>> initedVertexes = new ArrayList<WeightAware<MethodIncompleteSignature>>(size);
+ final LinkedHashMap<MethodIncompleteSignature, MethodsChain> initedChains = new LinkedHashMap<MethodIncompleteSignature, MethodsChain>(size);
+ final Iterator<Map.Entry<MethodIncompleteSignature, MethodsChain>> chainsIterator = myChains.entrySet().iterator();
+ for (final WeightAware<MethodIncompleteSignature> vertex : myVertexes) {
+ final Map.Entry<MethodIncompleteSignature, MethodsChain> chainEntry = chainsIterator.next();
+ final MethodIncompleteSignature method = vertex.getUnderlying();
+ if (!excludedEdgeNames.contains(method.getName())) {
+ initedVertexes.add(vertex);
+ final MethodsChain methodsChain = chainEntry.getValue();
+ initedChains.put(chainEntry.getKey(), methodsChain);
+ if (contextQNames.contains(method.getOwner())) {
+ final Integer occurrences = myOccurrencesMap.get(method);
+ if (occurrences > bestOccurrences) {
+ final PsiMethod oneOfFirst = methodsChain.getOneOfFirst();
+ if (oneOfFirst != null && oneOfFirst.hasModifierProperty(PsiModifier.STATIC)) {
+ bestTargetMethodChain = methodsChain;
+ bestOccurrences = occurrences;
+ continue;
+ }
+ final PsiClass firstQualifierClass = methodsChain.getFirstQualifierClass();
+ if (firstQualifierClass != null && (searchService.isSingleton(firstQualifierClass, contextMethodName)
+ || contextQNames.contains(firstQualifierClass.getQualifiedName()))) {
+ bestTargetMethodChain = methodsChain;
+ bestOccurrences = occurrences;
+ }
+ }
+ }
+ }
+ }
+ return new InitResult(initedVertexes, initedChains, bestTargetMethodChain);
+ }
+
+ public static class InitResult {
+ private final List<WeightAware<MethodIncompleteSignature>> myVertexes;
+ private final LinkedHashMap<MethodIncompleteSignature, MethodsChain> myChains;
+ private final MethodsChain myCurrentBestTargetChain;
+
+ private InitResult(final List<WeightAware<MethodIncompleteSignature>> vertexes,
+ final LinkedHashMap<MethodIncompleteSignature, MethodsChain> chains,
+ final @Nullable MethodsChain currentBestTargetChain) {
+ this.myVertexes = vertexes;
+ this.myChains = chains;
+ this.myCurrentBestTargetChain = currentBestTargetChain;
+ }
+
+ public List<WeightAware<MethodIncompleteSignature>> getVertexes() {
+ return myVertexes;
+ }
+
+ public LinkedHashMap<MethodIncompleteSignature, MethodsChain> getChains() {
+ return myChains;
+ }
+
+ @Nullable
+ public MethodsChain getCurrentBestTargetChain() {
+ return myCurrentBestTargetChain;
+ }
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/WeightAware.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/WeightAware.java
new file mode 100644
index 000000000000..617053d57baf
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/WeightAware.java
@@ -0,0 +1,29 @@
+package com.intellij.codeInsight.completion.methodChains.search;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class WeightAware<V> implements Comparable<WeightAware<V>> {
+ private final V myUnderlying;
+ private final int myWeight;
+
+ public WeightAware(final V underlying, final int weight) {
+ myUnderlying = underlying;
+ myWeight = weight;
+ }
+
+ public V getUnderlying() {
+ return myUnderlying;
+ }
+
+ public int getWeight() {
+ return myWeight;
+ }
+
+ @Override
+ public int compareTo(@NotNull final WeightAware<V> that) {
+ return -getWeight() + that.getWeight();
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/service/OverridenMethodsService.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/service/OverridenMethodsService.java
new file mode 100644
index 000000000000..f310a463b49c
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/service/OverridenMethodsService.java
@@ -0,0 +1,65 @@
+package com.intellij.codeInsight.completion.methodChains.search.service;
+
+import com.google.common.collect.Multiset;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.compilerOutputIndex.impl.callingLocation.CallingLocation;
+import com.intellij.compilerOutputIndex.impl.callingLocation.MethodCallingLocationIndex;
+import com.intellij.compilerOutputIndex.impl.callingLocation.MethodNameAndQualifier;
+import com.intellij.compilerOutputIndex.impl.callingLocation.VariableType;
+import com.intellij.compilerOutputIndex.impl.quickInheritance.QuickInheritanceIndex;
+import com.intellij.compilerOutputIndex.impl.quickInheritance.QuickMethodsIndex;
+import com.intellij.compilerOutputIndex.impl.quickInheritance.QuickOverrideUtil;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class OverridenMethodsService {
+
+ private final QuickMethodsIndex myQuickMethodsIndex;
+ private final QuickInheritanceIndex myQuickInheritanceIndex;
+ private final MethodCallingLocationIndex myMethodCallingLocationIndex;
+
+ public OverridenMethodsService(final Project project) {
+ myQuickInheritanceIndex = QuickInheritanceIndex.getInstance(project);
+ myQuickMethodsIndex = QuickMethodsIndex.getInstance(project);
+ myMethodCallingLocationIndex = MethodCallingLocationIndex.getInstance(project);
+ }
+
+ public boolean isMethodOverriden(final String classQName, final String methodName) {
+ return QuickOverrideUtil.isMethodOverriden(classQName, methodName, myQuickInheritanceIndex, myQuickMethodsIndex);
+ }
+
+ public Pair<Integer, Integer> getMethodsUsageInOverridenContext(final MethodNameAndQualifier method) {
+ final Multiset<MethodIncompleteSignature> locationsAsParam = myMethodCallingLocationIndex.getLocationsAsParam(method);
+ int overridenOccurrences = 0;
+ int nonOverridenOccurrences = 0;
+ for (final Multiset.Entry<MethodIncompleteSignature> e : locationsAsParam.entrySet()) {
+ final MethodIncompleteSignature sign = e.getElement();
+ final boolean methodOverriden = isMethodOverriden(sign.getOwner(), sign.getName());
+ if (methodOverriden) {
+ overridenOccurrences++;
+ }
+ else {
+ nonOverridenOccurrences++;
+ }
+ }
+
+ return Pair.create(overridenOccurrences, nonOverridenOccurrences);
+ }
+
+ public Pair<Integer, Integer> getMethodUsageInFieldContext(final MethodNameAndQualifier method) {
+ int asField = 0;
+ int notField = 0;
+ for (final CallingLocation callingLocation : myMethodCallingLocationIndex.getAllLocations(method)) {
+ if (callingLocation.getVariableType().equals(VariableType.FIELD)) {
+ asField++;
+ }
+ else {
+ notField++;
+ }
+ }
+ return Pair.create(asField, notField);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/service/SingletonService.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/service/SingletonService.java
new file mode 100644
index 000000000000..4f27ad24cf1f
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/service/SingletonService.java
@@ -0,0 +1,89 @@
+package com.intellij.codeInsight.completion.methodChains.search.service;
+
+import com.intellij.codeInsight.completion.methodChains.Constants;
+import com.intellij.compilerOutputIndex.impl.singleton.MethodShortSignatureWithWeight;
+import com.intellij.compilerOutputIndex.impl.singleton.ParamsInMethodOccurrencesIndex;
+import com.intellij.compilerOutputIndex.impl.singleton.TwinVariablesIndex;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.CommonClassNames;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class SingletonService {
+ private final TwinVariablesIndex myTwinVariablesIndex;
+ private final ParamsInMethodOccurrencesIndex myParamsInMethodOccurrencesIndex;
+ private final GlobalSearchScope myAllScope;
+ private final JavaPsiFacade myJavaPsiFacade;
+
+ private final Map<String, Boolean> myLocalCache;
+
+ public SingletonService(final Project project) {
+ myTwinVariablesIndex = TwinVariablesIndex.getInstance(project);
+ myParamsInMethodOccurrencesIndex = ParamsInMethodOccurrencesIndex.getInstance(project);
+ myAllScope = GlobalSearchScope.allScope(project);
+ myJavaPsiFacade = JavaPsiFacade.getInstance(project);
+
+ myLocalCache = new HashMap<String, Boolean>();
+ myLocalCache.put(null, false);
+ }
+
+ public boolean isSingleton(@Nullable final String typeQName, final @NotNull String contextMethodName) {
+ final Boolean isSingletonCached = myLocalCache.get(typeQName);
+ if (isSingletonCached == null) {
+ assert typeQName != null;
+ final PsiClass aClass = myJavaPsiFacade.findClass(typeQName, myAllScope);
+ if (aClass == null) {
+ myLocalCache.put(typeQName, false);
+ return false;
+ }
+ for (final PsiClass psiClass : aClass.getInterfaces()) {
+ final String qualifiedName = psiClass.getQualifiedName();
+ if (CommonClassNames.JAVA_LANG_OBJECT.equals(qualifiedName) || !isSingleton(qualifiedName, contextMethodName)) {
+ myLocalCache.put(typeQName, false);
+ return false;
+ }
+ }
+ final boolean isSingleton = hasTwinsFeature(typeQName) && isSuitableTypeFor(typeQName, contextMethodName);
+ myLocalCache.put(typeQName, isSingleton);
+ return isSingleton;
+ }
+ return isSingletonCached;
+ }
+
+ public boolean hasTwinsFeature(final String typeQName) {
+ final List<Integer> twinInfo = myTwinVariablesIndex.getTwinInfo(typeQName);
+ if (twinInfo.isEmpty()) {
+ return false;
+ }
+ int ones = 0;
+ for (final int i : twinInfo) {
+ if (i == 1) {
+ ones++;
+ }
+ }
+ return (twinInfo.size() - ones) * Constants.SINGLETON_MAGIC_RATIO < twinInfo.size();
+ }
+
+ private boolean isSuitableTypeFor(final String typeName, final String methodName) {
+ final Pair<List<MethodShortSignatureWithWeight>, Integer> parameterOccurrences =
+ myParamsInMethodOccurrencesIndex.getParameterOccurrences(typeName);
+ if (parameterOccurrences.getSecond() == 0) {
+ return true;
+ }
+ final List<MethodShortSignatureWithWeight> contextMethods = parameterOccurrences.getFirst();
+ final MethodShortSignatureWithWeight last = contextMethods.get(contextMethods.size() - 1);
+ return last.getMethodShortSignature().getName().equals(methodName) || last.getWeight() * Constants.SINGLETON_MAGIC_RATIO2 <= parameterOccurrences.getSecond();
+ }
+
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java
index 16fad58d214a..2ec4c4888d53 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java
@@ -95,8 +95,7 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
}
}
else if (qualifier != null) {
- myQualifierType = qualifier.getType();
- myQualifierClass = PsiUtil.resolveClassInType(myQualifierType);
+ setQualifierType(qualifier.getType());
if (myQualifierType == null && qualifier instanceof PsiJavaCodeReferenceElement) {
final PsiElement target = ((PsiJavaCodeReferenceElement)qualifier).resolve();
if (target instanceof PsiClass) {
@@ -256,6 +255,11 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
return false;
}
+ public void setQualifierType(@Nullable PsiType qualifierType) {
+ myQualifierType = qualifierType;
+ myQualifierClass = PsiUtil.resolveClassInClassTypeOnly(qualifierType);
+ }
+
@Nullable
public PsiType getQualifierType() {
return myQualifierType;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java
index 43a7037397ff..10de8bf533bf 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java
@@ -27,8 +27,7 @@ import com.intellij.codeInsight.daemon.impl.quickfix.*;
import com.intellij.codeInsight.intention.EmptyIntentionAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.IntentionManager;
-import com.intellij.codeInspection.InspectionProfile;
-import com.intellij.codeInspection.InspectionsBundle;
+import com.intellij.codeInspection.*;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
import com.intellij.codeInspection.ex.InspectionManagerEx;
import com.intellij.codeInspection.reference.UnusedDeclarationFixProvider;
@@ -36,8 +35,8 @@ import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection;
import com.intellij.codeInspection.unusedParameters.UnusedParametersInspection;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import com.intellij.codeInspection.util.SpecialAnnotationsUtilBase;
+import com.intellij.diagnostic.AttachmentFactory;
import com.intellij.diagnostic.LogMessageEx;
-import com.intellij.diagnostic.errordialog.Attachment;
import com.intellij.find.FindManager;
import com.intellij.find.findUsages.*;
import com.intellij.find.impl.FindManagerImpl;
@@ -83,6 +82,8 @@ import org.jetbrains.annotations.PropertyKey;
import java.util.*;
+import static com.intellij.psi.search.PsiSearchHelper.SearchCostResult.*;
+
public class PostHighlightingPass extends TextEditorHighlightingPass {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PostHighlightingPass");
private RefCountHolder myRefCountHolder;
@@ -211,7 +212,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
String afterText = file.getText();
if (Comparing.strEqual(beforeText, afterText)) {
LOG.error(LogMessageEx.createEvent("Import optimizer hasn't optimized any imports", file.getViewProvider().getVirtualFile().getPath(),
- new Attachment(file.getViewProvider().getVirtualFile())));
+ AttachmentFactory.createAttachment(file.getViewProvider().getVirtualFile())));
}
}
}
@@ -312,7 +313,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
return processField((PsiField)parent, identifier, progress, helper);
}
if (parent instanceof PsiParameter && myUnusedSymbolInspection.PARAMETER) {
- if (InspectionManagerEx.isSuppressed(identifier, UnusedParametersInspection.SHORT_NAME)) return null;
+ if (SuppressionUtil.isSuppressed(identifier, UnusedParametersInspection.SHORT_NAME)) return null;
return processParameter((PsiParameter)parent, identifier, progress);
}
if (parent instanceof PsiMethod && myUnusedSymbolInspection.METHOD) {
@@ -499,10 +500,11 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
if (UnusedSymbolLocalInspection.isInjected(method)) return null;
HighlightInfo highlightInfo = checkUnusedParameter(parameter, identifier, progress);
if (highlightInfo != null) {
- final ArrayList<IntentionAction> options = new ArrayList<IntentionAction>();
+ List<IntentionAction> options = new ArrayList<IntentionAction>();
options.addAll(IntentionManager.getInstance().getStandardIntentionOptions(myUnusedSymbolKey, myFile));
if (myUnusedParametersInspection != null) {
- Collections.addAll(options, myUnusedParametersInspection.getSuppressActions(parameter));
+ SuppressQuickFix[] batchSuppressActions = myUnusedParametersInspection.getBatchSuppressActions(parameter);
+ Collections.addAll(options, SuppressManagerImpl.convertBatchToSuppressIntentionActions(batchSuppressActions));
}
//need suppress from Unused Parameters but settings from Unused Symbol
QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedParameterFix(parameter),
@@ -623,16 +625,28 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
useScope = GlobalSearchScope.projectScope(project).uniteWith((GlobalSearchScope)useScope);
}
- PsiSearchHelper.SearchCostResult cheapEnough = PsiSearchHelper.SERVICE.getInstance(project).isCheapEnoughToSearch(name, (GlobalSearchScope)useScope,
- helper.isCurrentFileAlreadyChecked() ? member.getContainingFile() : null,
- progress);
- if (cheapEnough == PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) return false;
+ PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(project);
+ PsiFile file = member.getContainingFile();
+ PsiFile ignoreFile = helper.isCurrentFileAlreadyChecked() ? file : null;
+ PsiSearchHelper.SearchCostResult cheapEnough = searchHelper.isCheapEnoughToSearch(name, (GlobalSearchScope)useScope, ignoreFile, progress);
+ if (cheapEnough == TOO_MANY_OCCURRENCES) return false;
//search usages if it cheap
//if count is 0 there is no usages since we've called myRefCountHolder.isReferenced() before
- if (cheapEnough == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES) {
+ if (cheapEnough == ZERO_OCCURRENCES) {
if (!canBeReferencedViaWeirdNames(member)) return true;
}
+
+ if (member instanceof PsiMethod) {
+ String propertyName = PropertyUtil.getPropertyName(member);
+ if (propertyName != null && file != null) {
+ SearchScope fileScope = file.getUseScope();
+ if (fileScope instanceof GlobalSearchScope &&
+ searchHelper.isCheapEnoughToSearch(propertyName, (GlobalSearchScope)fileScope, ignoreFile, progress) == TOO_MANY_OCCURRENCES) {
+ return false;
+ }
+ }
+ }
}
FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager();
FindUsagesHandler handler = new JavaFindUsagesHandler(member, new JavaFindUsagesHandlerFactory(project));
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RemoveSuppressWarningAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RemoveSuppressWarningAction.java
deleted file mode 100644
index a473befa0b31..000000000000
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RemoveSuppressWarningAction.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInsight.daemon.impl;
-
-import com.intellij.codeInsight.FileModificationService;
-import com.intellij.codeInsight.daemon.QuickFixBundle;
-import com.intellij.codeInspection.LocalQuickFix;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.codeInspection.SuppressManager;
-import com.intellij.codeInspection.SuppressionUtil;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.*;
-import com.intellij.psi.javadoc.PsiDocComment;
-import com.intellij.psi.javadoc.PsiDocTag;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-public class RemoveSuppressWarningAction implements LocalQuickFix {
- private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.RemoveSuppressWarningAction");
-
- private final String myID;
- private final String myProblemLine;
-
- public RemoveSuppressWarningAction(final String ID, final String problemLine) {
- myID = ID;
- myProblemLine = problemLine;
- }
-
- public RemoveSuppressWarningAction(String id) {
- final int idx = id.indexOf(";");
- if (idx > -1) {
- myID = id.substring(0, idx);
- myProblemLine = id.substring(idx);
- }
- else {
- myID = id;
- myProblemLine = null;
- }
- }
-
- @Override
- @NotNull
- public String getFamilyName() {
- return QuickFixBundle.message("remove.suppression.action.family");
- }
-
- @Override
- public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
- PsiElement element = descriptor.getPsiElement();
- try {
- if (element instanceof PsiIdentifier) {
- if (!FileModificationService.getInstance().prepareFileForWrite(element.getContainingFile())) return;
- final PsiIdentifier identifier = (PsiIdentifier)element;
- final PsiDocCommentOwner commentOwner = PsiTreeUtil.getParentOfType(identifier, PsiDocCommentOwner.class);
- if (commentOwner != null) {
- final PsiElement psiElement = SuppressManager.getInstance().getElementMemberSuppressedIn(commentOwner, myID);
- if (psiElement instanceof PsiAnnotation) {
- removeFromAnnotation((PsiAnnotation)psiElement);
- } else if (psiElement instanceof PsiDocComment) {
- removeFromJavaDoc((PsiDocComment)psiElement);
- } else { //try to remove from all comments
- final Set<PsiComment> comments = new HashSet<PsiComment>();
- commentOwner.accept(new PsiRecursiveElementWalkingVisitor() {
- @Override public void visitComment(final PsiComment comment) {
- super.visitComment(comment);
- if (comment.getText().contains(myID)) {
- comments.add(comment);
- }
- }
- });
- for (PsiComment comment : comments) {
- try {
- removeFromComment(comment, comments.size() > 1);
- }
- catch (IncorrectOperationException e) {
- LOG.error(e);
- }
- }
- }
- }
- }
- }
- catch (IncorrectOperationException e) {
- LOG.error(e);
- }
- }
-
- @Override
- @NotNull
- public String getName() {
- return QuickFixBundle.message("remove.suppression.action.name", myID);
- }
-
- private void removeFromComment(final PsiComment comment, final boolean checkLine) throws IncorrectOperationException {
- if (checkLine) {
- final PsiStatement statement = PsiTreeUtil.getNextSiblingOfType(comment, PsiStatement.class);
- if (statement != null && !Comparing.strEqual(statement.getText(), myProblemLine)) return;
- }
- String newText = removeFromElementText(comment);
- if (newText != null) {
- if (newText.length() == 0) {
- comment.delete();
- }
- else {
- PsiComment newComment = JavaPsiFacade.getInstance(comment.getProject()).getElementFactory()
- .createCommentFromText("// " + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME+" "+newText, comment);
- comment.replace(newComment);
- }
- }
- }
-
- private void removeFromJavaDoc(PsiDocComment docComment) throws IncorrectOperationException {
- PsiDocTag tag = docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME);
- if (tag == null) return;
- String newText = removeFromElementText(tag.getDataElements());
- if (newText != null && newText.length() == 0) {
- tag.delete();
- }
- else if (newText != null) {
- newText = "@" + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME + " " + newText;
- PsiDocTag newTag = JavaPsiFacade.getInstance(tag.getProject()).getElementFactory().createDocTagFromText(newText);
- tag.replace(newTag);
- }
- }
-
- @Nullable
- private String removeFromElementText(final PsiElement... elements) {
- String text = "";
- for (PsiElement element : elements) {
- text += StringUtil.trimStart(element.getText(), "//").trim();
- }
- text = StringUtil.trimStart(text, "@").trim();
- text = StringUtil.trimStart(text, SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME).trim();
- List<String> ids = StringUtil.split(text, ",");
- int i = ArrayUtil.find(ids.toArray(), myID);
- if (i==-1) return null;
- ids.remove(i);
- return StringUtil.join(ids, ",");
- }
-
- private void removeFromAnnotation(final PsiAnnotation annotation) throws IncorrectOperationException {
- PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
- for (PsiNameValuePair attribute : attributes) {
- PsiAnnotationMemberValue value = attribute.getValue();
- if (value instanceof PsiArrayInitializerMemberValue) {
- PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)value).getInitializers();
- for (PsiAnnotationMemberValue initializer : initializers) {
- if (removeFromValue(annotation, initializer, initializers.length==1)) return;
- }
- }
- if (removeFromValue(annotation, value, attributes.length==1)) return;
- }
- }
-
- private boolean removeFromValue(final PsiAnnotationMemberValue parent, final PsiAnnotationMemberValue value, final boolean removeParent) throws IncorrectOperationException {
- String text = value.getText();
- text = StringUtil.trimStart(text, "\"");
- text = StringUtil.trimEnd(text, "\"");
- if (myID.equals(text)) {
- if (removeParent) {
- parent.delete();
- }
- else {
- value.delete();
- }
- return true;
- }
- 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 b1cbfe05c3b2..6c9723698a8d 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
@@ -27,6 +27,7 @@ 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.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.PsiClassReferenceType;
@@ -295,7 +296,7 @@ public class AnnotationsHighlightUtil {
);
@Nullable
- public static HighlightInfo checkApplicability(@NotNull PsiAnnotation annotation) {
+ public static HighlightInfo checkApplicability(@NotNull PsiAnnotation annotation, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
if (ANY_ANNOTATION_ALLOWED.accepts(annotation)) {
return null;
}
@@ -311,7 +312,7 @@ public class AnnotationsHighlightUtil {
}
if (!(owner instanceof PsiModifierList)) {
- HighlightInfo info = HighlightUtil.checkTypeAnnotationFeature(annotation);
+ HighlightInfo info = HighlightUtil.checkTypeAnnotationFeature(annotation, languageLevel,containingFile);
if (info != null) return info;
}
@@ -465,23 +466,23 @@ public class AnnotationsHighlightUtil {
LOG.assertTrue(aClass.isAnnotationType());
PsiType type = typeElement.getType();
final Set<PsiClass> checked = new HashSet<PsiClass>();
- if (cyclicDependencies(aClass, type, checked)) {
+ if (cyclicDependencies(aClass, type, checked, aClass.getManager())) {
String description = JavaErrorMessages.message("annotation.cyclic.element.type");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create();
}
return null;
}
- private static boolean cyclicDependencies(PsiClass aClass, PsiType type, Set<PsiClass> checked) {
+ private static boolean cyclicDependencies(PsiClass aClass, PsiType type, @NotNull Set<PsiClass> checked,@NotNull PsiManager manager) {
final PsiClass resolvedClass = PsiUtil.resolveClassInType(type);
if (resolvedClass != null && resolvedClass.isAnnotationType()) {
if (aClass == resolvedClass) {
return true;
}
- if (!checked.add(resolvedClass) || !resolvedClass.getManager().isInProject(resolvedClass)) return false;
+ if (!checked.add(resolvedClass) || !manager.isInProject(resolvedClass)) return false;
final PsiMethod[] methods = resolvedClass.getMethods();
for (PsiMethod method : methods) {
- if (cyclicDependencies(aClass, method.getReturnType(), checked)) return true;
+ if (cyclicDependencies(aClass, method.getReturnType(), checked,manager)) return true;
}
}
return false;
@@ -572,10 +573,10 @@ public class AnnotationsHighlightUtil {
}
@Nullable
- public static HighlightInfo checkFunctionalInterface(PsiAnnotation annotation) {
- final String errorMessage = LambdaUtil.checkFunctionalInterface(annotation);
+ public static HighlightInfo checkFunctionalInterface(@NotNull PsiAnnotation annotation, @NotNull LanguageLevel languageLevel) {
+ final String errorMessage = LambdaUtil.checkFunctionalInterface(annotation, languageLevel);
if (errorMessage != null) {
- return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(annotation).descriptionAndTooltip(errorMessage).create();
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(annotation).descriptionAndTooltip(errorMessage).create();
}
return null;
}
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 48e10ee31035..55990a6ffd0f 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
@@ -68,7 +68,7 @@ public class GenericsHighlightUtil {
for (PsiClassType type : extendsTypes) {
PsiType extendsType = substitutor.substitute(type);
if (substituted instanceof PsiWildcardType) {
- if (!((PsiWildcardType)substituted).isExtends()) {
+ if (((PsiWildcardType)substituted).isSuper()) {
continue;
}
final PsiType extendsBound = ((PsiWildcardType)substituted).getExtendsBound();
@@ -110,17 +110,19 @@ public class GenericsHighlightUtil {
@Nullable
public static HighlightInfo checkParameterizedReferenceTypeArguments(final PsiElement resolved,
final PsiJavaCodeReferenceElement referenceElement,
- final PsiSubstitutor substitutor) {
+ final PsiSubstitutor substitutor,
+ @NotNull JavaSdkVersion javaSdkVersion) {
if (!(resolved instanceof PsiTypeParameterListOwner)) return null;
final PsiTypeParameterListOwner typeParameterListOwner = (PsiTypeParameterListOwner)resolved;
- return checkReferenceTypeArgumentList(typeParameterListOwner, referenceElement.getParameterList(), substitutor, true);
+ return checkReferenceTypeArgumentList(typeParameterListOwner, referenceElement.getParameterList(), substitutor, true, javaSdkVersion);
}
@Nullable
public static HighlightInfo checkReferenceTypeArgumentList(final PsiTypeParameterListOwner typeParameterListOwner,
final PsiReferenceParameterList referenceParameterList,
final PsiSubstitutor substitutor,
- boolean registerIntentions) {
+ boolean registerIntentions,
+ @NotNull JavaSdkVersion javaSdkVersion) {
PsiDiamondType.DiamondInferenceResult inferenceResult = null;
PsiTypeElement[] referenceElements = null;
if (referenceParameterList != null) {
@@ -150,7 +152,7 @@ public class GenericsHighlightUtil {
if (targetParametersNum == 0) {
if (PsiTreeUtil.getParentOfType(referenceParameterList, PsiCall.class) != null &&
typeParameterListOwner instanceof PsiMethod &&
- JavaVersionService.getInstance().isAtLeast(referenceParameterList, JavaSdkVersion.JDK_1_7)) {
+ javaSdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7)) {
description = null;
}
else {
@@ -388,7 +390,8 @@ public class GenericsHighlightUtil {
public static HighlightInfo checkElementInTypeParameterExtendsList(@NotNull PsiReferenceList referenceList,
@NotNull PsiClass aClass,
@NotNull JavaResolveResult resolveResult,
- @NotNull PsiElement element) {
+ @NotNull PsiElement element,
+ @NotNull LanguageLevel languageLevel) {
final PsiJavaCodeReferenceElement[] referenceElements = referenceList.getReferenceElements();
PsiClass extendFrom = (PsiClass)resolveResult.getElement();
if (extendFrom == null) return null;
@@ -408,7 +411,7 @@ public class GenericsHighlightUtil {
IntentionAction fix = QUICK_FIX_FACTORY.createExtendsListFix(aClass, type, false);
QuickFixAction.registerQuickFixAction(errorResult, fix, null);
}
- if (errorResult == null && JavaVersionService.getInstance().isAtLeast(referenceList, JavaSdkVersion.JDK_1_7) &&
+ if (errorResult == null && languageLevel.isAtLeast(LanguageLevel.JDK_1_7) &&
referenceElements.length > 1) {
//todo suppress erased methods which come from the same class
return checkOverrideEquivalentMethods(aClass);
@@ -736,7 +739,7 @@ public class GenericsHighlightUtil {
//http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2
@Nullable
- public static HighlightInfo checkAccessStaticFieldFromEnumConstructor(PsiReferenceExpression expr, JavaResolveResult result) {
+ public static HighlightInfo checkAccessStaticFieldFromEnumConstructor(@NotNull PsiReferenceExpression expr, @NotNull JavaResolveResult result) {
final PsiElement resolved = result.getElement();
if (!(resolved instanceof PsiField)) return null;
@@ -806,10 +809,10 @@ public class GenericsHighlightUtil {
}
@Nullable
- public static HighlightInfo checkTypeParametersList(PsiTypeParameterList parameterList) {
+ public static HighlightInfo checkTypeParametersList(PsiTypeParameterList parameterList, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
PsiTypeParameter[] typeParameters = parameterList.getTypeParameters();
if (typeParameters.length == 0) return null;
- HighlightInfo info = HighlightUtil.checkGenericsFeature(parameterList, typeParameters.length);
+ HighlightInfo info = HighlightUtil.checkGenericsFeature(parameterList, typeParameters.length, languageLevel, containingFile);
if (info != null) return info;
final PsiElement parent = parameterList.getParent();
@@ -839,7 +842,7 @@ public class GenericsHighlightUtil {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeParameter2).descriptionAndTooltip(message).create();
}
}
- if (!JavaVersionService.getInstance().isAtLeast(parameterList, JavaSdkVersion.JDK_1_7)) {
+ if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
for (PsiJavaCodeReferenceElement referenceElement : typeParameter1.getExtendsList().getReferenceElements()) {
final PsiElement resolve = referenceElement.resolve();
if (resolve instanceof PsiTypeParameter && ArrayUtilRt.find(typeParameters, resolve) > i) {
@@ -941,7 +944,7 @@ public class GenericsHighlightUtil {
}
@Nullable
- public static HighlightInfo checkOverrideAnnotation(PsiMethod method) {
+ public static HighlightInfo checkOverrideAnnotation(PsiMethod method, final LanguageLevel languageLevel) {
PsiModifierList list = method.getModifierList();
final PsiAnnotation overrideAnnotation = list.findAnnotation("java.lang.Override");
if (overrideAnnotation == null) {
@@ -962,7 +965,6 @@ public class GenericsHighlightUtil {
PullAsAbstractUpFix.registerQuickFix(highlightInfo, method);
return highlightInfo;
}
- LanguageLevel languageLevel = PsiUtil.getLanguageLevel(method);
PsiClass superClass = superMethod.getMethod().getContainingClass();
if (languageLevel.equals(LanguageLevel.JDK_1_5) &&
superClass != null &&
@@ -1023,7 +1025,9 @@ public class GenericsHighlightUtil {
}
}
- static void checkEnumConstantForConstructorProblems(PsiEnumConstant enumConstant, final HighlightInfoHolder holder) {
+ static void checkEnumConstantForConstructorProblems(PsiEnumConstant enumConstant,
+ final HighlightInfoHolder holder,
+ @NotNull JavaSdkVersion javaSdkVersion) {
PsiClass containingClass = enumConstant.getContainingClass();
if (enumConstant.getInitializingClass() == null) {
HighlightInfo highlightInfo = HighlightClassUtil.checkInstantiationOfAbstractClass(containingClass, enumConstant.getNameIdentifier());
@@ -1040,7 +1044,7 @@ public class GenericsHighlightUtil {
}
PsiClassType type = JavaPsiFacade.getInstance(holder.getProject()).getElementFactory().createType(containingClass);
- HighlightMethodUtil.checkConstructorCall(type.resolveGenerics(), enumConstant, type, null, holder);
+ HighlightMethodUtil.checkConstructorCall(type.resolveGenerics(), enumConstant, type, null, holder, javaSdkVersion);
}
@Nullable
@@ -1061,12 +1065,12 @@ public class GenericsHighlightUtil {
}
@Nullable
- public static HighlightInfo checkVarArgParameterIsLast(PsiParameter parameter) {
+ public static HighlightInfo checkVarArgParameterIsLast(@NotNull PsiParameter parameter, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
PsiElement declarationScope = parameter.getDeclarationScope();
if (declarationScope instanceof PsiMethod) {
PsiParameter[] params = ((PsiMethod)declarationScope).getParameterList().getParameters();
if (parameter.isVarArgs()) {
- HighlightInfo info = HighlightUtil.checkVarargFeature(parameter);
+ HighlightInfo info = HighlightUtil.checkVarargFeature(parameter, languageLevel,containingFile);
if (info != null) return info;
if (params[params.length - 1] != parameter) {
@@ -1097,8 +1101,9 @@ public class GenericsHighlightUtil {
}
@Nullable
- public static HighlightInfo checkParametersAllowed(PsiReferenceParameterList refParamList) {
- HighlightInfo info = HighlightUtil.checkGenericsFeature(refParamList, refParamList.getTypeParameterElements().length);
+ public static HighlightInfo checkParametersAllowed(PsiReferenceParameterList refParamList, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+ HighlightInfo info = HighlightUtil.checkGenericsFeature(refParamList, refParamList.getTypeParameterElements().length,
+ languageLevel, containingFile);
if (info != null) return info;
if (refParamList.getTextLength() != 0) {
@@ -1148,7 +1153,7 @@ public class GenericsHighlightUtil {
if (qualifier instanceof PsiReferenceExpression){
final PsiClass typeParameter = PsiUtil.resolveClassInType(((PsiReferenceExpression)qualifier).getType());
if (typeParameter instanceof PsiTypeParameter) {
- if (JavaVersionService.getInstance().isAtLeast(element, JavaSdkVersion.JDK_1_7)) return null;
+ if (JavaVersionService.getInstance().isAtLeast(containingClass, JavaSdkVersion.JDK_1_7)) return null;
for (PsiClassType classType : typeParameter.getExtendsListTypes()) {
final PsiClass resolve = classType.resolve();
if (resolve != null) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
index ae32b61b8e45..449df8e09b16 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
@@ -377,7 +377,7 @@ public class HighlightClassUtil {
.parent(PsiMatchers.hasClass(PsiModifierList.class))
.parent(PsiMatchers.hasClass(parentClass))
.parent(PsiMatchers.hasClass(PsiClass.class))
- .dot(PsiMatchers.hasModifier(PsiModifier.STATIC, false))
+ .dot(JavaMatchers.hasModifier(PsiModifier.STATIC, false))
.parent(PsiMatchers.hasClass(PsiClass.class, PsiDeclarationStatement.class, PsiNewExpression.class, PsiEnumConstant.class))
.getElement();
}
@@ -387,9 +387,9 @@ public class HighlightClassUtil {
// keyword points to 'class' or 'interface' or 'enum'
if (new PsiMatcherImpl(keyword)
.parent(PsiMatchers.hasClass(PsiClass.class))
- .dot(PsiMatchers.hasModifier(PsiModifier.STATIC, true))
+ .dot(JavaMatchers.hasModifier(PsiModifier.STATIC, true))
.parent(PsiMatchers.hasClass(PsiClass.class))
- .dot(PsiMatchers.hasModifier(PsiModifier.STATIC, false))
+ .dot(JavaMatchers.hasModifier(PsiModifier.STATIC, false))
.parent(PsiMatchers.hasClass(PsiClass.class, PsiDeclarationStatement.class, PsiNewExpression.class, PsiEnumConstant.class))
.getElement() == null) {
return null;
@@ -626,7 +626,7 @@ public class HighlightClassUtil {
}
@Nullable
- public static HighlightInfo checkExtendsDuplicate(PsiJavaCodeReferenceElement element, PsiElement resolved) {
+ public static HighlightInfo checkExtendsDuplicate(PsiJavaCodeReferenceElement element, PsiElement resolved, @NotNull PsiFile containingFile) {
if (!(element.getParent() instanceof PsiReferenceList)) return null;
PsiReferenceList list = (PsiReferenceList)element.getParent();
if (!(list.getParent() instanceof PsiClass)) return null;
@@ -634,9 +634,10 @@ public class HighlightClassUtil {
PsiClass aClass = (PsiClass)resolved;
PsiClassType[] referencedTypes = list.getReferencedTypes();
int dupCount = 0;
+ PsiManager manager = containingFile.getManager();
for (PsiClassType referencedType : referencedTypes) {
PsiClass resolvedElement = referencedType.resolve();
- if (resolvedElement != null && list.getManager().areElementsEquivalent(resolvedElement, aClass)) {
+ if (resolvedElement != null && manager.areElementsEquivalent(resolvedElement, aClass)) {
dupCount++;
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
index 5a0f156c5bbd..f74f6f9d6214 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
@@ -29,8 +29,6 @@ import com.intellij.psi.controlFlow.*;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.tree.IElementType;
-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.Processor;
@@ -141,7 +139,7 @@ public class HighlightControlFlowUtil {
for (PsiMethod constructor : constructors) {
PsiCodeBlock ctrBody = constructor.getBody();
if (ctrBody == null) return false;
- final List<PsiMethod> redirectedConstructors = getChainedConstructors(constructor);
+ final List<PsiMethod> redirectedConstructors = JavaHighlightUtil.getChainedConstructors(constructor);
for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) {
PsiMethod redirectedConstructor = redirectedConstructors.get(j);
final PsiCodeBlock body = redirectedConstructor.getBody();
@@ -170,21 +168,9 @@ public class HighlightControlFlowUtil {
return false;
}
- /**
- * return all constructors which are referred from this constructor by
- * this (...) at the beginning of the constructor body
- * @return referring constructor
- */
- @Nullable public static List<PsiMethod> getChainedConstructors(PsiMethod constructor) {
- final ConstructorVisitorInfo info = new ConstructorVisitorInfo();
- visitConstructorChain(constructor, info);
- if (info.visitedConstructors != null) info.visitedConstructors.remove(constructor);
- return info.visitedConstructors;
- }
-
public static boolean isRecursivelyCalledConstructor(PsiMethod constructor) {
- final ConstructorVisitorInfo info = new ConstructorVisitorInfo();
- visitConstructorChain(constructor, info);
+ final JavaHighlightUtil.ConstructorVisitorInfo info = new JavaHighlightUtil.ConstructorVisitorInfo();
+ JavaHighlightUtil.visitConstructorChain(constructor, info);
if (info.recursivelyCalledConstructor == null) return false;
// our constructor is reached from some other constructor by constructor chain
return info.visitedConstructors.indexOf(info.recursivelyCalledConstructor) <=
@@ -214,42 +200,6 @@ public class HighlightControlFlowUtil {
}
}
- private static class ConstructorVisitorInfo {
- List<PsiMethod> visitedConstructors;
- PsiMethod recursivelyCalledConstructor;
- }
-
- private static void visitConstructorChain(PsiMethod constructor, ConstructorVisitorInfo info) {
- while (true) {
- if (constructor == null) return;
- final PsiCodeBlock body = constructor.getBody();
- if (body == null) return;
- final PsiStatement[] statements = body.getStatements();
- if (statements.length == 0) return;
- final PsiStatement statement = statements[0];
- final PsiElement element = new PsiMatcherImpl(statement)
- .dot(PsiMatchers.hasClass(PsiExpressionStatement.class))
- .firstChild(PsiMatchers.hasClass(PsiMethodCallExpression.class))
- .firstChild(PsiMatchers.hasClass(PsiReferenceExpression.class))
- .firstChild(PsiMatchers.hasClass(PsiKeyword.class))
- .dot(PsiMatchers.hasText(PsiKeyword.THIS))
- .parent(null)
- .parent(null)
- .getElement();
- if (element == null) return;
- PsiMethodCallExpression methodCall = (PsiMethodCallExpression)element;
- PsiMethod method = methodCall.resolveMethod();
- if (method == null) return;
- if (info.visitedConstructors != null && info.visitedConstructors.contains(method)) {
- info.recursivelyCalledConstructor = method;
- return;
- }
- if (info.visitedConstructors == null) info.visitedConstructors = new ArrayList<PsiMethod>(5);
- info.visitedConstructors.add(method);
- constructor = method;
- }
- }
-
/**
* see JLS chapter 16
* @return true if variable assigned (maybe more than once)
@@ -298,7 +248,7 @@ public class HighlightControlFlowUtil {
@Nullable
public static HighlightInfo checkVariableInitializedBeforeUsage(PsiReferenceExpression expression,
PsiVariable variable,
- Map<PsiElement, Collection<PsiReferenceExpression>> uninitializedVarProblems) {
+ Map<PsiElement, Collection<PsiReferenceExpression>> uninitializedVarProblems, @NotNull PsiFile containingFile) {
if (variable instanceof ImplicitVariable) return null;
if (!PsiUtil.isAccessedForReading(expression)) return null;
final int startOffset = expression.getTextRange().getStartOffset();
@@ -326,18 +276,18 @@ public class HighlightControlFlowUtil {
return null;
}
// access to final fields from inner classes always allowed
- if (inInnerClass(expression, ((PsiField)variable).getContainingClass())) return null;
+ if (inInnerClass(expression, ((PsiField)variable).getContainingClass(),containingFile)) return null;
if (topBlock == null) return null;
final PsiElement parent = topBlock.getParent();
final PsiCodeBlock block;
final PsiClass aClass;
if (parent instanceof PsiMethod) {
PsiMethod constructor = (PsiMethod)parent;
- if (!parent.getManager().areElementsEquivalent(constructor.getContainingClass(), ((PsiField)variable).getContainingClass())) return null;
+ if (!containingFile.getManager().areElementsEquivalent(constructor.getContainingClass(), ((PsiField)variable).getContainingClass())) return null;
// static variables already initialized in class initializers
if (variable.hasModifierProperty(PsiModifier.STATIC)) return null;
// as a last chance, field may be initialized in this() call
- final List<PsiMethod> redirectedConstructors = getChainedConstructors(constructor);
+ final List<PsiMethod> redirectedConstructors = JavaHighlightUtil.getChainedConstructors(constructor);
for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) {
PsiMethod redirectedConstructor = redirectedConstructors.get(j);
// variable must be initialized before its usage
@@ -353,7 +303,7 @@ public class HighlightControlFlowUtil {
}
else if (parent instanceof PsiClassInitializer) {
final PsiClassInitializer classInitializer = (PsiClassInitializer)parent;
- if (!parent.getManager().areElementsEquivalent(classInitializer.getContainingClass(), ((PsiField)variable).getContainingClass())) return null;
+ if (!containingFile.getManager().areElementsEquivalent(classInitializer.getContainingClass(), ((PsiField)variable).getContainingClass())) return null;
block = classInitializer.getBody();
aClass = classInitializer.getContainingClass();
}
@@ -377,7 +327,7 @@ public class HighlightControlFlowUtil {
return null;
}
// as a last chance, field may be initialized in this() call
- final List<PsiMethod> redirectedConstructors = getChainedConstructors(constructor);
+ final List<PsiMethod> redirectedConstructors = JavaHighlightUtil.getChainedConstructors(constructor);
for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) {
PsiMethod redirectedConstructor = redirectedConstructors.get(j);
// variable must be initialized before its usage
@@ -435,9 +385,9 @@ public class HighlightControlFlowUtil {
return null;
}
- private static boolean inInnerClass(PsiElement element, PsiClass containingClass) {
+ private static boolean inInnerClass(PsiElement element, PsiClass containingClass, @NotNull PsiFile containingFile) {
while (element != null) {
- if (element instanceof PsiClass) return !element.getManager().areElementsEquivalent(element, containingClass);
+ if (element instanceof PsiClass) return !containingFile.getManager().areElementsEquivalent(element, containingClass);
element = element.getParent();
}
return false;
@@ -536,7 +486,7 @@ public class HighlightControlFlowUtil {
final PsiMethod ctr = codeBlock.getParent() instanceof PsiMethod ?
(PsiMethod)codeBlock.getParent() : null;
// assignment to final field in several constructors threatens us only if these are linked (there is this() call in the beginning)
- final List<PsiMethod> redirectedConstructors = ctr != null && ctr.isConstructor() ? getChainedConstructors(ctr) : null;
+ final List<PsiMethod> redirectedConstructors = ctr != null && ctr.isConstructor() ? JavaHighlightUtil.getChainedConstructors(ctr) : null;
for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) {
PsiMethod redirectedConstructor = redirectedConstructors.get(j);
if (redirectedConstructor.getBody() != null &&
@@ -593,7 +543,7 @@ public class HighlightControlFlowUtil {
@Nullable
- public static HighlightInfo checkCannotWriteToFinal(PsiExpression expression) {
+ public static HighlightInfo checkCannotWriteToFinal(PsiExpression expression, @NotNull PsiFile containingFile) {
PsiReferenceExpression reference = null;
if (expression instanceof PsiAssignmentExpression) {
final PsiExpression left = ((PsiAssignmentExpression)expression).getLExpression();
@@ -618,7 +568,7 @@ public class HighlightControlFlowUtil {
final PsiElement resolved = reference == null ? null : reference.resolve();
PsiVariable variable = resolved instanceof PsiVariable ? (PsiVariable)resolved : null;
if (variable == null || !variable.hasModifierProperty(PsiModifier.FINAL)) return null;
- if (!canWriteToFinal(variable, expression, reference)) {
+ if (!canWriteToFinal(variable, expression, reference,containingFile)) {
final String name = variable.getName();
String description = JavaErrorMessages.message("assignment.to.final.variable", name);
final HighlightInfo highlightInfo =
@@ -637,7 +587,7 @@ public class HighlightControlFlowUtil {
return null;
}
- private static boolean canWriteToFinal(PsiVariable variable, PsiExpression expression, final PsiReferenceExpression reference) {
+ private static boolean canWriteToFinal(PsiVariable variable, PsiExpression expression, final PsiReferenceExpression reference, @NotNull PsiFile containingFile) {
if (variable.hasInitializer()) return false;
if (variable instanceof PsiParameter) return false;
PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, expression);
@@ -646,9 +596,9 @@ public class HighlightControlFlowUtil {
if (HighlightUtil.findEnclosingFieldInitializer(expression) != null) return true;
// assignment from within inner class is illegal always
PsiField field = (PsiField)variable;
- if (innerClass != null && !innerClass.getManager().areElementsEquivalent(innerClass, field.getContainingClass())) return false;
+ if (innerClass != null && !containingFile.getManager().areElementsEquivalent(innerClass, field.getContainingClass())) return false;
final PsiMember enclosingCtrOrInitializer = PsiUtil.findEnclosingConstructorOrInitializer(expression);
- return enclosingCtrOrInitializer != null && isSameField(variable, enclosingCtrOrInitializer, field, reference);
+ return enclosingCtrOrInitializer != null && isSameField(variable, enclosingCtrOrInitializer, field, reference,containingFile);
}
if (variable instanceof PsiLocalVariable) {
boolean isAccessedFromOtherClass = innerClass != null;
@@ -662,16 +612,18 @@ public class HighlightControlFlowUtil {
private static boolean isSameField(final PsiVariable variable,
final PsiMember enclosingCtrOrInitializer,
final PsiField field,
- final PsiReferenceExpression reference) {
+ final PsiReferenceExpression reference, @NotNull PsiFile containingFile) {
- if (!variable.getManager().areElementsEquivalent(enclosingCtrOrInitializer.getContainingClass(), field.getContainingClass())) return false;
+ if (!containingFile.getManager().areElementsEquivalent(enclosingCtrOrInitializer.getContainingClass(), field.getContainingClass())) return false;
PsiExpression qualifierExpression = reference.getQualifierExpression();
return qualifierExpression == null || qualifierExpression instanceof PsiThisExpression;
}
@Nullable
- static HighlightInfo checkVariableMustBeFinal(PsiVariable variable, PsiJavaCodeReferenceElement context) {
+ static HighlightInfo checkVariableMustBeFinal(PsiVariable variable,
+ PsiJavaCodeReferenceElement context,
+ @NotNull LanguageLevel languageLevel) {
if (variable.hasModifierProperty(PsiModifier.FINAL)) return null;
final PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, context);
if (innerClass != null) {
@@ -682,8 +634,7 @@ public class HighlightControlFlowUtil {
return null;
}
}
- if (PsiUtil.getLanguageLevel(variable).isAtLeast(LanguageLevel.JDK_1_8) &&
- isEffectivelyFinal(variable, innerClass, context)) {
+ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && isEffectivelyFinal(variable, innerClass, context)) {
return null;
}
final String description = JavaErrorMessages.message("variable.must.be.final", context.getText());
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 2d1a4db5ff7d..96319603fc1e 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
@@ -26,9 +26,11 @@ import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.codeInspection.LocalQuickFixOnPsiElementAsIntentionAdapter;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.IndexNotReadyException;
+import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
@@ -312,7 +314,10 @@ public class HighlightMethodUtil {
}
@Nullable
- static HighlightInfo checkMethodCall(PsiMethodCallExpression methodCall, PsiResolveHelper resolveHelper) {
+ static HighlightInfo checkMethodCall(@NotNull PsiMethodCallExpression methodCall,
+ @NotNull PsiResolveHelper resolveHelper,
+ @NotNull LanguageLevel languageLevel,
+ @NotNull JavaSdkVersion javaSdkVersion) {
PsiExpressionList list = methodCall.getArgumentList();
PsiReferenceExpression referenceToMethod = methodCall.getMethodExpression();
JavaResolveResult[] results = referenceToMethod.multiResolve(true);
@@ -327,7 +332,7 @@ public class HighlightMethodUtil {
if (resolved instanceof PsiMethod && resolveResult.isValidResult()) {
TextRange fixRange = getFixRange(methodCall);
highlightInfo = HighlightUtil.checkUnhandledExceptions(methodCall, fixRange);
- if (highlightInfo == null && !LambdaUtil.isValidQualifier4InterfaceStaticMethodCall((PsiMethod)resolved, methodCall.getMethodExpression())) {
+ if (highlightInfo == null && !LambdaUtil.isValidQualifier4InterfaceStaticMethodCall((PsiMethod)resolved, methodCall.getMethodExpression(), languageLevel)) {
highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip("Static method may be invoked on containing interface class only").range(fixRange).create();
}
}
@@ -364,7 +369,7 @@ public class HighlightMethodUtil {
highlightInfo = GenericsHighlightUtil.checkInferredTypeArguments(resolvedMethod, methodCall, substitutor);
}
else {
- highlightInfo = GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, methodExpression, substitutor);
+ highlightInfo = GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, methodExpression, substitutor, javaSdkVersion);
}
}
}
@@ -384,7 +389,8 @@ public class HighlightMethodUtil {
}
}
if (highlightInfo == null) {
- highlightInfo = GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, referenceToMethod, substitutor);
+ highlightInfo = GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, referenceToMethod, substitutor,
+ javaSdkVersion);
}
return highlightInfo;
}
@@ -860,7 +866,7 @@ public class HighlightMethodUtil {
}
@Nullable
- static HighlightInfo checkMethodCanHaveBody(PsiMethod method) {
+ static HighlightInfo checkMethodCanHaveBody(PsiMethod method, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
PsiClass aClass = method.getContainingClass();
boolean hasNoBody = method.getBody() == null;
boolean isInterface = aClass != null && aClass.isInterface();
@@ -887,7 +893,7 @@ public class HighlightMethodUtil {
}
}
else if (isExtension) {
- return HighlightUtil.checkExtensionMethodsFeature(method);
+ return HighlightUtil.checkExtensionMethodsFeature(method, languageLevel,containingFile);
}
}
else if (isExtension) {
@@ -983,7 +989,7 @@ public class HighlightMethodUtil {
* @return error if static method overrides instance method or
* instance method overrides static. see JLS 8.4.6.1, 8.4.6.2
*/
- static HighlightInfo checkStaticMethodOverride(PsiMethod method) {
+ static HighlightInfo checkStaticMethodOverride(@NotNull PsiMethod method,@NotNull PsiFile containingFile) {
// constructors are not members and therefor don't override class methods
if (method.isConstructor()) {
return null;
@@ -997,7 +1003,7 @@ public class HighlightMethodUtil {
: MethodSignatureUtil.findMethodBySignature(superClass, method, true);
boolean isStatic = method.hasModifierProperty(PsiModifier.STATIC);
- HighlightInfo highlightInfo = checkStaticMethodOverride(aClass, method, isStatic,superClass, superMethod);
+ HighlightInfo highlightInfo = checkStaticMethodOverride(aClass, method, isStatic,superClass, superMethod,containingFile);
if (highlightInfo != null) return highlightInfo;
if (!isStatic) {
// all methods in interface are instance, so no possible errors in this case
@@ -1007,15 +1013,15 @@ public class HighlightMethodUtil {
for (PsiClass aInterfaces : interfaces) {
superClass = aInterfaces;
superMethod = MethodSignatureUtil.findMethodInSuperClassBySignatureInDerived(aClass, superClass, method.getSignature(PsiSubstitutor.EMPTY), true);
- highlightInfo = checkStaticMethodOverride(aClass, method, true, superClass, superMethod);
+ highlightInfo = checkStaticMethodOverride(aClass, method, true, superClass, superMethod,containingFile);
if (highlightInfo != null) return highlightInfo;
}
return null;
}
- private static HighlightInfo checkStaticMethodOverride(PsiClass aClass, PsiMethod method, boolean isMethodStatic, PsiClass superClass, PsiMethod superMethod) {
+ private static HighlightInfo checkStaticMethodOverride(PsiClass aClass, PsiMethod method, boolean isMethodStatic, PsiClass superClass, PsiMethod superMethod,@NotNull PsiFile containingFile) {
if (superMethod == null) return null;
- PsiManager manager = superMethod.getManager();
+ PsiManager manager = containingFile.getManager();
PsiModifierList superModifierList = superMethod.getModifierList();
PsiModifierList modifierList = method.getModifierList();
if (superModifierList.hasModifierProperty(PsiModifier.PRIVATE)) return null;
@@ -1208,7 +1214,7 @@ public class HighlightMethodUtil {
}
- static void checkNewExpression(@NotNull PsiNewExpression expression, @NotNull HighlightInfoHolder holder) {
+ static void checkNewExpression(@NotNull PsiNewExpression expression, @NotNull HighlightInfoHolder holder, @NotNull JavaSdkVersion javaSdkVersion) {
PsiType type = expression.getType();
if (!(type instanceof PsiClassType)) return;
PsiClassType.ClassResolveResult typeResult = ((PsiClassType)type).resolveGenerics();
@@ -1222,15 +1228,16 @@ public class HighlightMethodUtil {
}
PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
- checkConstructorCall(typeResult, expression, type, classReference, holder);
+ checkConstructorCall(typeResult, expression, type, classReference, holder, javaSdkVersion);
}
public static void checkConstructorCall(PsiClassType.ClassResolveResult typeResolveResult,
- PsiConstructorCall constructorCall,
- PsiType type,
- PsiJavaCodeReferenceElement classReference,
- final HighlightInfoHolder holder) {
+ PsiConstructorCall constructorCall,
+ PsiType type,
+ PsiJavaCodeReferenceElement classReference,
+ final HighlightInfoHolder holder,
+ @NotNull JavaSdkVersion javaSdkVersion) {
PsiExpressionList list = constructorCall.getArgumentList();
if (list == null) return;
PsiClass aClass = typeResolveResult.getElement();
@@ -1343,12 +1350,10 @@ public class HighlightMethodUtil {
}
else {
if (constructorCall instanceof PsiNewExpression) {
- HighlightInfo highlightInfo = GenericsHighlightUtil.checkReferenceTypeArgumentList(constructor,
- ((PsiNewExpression)constructorCall)
- .getTypeArgumentList(),
- result.getSubstitutor(), false);
- if (highlightInfo != null) {
- holder.add(highlightInfo);
+ PsiReferenceParameterList typeArgumentList = ((PsiNewExpression)constructorCall).getTypeArgumentList();
+ HighlightInfo info = GenericsHighlightUtil.checkReferenceTypeArgumentList(constructor, typeArgumentList, result.getSubstitutor(), false, javaSdkVersion);
+ if (info != null) {
+ holder.add(info);
}
}
}
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 dc8aaa969930..a8c041e4e829 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
@@ -28,6 +28,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.editor.colors.TextAttributesScheme;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
@@ -51,14 +52,14 @@ public class HighlightNamesUtil {
public static HighlightInfo highlightMethodName(@NotNull PsiMethod method,
final PsiElement elementToHighlight,
final boolean isDeclaration,
- @NotNull EditorColorsScheme colorsScheme) {
+ @NotNull TextAttributesScheme 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) {
+ TextRange range, @NotNull TextAttributesScheme colorsScheme, final boolean isDeclaration) {
boolean isInherited = false;
if (!isDeclaration) {
@@ -93,7 +94,7 @@ public class HighlightNamesUtil {
private static TextAttributes mergeWithScopeAttributes(final PsiElement element,
@NotNull HighlightInfoType type,
- @NotNull EditorColorsScheme colorsScheme) {
+ @NotNull TextAttributesScheme colorsScheme) {
TextAttributes regularAttributes = HighlightInfo.getAttributesByType(element, type, colorsScheme);
if (element == null) return regularAttributes;
TextAttributes scopeAttributes = getScopeAttributes(element, colorsScheme);
@@ -101,7 +102,7 @@ public class HighlightNamesUtil {
}
@Nullable
- public static HighlightInfo highlightClassName(PsiClass aClass, PsiElement elementToHighlight, @NotNull EditorColorsScheme colorsScheme) {
+ public static HighlightInfo highlightClassName(PsiClass aClass, PsiElement elementToHighlight, @NotNull TextAttributesScheme colorsScheme) {
HighlightInfoType type = getClassNameHighlightType(aClass, elementToHighlight);
if (elementToHighlight != null) {
TextAttributes attributes = mergeWithScopeAttributes(aClass, type, colorsScheme);
@@ -136,7 +137,7 @@ public class HighlightNamesUtil {
@Nullable
public static HighlightInfo highlightVariableName(final PsiVariable variable,
final PsiElement elementToHighlight,
- @NotNull EditorColorsScheme colorsScheme) {
+ @NotNull TextAttributesScheme colorsScheme) {
HighlightInfoType varType = getVariableNameHighlightType(variable);
if (varType != null) {
if (variable instanceof PsiField) {
@@ -154,7 +155,7 @@ public class HighlightNamesUtil {
@Nullable
public static HighlightInfo highlightClassNameInQualifier(final PsiJavaCodeReferenceElement element,
- @NotNull EditorColorsScheme colorsScheme) {
+ @NotNull TextAttributesScheme colorsScheme) {
PsiExpression qualifierExpression = null;
if (element instanceof PsiReferenceExpression) {
qualifierExpression = ((PsiReferenceExpression)element).getQualifierExpression();
@@ -228,7 +229,7 @@ public class HighlightNamesUtil {
return null;
}
- private static TextAttributes getScopeAttributes(@NotNull PsiElement element, @NotNull EditorColorsScheme colorsScheme) {
+ private static TextAttributes getScopeAttributes(@NotNull PsiElement element, @NotNull TextAttributesScheme colorsScheme) {
PsiFile file = element.getContainingFile();
if (file == null) return null;
TextAttributes result = null;
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 e7b3d6b4bbc9..3181bed81402 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
@@ -34,7 +34,6 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
-import com.intellij.openapi.projectRoots.JavaVersionService;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
@@ -46,7 +45,9 @@ import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
+import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
import com.intellij.psi.impl.source.tree.java.PsiLiteralExpressionImpl;
+import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.jsp.JspFile;
import com.intellij.psi.scope.processor.VariablesNotProcessor;
@@ -336,7 +337,7 @@ public class HighlightUtil extends HighlightUtilBase {
@Nullable
- static HighlightInfo checkAssignmentOperatorApplicable(@NotNull PsiAssignmentExpression assignment) {
+ static HighlightInfo checkAssignmentOperatorApplicable(@NotNull PsiAssignmentExpression assignment,@NotNull PsiFile containingFile) {
PsiJavaToken operationSign = assignment.getOperationSign();
IElementType eqOpSign = operationSign.getTokenType();
IElementType opSign = TypeConversionUtil.convertEQtoOperation(eqOpSign);
@@ -347,7 +348,7 @@ public class HighlightUtil extends HighlightUtilBase {
final PsiType rType = rExpression.getType();
HighlightInfo errorResult = null;
if (!TypeConversionUtil.isBinaryOperatorApplicable(opSign, lType, rType, true) ||
- PsiType.getJavaLangObject(assignment.getManager(), assignment.getResolveScope()).equals(lType)) {
+ PsiType.getJavaLangObject(containingFile.getManager(), assignment.getResolveScope()).equals(lType)) {
String operatorText = operationSign.getText().substring(0, operationSign.getText().length() - 1);
String message = JavaErrorMessages.message("binary.operator.not.applicable", operatorText,
JavaHighlightUtil.formatType(lType),
@@ -621,6 +622,22 @@ public class HighlightUtil extends HighlightUtilBase {
return null;
}
+ @Nullable
+ public static HighlightInfo checkUnderscore(@NotNull PsiIdentifier identifier, @NotNull PsiVariable variable) {
+ if ("_".equals(variable.getName()) && PsiUtil.isLanguageLevel8OrHigher(variable)) {
+ if (variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiLambdaExpression) {
+ String message = JavaErrorMessages.message("underscore.lambda.identifier");
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(message).create();
+ }
+ else {
+ String message = JavaErrorMessages.message("underscore.identifier");
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(identifier).descriptionAndTooltip(message).create();
+ }
+ }
+
+ return null;
+ }
+
@NotNull
public static String formatClass(@NotNull PsiClass aClass) {
return formatClass(aClass, true);
@@ -845,7 +862,8 @@ public class HighlightUtil extends HighlightUtilBase {
}
@Nullable
- public static HighlightInfo checkLiteralExpressionParsingError(@NotNull final PsiLiteralExpression expression) {
+ public static HighlightInfo checkLiteralExpressionParsingError(@NotNull final PsiLiteralExpression expression,
+ @NotNull LanguageLevel languageLevel, @NotNull PsiFile containingFile) {
PsiElement literal = expression.getFirstChild();
assert literal instanceof PsiJavaToken : literal;
IElementType type = ((PsiJavaToken)literal).getTokenType();
@@ -860,19 +878,19 @@ public class HighlightUtil extends HighlightUtilBase {
if (isFP) {
if (text.startsWith(PsiLiteralExpressionImpl.HEX_PREFIX)) {
- final HighlightInfo info = checkFeature(expression, Feature.HEX_FP_LITERALS);
+ final HighlightInfo info = checkFeature(expression, Feature.HEX_FP_LITERALS, languageLevel, containingFile);
if (info != null) return info;
}
}
if (isInt) {
if (text.startsWith(PsiLiteralExpressionImpl.BIN_PREFIX)) {
- final HighlightInfo info = checkFeature(expression, Feature.BIN_LITERALS);
+ final HighlightInfo info = checkFeature(expression, Feature.BIN_LITERALS, languageLevel, containingFile);
if (info != null) return info;
}
}
if (isInt || isFP) {
if (text.contains("_")) {
- HighlightInfo info = checkFeature(expression, Feature.UNDERSCORES);
+ HighlightInfo info = checkFeature(expression, Feature.UNDERSCORES, languageLevel, containingFile);
if (info != null) return info;
info = checkUnderscores(expression, text, isInt);
if (info != null) return info;
@@ -1176,7 +1194,7 @@ public class HighlightUtil extends HighlightUtilBase {
@Nullable
static Collection<HighlightInfo> checkWithImprovedCatchAnalysis(@NotNull final PsiParameter parameter,
- @NotNull final Collection<PsiClassType> thrownInTryStatement) {
+ @NotNull final Collection<PsiClassType> thrownInTryStatement,@NotNull PsiFile containingFile) {
final PsiElement scope = parameter.getDeclarationScope();
if (!(scope instanceof PsiCatchSection)) return null;
@@ -1186,8 +1204,10 @@ public class HighlightUtil extends HighlightUtilBase {
if (idx <= 0) return null;
final Collection<PsiClassType> thrownTypes = ContainerUtil.newHashSet(thrownInTryStatement);
- thrownTypes.add(PsiType.getJavaLangError(parameter.getManager(), parameter.getResolveScope()));
- thrownTypes.add(PsiType.getJavaLangRuntimeException(parameter.getManager(), parameter.getResolveScope()));
+ PsiManager manager = containingFile.getManager();
+ GlobalSearchScope parameterResolveScope = parameter.getResolveScope();
+ thrownTypes.add(PsiType.getJavaLangError(manager, parameterResolveScope));
+ thrownTypes.add(PsiType.getJavaLangRuntimeException(manager, parameterResolveScope));
final Collection<HighlightInfo> result = ContainerUtil.newArrayList();
final List<PsiTypeElement> parameterTypeElements = PsiUtil.getParameterTypeElements(parameter);
@@ -1805,7 +1825,9 @@ public class HighlightUtil extends HighlightUtilBase {
}
@Nullable
- public static HighlightInfo checkMemberReferencedBeforeConstructorCalled(@NotNull PsiElement expression, PsiElement resolved) {
+ public static HighlightInfo checkMemberReferencedBeforeConstructorCalled(@NotNull PsiElement expression,
+ PsiElement resolved,
+ @NotNull PsiFile containingFile) {
PsiClass referencedClass;
@NonNls String resolvedName;
PsiType type;
@@ -1903,13 +1925,14 @@ public class HighlightUtil extends HighlightUtilBase {
return null;
}
if (referencedClass == null) return null;
- return checkReferenceToOurInstanceInsideThisOrSuper(expression, referencedClass, resolvedName);
+ return checkReferenceToOurInstanceInsideThisOrSuper(expression, referencedClass, resolvedName, containingFile);
}
@Nullable
private static HighlightInfo checkReferenceToOurInstanceInsideThisOrSuper(@NotNull final PsiElement expression,
@NotNull PsiClass referencedClass,
- final String resolvedName) {
+ final String resolvedName,
+ @NotNull PsiFile containingFile) {
if (PsiTreeUtil.getParentOfType(expression, PsiReferenceParameterList.class) != null) return null;
PsiElement element = expression.getParent();
while (element != null) {
@@ -1919,7 +1942,7 @@ public class HighlightUtil extends HighlightUtilBase {
.parent(PsiMatchers.hasClass(PsiExpressionStatement.class))
.parent(PsiMatchers.hasClass(PsiCodeBlock.class))
.parent(PsiMatchers.hasClass(PsiMethod.class))
- .dot(PsiMatchers.isConstructor(true))
+ .dot(JavaMatchers.isConstructor(true))
.parent(PsiMatchers.hasClass(PsiClass.class))
.getElement();
if (parentClass == null) {
@@ -1958,7 +1981,16 @@ public class HighlightUtil extends HighlightUtilBase {
}
if (element instanceof PsiReferenceExpression) {
- final PsiElement resolve = ((PsiReferenceExpression)element).resolve();
+ final PsiElement resolve;
+ if (element instanceof PsiReferenceExpressionImpl) {
+ PsiReferenceExpressionImpl referenceExpression = (PsiReferenceExpressionImpl)element;
+ JavaResolveResult[] results = JavaResolveUtil
+ .resolveWithContainingFile(referenceExpression, PsiReferenceExpressionImpl.OurGenericsResolver.INSTANCE, true, false, containingFile);
+ resolve = results.length == 1 ? results[0].getElement() : null;
+ }
+ else {
+ resolve = ((PsiReferenceExpression)element).resolve();
+ }
if (resolve instanceof PsiField && ((PsiField)resolve).hasModifierProperty(PsiModifier.STATIC)) {
return null;
}
@@ -1976,8 +2008,8 @@ public class HighlightUtil extends HighlightUtilBase {
}
@Nullable
- public static HighlightInfo checkImplicitThisReferenceBeforeSuper(@NotNull PsiClass aClass) {
- if (JavaVersionService.getInstance().isAtLeast(aClass, JavaSdkVersion.JDK_1_7)) return null;
+ public static HighlightInfo checkImplicitThisReferenceBeforeSuper(@NotNull PsiClass aClass, @NotNull JavaSdkVersion javaSdkVersion) {
+ if (javaSdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7)) return null;
if (aClass instanceof PsiAnonymousClass || aClass instanceof PsiTypeParameter) return null;
PsiClass superClass = aClass.getSuperClass();
if (superClass == null || !PsiUtil.isInnerClass(superClass)) return null;
@@ -2205,13 +2237,13 @@ public class HighlightUtil extends HighlightUtilBase {
@Nullable
- public static HighlightInfo checkSynchronizedExpressionType(@NotNull PsiExpression expression, @Nullable PsiType type) {
+ public static HighlightInfo checkSynchronizedExpressionType(@NotNull PsiExpression expression, @Nullable PsiType type,@NotNull PsiFile containingFile) {
if (type == null) return null;
if (expression.getParent() instanceof PsiSynchronizedStatement) {
PsiSynchronizedStatement synchronizedStatement = (PsiSynchronizedStatement)expression.getParent();
if (expression == synchronizedStatement.getLockExpression() &&
(type instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(type))) {
- PsiClassType objectType = PsiType.getJavaLangObject(expression.getManager(), expression.getResolveScope());
+ PsiClassType objectType = PsiType.getJavaLangObject(containingFile.getManager(), expression.getResolveScope());
return createIncompatibleTypeHighlightInfo(objectType, type, expression.getTextRange(), 0);
}
}
@@ -2308,14 +2340,14 @@ public class HighlightUtil extends HighlightUtilBase {
@Nullable
public static HighlightInfo checkSingleImportClassConflict(@NotNull PsiImportStatement statement,
- @NotNull Map<String, Pair<PsiImportStaticReferenceElement, PsiClass>> importedClasses) {
+ @NotNull Map<String, Pair<PsiImportStaticReferenceElement, PsiClass>> importedClasses,@NotNull PsiFile containingFile) {
if (statement.isOnDemand()) return null;
PsiElement element = statement.resolve();
if (element instanceof PsiClass) {
String name = ((PsiClass)element).getName();
Pair<PsiImportStaticReferenceElement, PsiClass> imported = importedClasses.get(name);
PsiClass importedClass = imported == null ? null : imported.getSecond();
- if (importedClass != null && !element.getManager().areElementsEquivalent(importedClass, element)) {
+ if (importedClass != null && !containingFile.getManager().areElementsEquivalent(importedClass, element)) {
String description = JavaErrorMessages.message("single.import.class.conflict", formatClass(importedClass));
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(description).create();
}
@@ -2378,13 +2410,16 @@ public class HighlightUtil extends HighlightUtilBase {
@Nullable
- static HighlightInfo checkReference(@NotNull final PsiJavaCodeReferenceElement ref, @NotNull final JavaResolveResult result) {
+ static HighlightInfo checkReference(@NotNull final PsiJavaCodeReferenceElement ref,
+ @NotNull final JavaResolveResult result,
+ @NotNull PsiFile containingFile,
+ @NotNull LanguageLevel languageLevel) {
final PsiElement refName = ref.getReferenceNameElement();
if (!(refName instanceof PsiIdentifier) && !(refName instanceof PsiKeyword)) return null;
final PsiElement resolved = result.getElement();
- HighlightInfo highlightInfo = checkMemberReferencedBeforeConstructorCalled(ref, resolved);
+ HighlightInfo highlightInfo = checkMemberReferencedBeforeConstructorCalled(ref, resolved, containingFile);
if (highlightInfo != null) return highlightInfo;
PsiElement refParent = ref.getParent();
@@ -2454,7 +2489,8 @@ public class HighlightUtil extends HighlightUtilBase {
}
}
if ((resolved instanceof PsiLocalVariable || resolved instanceof PsiParameter) && !(resolved instanceof ImplicitVariable)) {
- highlightInfo = HighlightControlFlowUtil.checkVariableMustBeFinal((PsiVariable)resolved, ref);
+ highlightInfo = HighlightControlFlowUtil.checkVariableMustBeFinal((PsiVariable)resolved, ref,
+ languageLevel);
}
else if (resolved instanceof PsiClass) {
if (Comparing.strEqual(((PsiClass)resolved).getQualifiedName(), ((PsiClass)resolved).getName())) {
@@ -2508,7 +2544,8 @@ public class HighlightUtil extends HighlightUtilBase {
@Nullable
static HighlightInfo checkElementInReferenceList(@NotNull PsiJavaCodeReferenceElement ref,
@NotNull PsiReferenceList referenceList,
- @NotNull JavaResolveResult resolveResult) {
+ @NotNull JavaResolveResult resolveResult,
+ @NotNull LanguageLevel languageLevel) {
PsiElement resolved = resolveResult.getElement();
HighlightInfo highlightInfo = null;
PsiElement refGrandParent = referenceList.getParent();
@@ -2516,7 +2553,7 @@ public class HighlightUtil extends HighlightUtilBase {
PsiClass aClass = (PsiClass)resolved;
if (refGrandParent instanceof PsiClass) {
if (refGrandParent instanceof PsiTypeParameter) {
- highlightInfo = GenericsHighlightUtil.checkElementInTypeParameterExtendsList(referenceList, (PsiClass)refGrandParent, resolveResult, ref);
+ highlightInfo = GenericsHighlightUtil.checkElementInTypeParameterExtendsList(referenceList, (PsiClass)refGrandParent, resolveResult, ref, languageLevel);
}
else {
highlightInfo = HighlightClassUtil.checkExtendsClassAndImplementsInterface(referenceList, resolveResult, ref);
@@ -2630,8 +2667,11 @@ 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)) {
+ private static HighlightInfo checkFeature(@NotNull final PsiElement element,
+ @NotNull Feature feature,
+ @NotNull LanguageLevel languageLevel,
+ @NotNull PsiFile containingFile) {
+ if (containingFile.getManager().isInProject(containingFile) && !languageLevel.isAtLeast(feature.level)) {
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));
@@ -2643,62 +2683,69 @@ public class HighlightUtil extends HighlightUtilBase {
}
@Nullable
- public static HighlightInfo checkGenericsFeature(PsiElement parameterList, int listSize) {
- return listSize > 0 ? checkFeature(parameterList, Feature.GENERICS) : null;
+ public static HighlightInfo checkGenericsFeature(@NotNull PsiElement parameterList,
+ int listSize,
+ @NotNull LanguageLevel languageLevel,
+ @NotNull PsiFile containingFile) {
+ return listSize > 0 ? checkFeature(parameterList, Feature.GENERICS, languageLevel, containingFile) : null;
}
@Nullable
- public static HighlightInfo checkAnnotationFeature(PsiElement element) {
- return checkFeature(element, Feature.ANNOTATIONS);
+ public static HighlightInfo checkAnnotationFeature(@NotNull PsiElement element,
+ @NotNull LanguageLevel languageLevel,
+ @NotNull PsiFile containingFile) {
+ return checkFeature(element, Feature.ANNOTATIONS, languageLevel, containingFile);
}
@Nullable
- public static HighlightInfo checkForEachFeature(PsiForeachStatement statement) {
- return checkFeature(statement, Feature.FOR_EACH);
+ public static HighlightInfo checkForEachFeature(@NotNull PsiForeachStatement statement, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+ return checkFeature(statement, Feature.FOR_EACH, languageLevel, containingFile);
}
@Nullable
- public static HighlightInfo checkStaticImportFeature(PsiImportStaticStatement statement) {
- return checkFeature(statement, Feature.STATIC_IMPORTS);
+ public static HighlightInfo checkStaticImportFeature(@NotNull PsiImportStaticStatement statement, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+ return checkFeature(statement, Feature.STATIC_IMPORTS, languageLevel, containingFile);
}
@Nullable
- public static HighlightInfo checkVarargFeature(PsiParameter parameter) {
- return checkFeature(parameter, Feature.VARARGS);
+ public static HighlightInfo checkVarargFeature(@NotNull PsiParameter parameter, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+ return checkFeature(parameter, Feature.VARARGS, languageLevel, containingFile);
}
@Nullable
- public static HighlightInfo checkDiamondFeature(PsiTypeElement typeElement) {
- return typeElement.getType() instanceof PsiDiamondType ? checkFeature(typeElement.getParent(), Feature.DIAMOND_TYPES) : null;
+ public static HighlightInfo checkDiamondFeature(@NotNull PsiTypeElement typeElement, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+ return typeElement.getType() instanceof PsiDiamondType ? checkFeature(typeElement.getParent(), Feature.DIAMOND_TYPES,
+ languageLevel, containingFile) : null;
}
@Nullable
- public static HighlightInfo checkMultiCatchFeature(PsiParameter parameter) {
- return parameter.getType() instanceof PsiDisjunctionType ? checkFeature(parameter, Feature.MULTI_CATCH) : null;
+ public static HighlightInfo checkMultiCatchFeature(@NotNull PsiParameter parameter, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+ return parameter.getType() instanceof PsiDisjunctionType ? checkFeature(parameter, Feature.MULTI_CATCH,
+ languageLevel, containingFile) : null;
}
@Nullable
- public static HighlightInfo checkTryWithResourcesFeature(PsiResourceVariable resourceVariable) {
- return checkFeature(resourceVariable.getParent(), Feature.TRY_WITH_RESOURCES);
+ public static HighlightInfo checkTryWithResourcesFeature(@NotNull PsiResourceVariable resourceVariable, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+ return checkFeature(resourceVariable.getParent(), Feature.TRY_WITH_RESOURCES, languageLevel, containingFile);
}
@Nullable
- public static HighlightInfo checkExtensionMethodsFeature(PsiMethod method) {
- return checkFeature(method, Feature.EXTENSION_METHODS);
+ public static HighlightInfo checkExtensionMethodsFeature(@NotNull PsiMethod method, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+ return checkFeature(method, Feature.EXTENSION_METHODS, languageLevel, containingFile);
}
@Nullable
- public static HighlightInfo checkMethodReferencesFeature(PsiMethodReferenceExpression expression) {
- return checkFeature(expression, Feature.METHOD_REFERENCES);
+ public static HighlightInfo checkMethodReferencesFeature(@NotNull PsiMethodReferenceExpression expression, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+ return checkFeature(expression, Feature.METHOD_REFERENCES, languageLevel, containingFile);
}
@Nullable
- public static HighlightInfo checkLambdaFeature(PsiLambdaExpression expression) {
- return checkFeature(expression, Feature.LAMBDA_EXPRESSIONS);
+ public static HighlightInfo checkLambdaFeature(@NotNull PsiLambdaExpression expression, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+ return checkFeature(expression, Feature.LAMBDA_EXPRESSIONS, languageLevel, containingFile);
}
@Nullable
- public static HighlightInfo checkTypeAnnotationFeature(PsiAnnotation annotation) {
- return checkFeature(annotation, Feature.TYPE_ANNOTATIONS);
+ public static HighlightInfo checkTypeAnnotationFeature(@NotNull PsiAnnotation annotation, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+ return checkFeature(annotation, Feature.TYPE_ANNOTATIONS, languageLevel, containingFile);
}
}
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 c705951fe395..4b8075da2503 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
@@ -23,24 +23,28 @@ import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
import com.intellij.codeInsight.daemon.impl.quickfix.SetupJDKFix;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.editor.colors.TextAttributesScheme;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
-import com.intellij.openapi.projectRoots.JavaVersionService;
+import com.intellij.openapi.projectRoots.JavaSdkVersionUtil;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
+import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.controlFlow.ControlFlowUtil;
import com.intellij.psi.impl.source.javadoc.PsiDocMethodOrFieldRef;
import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
+import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
+import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTagValue;
import com.intellij.psi.util.*;
import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.MostlySingularMultiMap;
import gnu.trove.THashMap;
import gnu.trove.TObjectIntHashMap;
@@ -81,6 +85,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
};
private final Map<PsiClass, MostlySingularMultiMap<MethodSignature, PsiMethod>> myDuplicateMethods = new THashMap<PsiClass, MostlySingularMultiMap<MethodSignature, PsiMethod>>();
+ private LanguageLevel myLanguageLevel;
+ private JavaSdkVersion myJavaSdkVersion;
public HighlightVisitorImpl(@NotNull PsiResolveHelper resolveHelper) {
myResolveHelper = resolveHelper;
@@ -92,6 +98,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (signatures == null) {
signatures = new MostlySingularMultiMap<MethodSignature, PsiMethod>();
for (PsiMethod method : aClass.getMethods()) {
+ if (method instanceof ExternallyDefinedPsiElement) continue; // ignore aspectj-weaved methods; they are checked elsewhere
MethodSignature signature = method.getSignature(PsiSubstitutor.EMPTY);
signatures.add(signature, method);
}
@@ -140,6 +147,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
myHolder = holder;
boolean success = true;
try {
+ myLanguageLevel = PsiUtil.getLanguageLevel(file);
+ myJavaSdkVersion = ObjectUtils.notNull(JavaSdkVersionUtil.getJavaSdkVersion(file), JavaSdkVersion.fromLanguageLevel(myLanguageLevel));
if (updateWholeFile) {
Project project = file.getProject();
DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(project);
@@ -192,14 +201,14 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitAnnotation(PsiAnnotation annotation) {
super.visitAnnotation(annotation);
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAnnotationFeature(annotation));
- if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkApplicability(annotation));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAnnotationFeature(annotation, myLanguageLevel, myFile));
+ if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkApplicability(annotation, myLanguageLevel,myFile));
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkAnnotationType(annotation));
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkMissingAttributes(annotation));
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkTargetAnnotationDuplicates(annotation));
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkDuplicateAnnotations(annotation));
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkForeignInnerClassesUsed(annotation));
- if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkFunctionalInterface(annotation));
+ if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkFunctionalInterface(annotation, myLanguageLevel));
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkRepeatableAnnotation(annotation));
}
@@ -225,7 +234,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
- @Override public void visitAnnotationMethod(PsiAnnotationMethod method) {
+ @Override
+ public void visitAnnotationMethod(PsiAnnotationMethod method) {
PsiType returnType = method.getReturnType();
PsiAnnotationMemberValue value = method.getDefaultValue();
if (returnType != null && value != null) {
@@ -237,7 +247,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
myHolder.add(AnnotationsHighlightUtil.checkClashesWithSuperMethods(method));
}
- @Override public void visitArrayInitializerExpression(PsiArrayInitializerExpression expression) {
+ @Override
+ public void visitArrayInitializerExpression(PsiArrayInitializerExpression expression) {
super.visitArrayInitializerExpression(expression);
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkArrayInitializerApplicable(expression));
if (!(expression.getParent() instanceof PsiNewExpression)) {
@@ -245,9 +256,10 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
- @Override public void visitAssignmentExpression(PsiAssignmentExpression assignment) {
+ @Override
+ public void visitAssignmentExpression(PsiAssignmentExpression assignment) {
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentCompatibleTypes(assignment));
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentOperatorApplicable(assignment));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentOperatorApplicable(assignment,myFile));
if (!myHolder.hasErrorResults()) visitExpression(assignment);
}
@@ -259,7 +271,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitLambdaExpression(PsiLambdaExpression expression) {
- myHolder.add(HighlightUtil.checkLambdaFeature(expression));
+ myHolder.add(HighlightUtil.checkLambdaFeature(expression, myLanguageLevel,myFile));
if (!myHolder.hasErrorResults()) {
if (LambdaUtil.isValidLambdaContext(expression.getParent())) {
final PsiType functionalInterfaceType = expression.getFunctionalInterfaceType();
@@ -354,11 +366,12 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkInterfaceMultipleInheritance(aClass));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkDuplicateTopLevelClass(aClass));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumMustNotBeLocal(aClass));
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkImplicitThisReferenceBeforeSuper(aClass));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkImplicitThisReferenceBeforeSuper(aClass, myJavaSdkVersion));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassAndPackageConflict(aClass));
}
- @Override public void visitClassInitializer(PsiClassInitializer initializer) {
+ @Override
+ public void visitClassInitializer(PsiClassInitializer initializer) {
super.visitClassInitializer(initializer);
if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkInitializerCompleteNormally(initializer));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkUnreachableStatement(initializer.getBody()));
@@ -367,25 +380,29 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
- @Override public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
+ @Override
+ public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
super.visitClassObjectAccessExpression(expression);
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkClassObjectAccessExpression(expression));
}
- @Override public void visitComment(PsiComment comment) {
+ @Override
+ public void visitComment(PsiComment comment) {
super.visitComment(comment);
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnclosedComment(comment));
if (myRefCountHolder != null && !myHolder.hasErrorResults()) registerReferencesFromInjectedFragments(comment);
}
- @Override public void visitContinueStatement(PsiContinueStatement statement) {
+ @Override
+ public void visitContinueStatement(PsiContinueStatement statement) {
super.visitContinueStatement(statement);
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightUtil.checkLabelDefined(statement.getLabelIdentifier(), statement.findContinuedStatement()));
}
}
- @Override public void visitJavaToken(PsiJavaToken token) {
+ @Override
+ public void visitJavaToken(PsiJavaToken token) {
super.visitJavaToken(token);
if (!myHolder.hasErrorResults()
&& token.getTokenType() == JavaTokenType.RBRACE
@@ -398,28 +415,31 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
PsiMethod method = (PsiMethod)gParent;
codeBlock = method.getBody();
returnType = method.getReturnType();
- } else if (gParent instanceof PsiLambdaExpression) {
+ }
+ else if (gParent instanceof PsiLambdaExpression) {
final PsiElement body = ((PsiLambdaExpression)gParent).getBody();
if (!(body instanceof PsiCodeBlock)) return;
codeBlock = (PsiCodeBlock)body;
returnType = LambdaUtil.getFunctionalInterfaceReturnType((PsiLambdaExpression)gParent);
- } else {
+ }
+ else {
return;
}
myHolder.add(HighlightControlFlowUtil.checkMissingReturnStatement(codeBlock, returnType));
}
-
}
- @Override public void visitDocComment(PsiDocComment comment) {
+ @Override
+ public void visitDocComment(PsiDocComment comment) {
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnclosedComment(comment));
}
- @Override public void visitDocTagValue(PsiDocTagValue value) {
+ @Override
+ public void visitDocTagValue(PsiDocTagValue value) {
PsiReference reference = value.getReference();
if (reference != null) {
PsiElement element = reference.resolve();
- final EditorColorsScheme colorsScheme = myHolder.getColorsScheme();
+ final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
if (element instanceof PsiMethod) {
myHolder.add(HighlightNamesUtil.highlightMethodName((PsiMethod)element, ((PsiDocMethodOrFieldRef)value).getNameElement(), false,
colorsScheme));
@@ -430,13 +450,15 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
- @Override public void visitEnumConstant(PsiEnumConstant enumConstant) {
+ @Override
+ public void visitEnumConstant(PsiEnumConstant enumConstant) {
super.visitEnumConstant(enumConstant);
- if (!myHolder.hasErrorResults()) GenericsHighlightUtil.checkEnumConstantForConstructorProblems(enumConstant, myHolder);
+ if (!myHolder.hasErrorResults()) GenericsHighlightUtil.checkEnumConstantForConstructorProblems(enumConstant, myHolder, myJavaSdkVersion);
if (!myHolder.hasErrorResults()) registerConstructorCall(enumConstant);
}
- @Override public void visitEnumConstantInitializer(PsiEnumConstantInitializer enumConstantInitializer) {
+ @Override
+ public void visitEnumConstantInitializer(PsiEnumConstantInitializer enumConstantInitializer) {
super.visitEnumConstantInitializer(enumConstantInitializer);
if (!myHolder.hasErrorResults()) {
TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(enumConstantInitializer);
@@ -444,29 +466,30 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
- @Override public void visitExpression(PsiExpression expression) {
+ @Override
+ public void visitExpression(PsiExpression expression) {
ProgressManager.checkCanceled(); // visitLiteralExpression is invoked very often in array initializers
super.visitExpression(expression);
PsiType type = expression.getType();
if (myHolder.add(HighlightUtil.checkMustBeBoolean(expression, type))) return;
- if(expression instanceof PsiArrayAccessExpression) {
+ if (expression instanceof PsiArrayAccessExpression) {
myHolder.add(HighlightUtil.checkValidArrayAccessExpression((PsiArrayAccessExpression)expression));
}
if (expression.getParent() instanceof PsiNewExpression
- && ((PsiNewExpression)expression.getParent()).getQualifier() != expression
- && ((PsiNewExpression)expression.getParent()).getArrayInitializer() != expression) {
+ && ((PsiNewExpression)expression.getParent()).getQualifier() != expression
+ && ((PsiNewExpression)expression.getParent()).getArrayInitializer() != expression) {
// like in 'new String["s"]'
myHolder.add(HighlightUtil.checkAssignability(PsiType.INT, expression.getType(), expression, expression));
}
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkCannotWriteToFinal(expression));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkCannotWriteToFinal(expression,myFile));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkVariableExpected(expression));
if (!myHolder.hasErrorResults()) myHolder.addAll(HighlightUtil.checkArrayInitializer(expression, type));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTernaryOperatorConditionIsBoolean(expression, type));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssertOperatorTypes(expression, type));
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSynchronizedExpressionType(expression, type));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSynchronizedExpressionType(expression, type,myFile));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkConditionalExpressionBranchTypesMatch(expression, type));
if (!myHolder.hasErrorResults()
&& expression.getParent() instanceof PsiThrowStatement
@@ -492,18 +515,19 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitForeachStatement(final PsiForeachStatement statement) {
- myHolder.add(HighlightUtil.checkForEachFeature(statement));
+ myHolder.add(HighlightUtil.checkForEachFeature(statement, myLanguageLevel, myFile));
}
@Override
public void visitImportStaticStatement(final PsiImportStaticStatement statement) {
- myHolder.add(HighlightUtil.checkStaticImportFeature(statement));
+ myHolder.add(HighlightUtil.checkStaticImportFeature(statement, myLanguageLevel, myFile));
}
@Override
public void visitIdentifier(final PsiIdentifier identifier) {
+ TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
+
PsiElement parent = identifier.getParent();
- final EditorColorsScheme colorsScheme = myHolder.getColorsScheme();
if (parent instanceof PsiVariable) {
PsiVariable variable = (PsiVariable)parent;
myHolder.add(HighlightUtil.checkVariableAlreadyDefined(variable));
@@ -512,6 +536,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
final PsiElement child = variable.getLastChild();
if (child instanceof PsiErrorElement && child.getPrevSibling() == identifier) return;
}
+
boolean isMethodParameter = variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiMethod;
if (!isMethodParameter) { // method params are highlighted in visitMethod since we should make sure the method body was visited before
if (HighlightControlFlowUtil.isReassigned(variable, myFinalVarProblems)) {
@@ -524,11 +549,13 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
else {
myReassignedParameters.put((PsiParameter)variable, 1); // mark param as present in current file
}
+
+ myHolder.add(HighlightUtil.checkUnderscore(identifier, variable));
}
else if (parent instanceof PsiClass) {
PsiClass aClass = (PsiClass)parent;
if (aClass.isAnnotationType()) {
- myHolder.add(HighlightUtil.checkAnnotationFeature(identifier));
+ myHolder.add(HighlightUtil.checkAnnotationFeature(identifier, myLanguageLevel, myFile));
}
myHolder.add(HighlightClassUtil.checkClassAlreadyImported(aClass, identifier));
@@ -546,6 +573,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
else {
visitParentReference(parent);
}
+
super.visitIdentifier(identifier);
}
@@ -560,7 +588,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
catch (IndexNotReadyException e) {
return;
}
- myHolder.add(HighlightUtil.checkReference(ref, result));
+ myHolder.add(HighlightUtil.checkReference(ref, result, myFile, myLanguageLevel));
if (myRefCountHolder != null) {
myRefCountHolder.registerReference(ref, result);
}
@@ -570,7 +598,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitImportStatement(final PsiImportStatement statement) {
if (!myHolder.hasErrorResults()) {
- myHolder.add(HighlightUtil.checkSingleImportClassConflict(statement, mySingleImportedClasses));
+ myHolder.add(HighlightUtil.checkSingleImportClassConflict(statement, mySingleImportedClasses,myFile));
}
}
@@ -624,13 +652,15 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
- @Override public void visitInstanceOfExpression(PsiInstanceOfExpression expression) {
+ @Override
+ public void visitInstanceOfExpression(PsiInstanceOfExpression expression) {
super.visitInstanceOfExpression(expression);
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkInstanceOfApplicable(expression));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkInstanceOfGenericType(expression));
}
- @Override public void visitKeyword(PsiKeyword keyword) {
+ @Override
+ public void visitKeyword(PsiKeyword keyword) {
super.visitKeyword(keyword);
PsiElement parent = keyword.getParent();
String text = keyword.getText();
@@ -668,25 +698,28 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
- @Override public void visitLabeledStatement(PsiLabeledStatement statement) {
+ @Override
+ public void visitLabeledStatement(PsiLabeledStatement statement) {
super.visitLabeledStatement(statement);
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkLabelWithoutStatement(statement));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkLabelAlreadyInUse(statement));
}
- @Override public void visitLiteralExpression(PsiLiteralExpression expression) {
+ @Override
+ public void visitLiteralExpression(PsiLiteralExpression expression) {
super.visitLiteralExpression(expression);
if (myHolder.hasErrorResults()) return;
- myHolder.add(HighlightUtil.checkLiteralExpressionParsingError(expression));
+ myHolder.add(HighlightUtil.checkLiteralExpressionParsingError(expression, myLanguageLevel,myFile));
if (myRefCountHolder != null && !myHolder.hasErrorResults()) registerReferencesFromInjectedFragments(expression);
}
- @Override public void visitMethod(PsiMethod method) {
+ @Override
+ public void visitMethod(PsiMethod method) {
super.visitMethod(method);
if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkUnreachableStatement(method.getBody()));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorHandleSuperClassExceptions(method));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkRecursiveConstructorInvocation(method));
- if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkOverrideAnnotation(method));
+ if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkOverrideAnnotation(method, myLanguageLevel));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkSafeVarargsAnnotation(method));
if (!myHolder.hasErrorResults() && method.isConstructor()) {
myHolder.add(HighlightClassUtil.checkThingNotAllowedInInterface(method, method.getContainingClass()));
@@ -694,7 +727,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
// method params are highlighted in visitMethod since we should make sure the method body was visited before
PsiParameter[] parameters = method.getParameterList().getParameters();
- final EditorColorsScheme colorsScheme = myHolder.getColorsScheme();
+ final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
for (PsiParameter parameter : parameters) {
int info = myReassignedParameters.get(parameter);
@@ -713,7 +746,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (parent instanceof PsiReferenceExpression || parent instanceof PsiJavaCodeReferenceElement) {
return;
}
- final EditorColorsScheme colorsScheme = myHolder.getColorsScheme();
+ final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
if (parent instanceof PsiMethodCallExpression) {
PsiMethod method = ((PsiMethodCallExpression)parent).resolveMethod();
PsiElement methodNameElement = element.getReferenceNameElement();
@@ -751,13 +784,14 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
- @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+ @Override
+ public void visitMethodCallExpression(PsiMethodCallExpression expression) {
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumSuperConstructorCall(expression));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkSuperQualifierType(myFile.getProject(), expression));
// in case of JSP synthetic method call, do not check
- if (expression.getMethodExpression().isPhysical() && !myHolder.hasErrorResults()) {
+ if (myFile.isPhysical() && !myHolder.hasErrorResults()) {
try {
- myHolder.add(HighlightMethodUtil.checkMethodCall(expression, myResolveHelper));
+ myHolder.add(HighlightMethodUtil.checkMethodCall(expression, myResolveHelper, myLanguageLevel,myJavaSdkVersion));
}
catch (IndexNotReadyException ignored) {
}
@@ -772,7 +806,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
PsiElement parent = list.getParent();
if (parent instanceof PsiMethod) {
PsiMethod method = (PsiMethod)parent;
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodCanHaveBody(method));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodCanHaveBody(method, myLanguageLevel,myFile));
MethodSignatureBackedByPsiMethod methodSignature = MethodSignatureBackedByPsiMethod.create(method, PsiSubstitutor.EMPTY);
if (!method.isConstructor()) {
try {
@@ -793,7 +827,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodMustHaveBody(method, aClass));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkDuplicateMethod(aClass, method, getDuplicateMethods(aClass)));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallsBaseClassConstructor(method, myRefCountHolder, myResolveHelper));
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkStaticMethodOverride(method));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkStaticMethodOverride(method,myFile));
}
else if (parent instanceof PsiClass) {
PsiClass aClass = (PsiClass)parent;
@@ -818,7 +852,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
- @Override public void visitNameValuePair(PsiNameValuePair pair) {
+ @Override
+ public void visitNameValuePair(PsiNameValuePair pair) {
myHolder.add(AnnotationsHighlightUtil.checkNameValuePair(pair));
if (!myHolder.hasErrorResults()) {
PsiIdentifier nameId = pair.getNameIdentifier();
@@ -829,14 +864,15 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
- @Override public void visitNewExpression(PsiNewExpression expression) {
+ @Override
+ public void visitNewExpression(PsiNewExpression expression) {
myHolder.add(HighlightUtil.checkUnhandledExceptions(expression, null));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkAnonymousInheritFinal(expression));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkQualifiedNew(expression));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCreateInnerClassFromStaticContext(expression));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkTypeParameterInstantiation(expression));
try {
- if (!myHolder.hasErrorResults()) HighlightMethodUtil.checkNewExpression(expression, myHolder);
+ if (!myHolder.hasErrorResults()) HighlightMethodUtil.checkNewExpression(expression, myHolder, myJavaSdkVersion);
}
catch (IndexNotReadyException ignored) {
}
@@ -859,13 +895,14 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
final PsiElement parent = parameter.getParent();
if (parent instanceof PsiParameterList) {
- if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkVarArgParameterIsLast(parameter));
+ if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkVarArgParameterIsLast(parameter,
+ myLanguageLevel,myFile));
}
else if (parent instanceof PsiForeachStatement) {
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkForeachLoopParameterType((PsiForeachStatement)parent));
}
else if (parent instanceof PsiCatchSection) {
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkMultiCatchFeature(parameter));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkMultiCatchFeature(parameter, myLanguageLevel,myFile));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkCatchParameterIsThrowable(parameter));
if (!myHolder.hasErrorResults()) myHolder.addAll(GenericsHighlightUtil.checkCatchParameterIsClass(parameter));
if (!myHolder.hasErrorResults()) myHolder.addAll(HighlightUtil.checkCatchTypeIsDisjoint(parameter));
@@ -878,14 +915,16 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAnnotationMethodParameters(list));
}
- @Override public void visitPostfixExpression(PsiPostfixExpression expression) {
+ @Override
+ public void visitPostfixExpression(PsiPostfixExpression expression) {
super.visitPostfixExpression(expression);
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightUtil.checkUnaryOperatorApplicable(expression.getOperationSign(), expression.getOperand()));
}
}
- @Override public void visitPrefixExpression(PsiPrefixExpression expression) {
+ @Override
+ public void visitPrefixExpression(PsiPrefixExpression expression) {
super.visitPrefixExpression(expression);
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightUtil.checkUnaryOperatorApplicable(expression.getOperationSign(), expression.getOperand()));
@@ -910,7 +949,17 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
private JavaResolveResult doVisitReferenceElement(@NotNull PsiJavaCodeReferenceElement ref) {
JavaResolveResult result;
try {
- result = ref.advancedResolve(true);
+ if (ref instanceof PsiReferenceExpressionImpl) {
+ PsiReferenceExpressionImpl referenceExpression = (PsiReferenceExpressionImpl)ref;
+ JavaResolveResult[] results = JavaResolveUtil.resolveWithContainingFile(referenceExpression,
+ PsiReferenceExpressionImpl.OurGenericsResolver.INSTANCE,
+ true, true,
+ myFile);
+ result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
+ }
+ else {
+ result = ref.advancedResolve(true);
+ }
}
catch (IndexNotReadyException e) {
return null;
@@ -922,9 +971,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (myRefCountHolder != null) {
myRefCountHolder.registerReference(ref, result);
}
- myHolder.add(HighlightUtil.checkReference(ref, result));
+ myHolder.add(HighlightUtil.checkReference(ref, result, myFile, myLanguageLevel));
if (!myHolder.hasErrorResults() && resolved instanceof PsiTypeParameter) {
- boolean cannotSelectFromTypeParameter = !JavaVersionService.getInstance().isAtLeast(ref, JavaSdkVersion.JDK_1_7);
+ boolean cannotSelectFromTypeParameter = !myJavaSdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7);
if (!cannotSelectFromTypeParameter) {
final PsiClass containingClass = PsiTreeUtil.getParentOfType(ref, PsiClass.class);
if (containingClass != null) {
@@ -940,17 +989,18 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkAbstractInstantiation(ref, resolved));
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkExtendsDuplicate(ref, resolved));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkExtendsDuplicate(ref, resolved,myFile));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassExtendsForeignInnerClass(ref, resolved));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkSelectStaticClassFromParameterizedType(resolved, ref));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, ref,
- result.getSubstitutor()));
+ result.getSubstitutor(),
+ myJavaSdkVersion));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkCannotPassInner(ref));
if (resolved != null && parent instanceof PsiReferenceList) {
if (!myHolder.hasErrorResults()) {
PsiReferenceList referenceList = (PsiReferenceList)parent;
- myHolder.add(HighlightUtil.checkElementInReferenceList(ref, referenceList, result));
+ myHolder.add(HighlightUtil.checkElementInReferenceList(ref, referenceList, result, myLanguageLevel));
}
}
@@ -974,7 +1024,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
myReassignedParameters.put((PsiParameter)variable, 2);
}
- final EditorColorsScheme colorsScheme = myHolder.getColorsScheme();
+ final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
if (!variable.hasModifierProperty(PsiModifier.FINAL) && isReassigned(variable)) {
myHolder.add(HighlightNamesUtil.highlightReassignedVariable(variable, ref));
}
@@ -1027,7 +1077,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
return result;
}
- @Override public void visitReferenceExpression(PsiReferenceExpression expression) {
+ @Override
+ public void visitReferenceExpression(PsiReferenceExpression expression) {
JavaResolveResult resultForIncompleteCode = doVisitReferenceElement(expression);
if (!myHolder.hasErrorResults()) {
visitExpression(expression);
@@ -1036,7 +1087,15 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
JavaResolveResult result;
JavaResolveResult[] results;
try {
- results = expression.multiResolve(true);
+ if (expression instanceof PsiReferenceExpressionImpl) {
+ PsiReferenceExpressionImpl referenceExpression = (PsiReferenceExpressionImpl)expression;
+ results = JavaResolveUtil.resolveWithContainingFile(referenceExpression,
+ PsiReferenceExpressionImpl.OurGenericsResolver.INSTANCE, true, true,
+ myFile);
+ }
+ else {
+ results = expression.multiResolve(true);
+ }
result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
}
catch (IndexNotReadyException e) {
@@ -1046,7 +1105,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (resolved instanceof PsiVariable && resolved.getContainingFile() == expression.getContainingFile()) {
if (!myHolder.hasErrorResults()) {
try {
- myHolder.add(HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(expression, (PsiVariable)resolved, myUninitializedVarProblems));
+ myHolder.add(HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(expression, (PsiVariable)resolved, myUninitializedVarProblems,myFile));
}
catch (IndexNotReadyException ignored) {
}
@@ -1089,7 +1148,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
- myHolder.add(HighlightUtil.checkMethodReferencesFeature(expression));
+ myHolder.add(HighlightUtil.checkMethodReferencesFeature(expression, myLanguageLevel,myFile));
JavaResolveResult result;
try {
result = expression.advancedResolve(true);
@@ -1164,51 +1223,59 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitReferenceParameterList(PsiReferenceParameterList list) {
- myHolder.add(GenericsHighlightUtil.checkParametersAllowed(list));
+ myHolder.add(GenericsHighlightUtil.checkParametersAllowed(list, myLanguageLevel,myFile));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkParametersOnRaw(list));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkRawOnParameterizedType(list));
}
- @Override public void visitReturnStatement(PsiReturnStatement statement) {
+ @Override
+ public void visitReturnStatement(PsiReturnStatement statement) {
try {
myHolder.add(HighlightUtil.checkReturnStatementType(statement));
}
- catch (IndexNotReadyException ignore) { }
+ catch (IndexNotReadyException ignore) {
+ }
}
- @Override public void visitStatement(PsiStatement statement) {
+ @Override
+ public void visitStatement(PsiStatement statement) {
super.visitStatement(statement);
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkNotAStatement(statement));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkStatementPrependedWithCaseInsideSwitch(statement));
}
- @Override public void visitSuperExpression(PsiSuperExpression expr) {
+ @Override
+ public void visitSuperExpression(PsiSuperExpression expr) {
myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier()));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkAbstractMethodDirectCall(expr));
if (!myHolder.hasErrorResults()) visitExpression(expr);
}
- @Override public void visitSwitchLabelStatement(PsiSwitchLabelStatement statement) {
+ @Override
+ public void visitSwitchLabelStatement(PsiSwitchLabelStatement statement) {
super.visitSwitchLabelStatement(statement);
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkCaseStatement(statement));
}
- @Override public void visitSwitchStatement(PsiSwitchStatement statement) {
+ @Override
+ public void visitSwitchStatement(PsiSwitchStatement statement) {
super.visitSwitchStatement(statement);
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSwitchSelectorType(statement));
}
- @Override public void visitThisExpression(PsiThisExpression expr) {
+ @Override
+ public void visitThisExpression(PsiThisExpression expr) {
myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier()));
if (!myHolder.hasErrorResults()) {
- myHolder.add(HighlightUtil.checkMemberReferencedBeforeConstructorCalled(expr, null));
+ myHolder.add(HighlightUtil.checkMemberReferencedBeforeConstructorCalled(expr, null, myFile));
}
if (!myHolder.hasErrorResults()) {
visitExpression(expr);
}
}
- @Override public void visitThrowStatement(PsiThrowStatement statement) {
+ @Override
+ public void visitThrowStatement(PsiThrowStatement statement) {
myHolder.add(HighlightUtil.checkUnhandledExceptions(statement, null));
if (!myHolder.hasErrorResults()) visitStatement(statement);
}
@@ -1224,7 +1291,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
added = myHolder.addAll(HighlightUtil.checkExceptionThrownInTry(parameter, thrownTypes));
}
if (!added) {
- myHolder.addAll(HighlightUtil.checkWithImprovedCatchAnalysis(parameter, thrownTypes));
+ myHolder.addAll(HighlightUtil.checkWithImprovedCatchAnalysis(parameter, thrownTypes,myFile));
}
}
}
@@ -1233,20 +1300,21 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitResourceVariable(final PsiResourceVariable resourceVariable) {
visitVariable(resourceVariable);
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryWithResourcesFeature(resourceVariable));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryWithResourcesFeature(resourceVariable, myLanguageLevel,myFile));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resourceVariable));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnhandledCloserExceptions(resourceVariable));
}
@Override
public void visitTypeElement(final PsiTypeElement type) {
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkDiamondFeature(type));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkDiamondFeature(type, myLanguageLevel,myFile));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalType(type));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkReferenceTypeUsedAsTypeArgument(type));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkWildcardUsage(type));
}
- @Override public void visitTypeCastExpression(PsiTypeCastExpression typeCast) {
+ @Override
+ public void visitTypeCastExpression(PsiTypeCastExpression typeCast) {
super.visitTypeCastExpression(typeCast);
try {
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkInconvertibleTypeCast(typeCast));
@@ -1255,11 +1323,13 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
- @Override public void visitTypeParameterList(PsiTypeParameterList list) {
- myHolder.add(GenericsHighlightUtil.checkTypeParametersList(list));
+ @Override
+ public void visitTypeParameterList(PsiTypeParameterList list) {
+ myHolder.add(GenericsHighlightUtil.checkTypeParametersList(list, myLanguageLevel,myFile));
}
- @Override public void visitVariable(PsiVariable variable) {
+ @Override
+ public void visitVariable(PsiVariable variable) {
super.visitVariable(variable);
try {
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkVariableInitializerType(variable));
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BringVariableIntoScopeFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BringVariableIntoScopeFix.java
index ff14d0c5bf5a..8212b039d100 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BringVariableIntoScopeFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BringVariableIntoScopeFix.java
@@ -145,7 +145,7 @@ public class BringVariableIntoScopeFix implements IntentionAction {
myOutOfScopeVariable.delete();
}
- if (HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(myUnresolvedReference, addedVar, new THashMap<PsiElement, Collection<PsiReferenceExpression>>()) != null) {
+ if (HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(myUnresolvedReference, addedVar, new THashMap<PsiElement, Collection<PsiReferenceExpression>>(),file) != null) {
initialize(addedVar);
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java
index c12e9cb2c8c4..ac607483d723 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java
@@ -18,7 +18,7 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.daemon.QuickFixBundle;
-import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
+import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
import com.intellij.codeInsight.generation.PsiElementClassMember;
import com.intellij.codeInsight.generation.PsiFieldMember;
import com.intellij.codeInsight.generation.PsiMethodMember;
@@ -316,7 +316,7 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction {
if (newParameters == parameters) return false; //user must have canceled dialog
boolean created = false;
// do not introduce assignment in chanined constructor
- if (HighlightControlFlowUtil.getChainedConstructors(constructor) == null) {
+ if (JavaHighlightUtil.getChainedConstructors(constructor) == null) {
for (PsiField field : fields.keySet()) {
final String defaultParamName = fields.get(field);
PsiParameter parameter = findParamByName(defaultParamName, field.getType(), newParameters, parameterInfos);
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 667143b2da35..491a5f6afe13 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
@@ -569,7 +569,7 @@ public class CreateFromUsageUtils {
return result.toArray(new PsiVariable[result.size()]);
}
- private static void getExpectedInformation(PsiExpression expression,
+ private static void getExpectedInformation(final PsiExpression expression,
List<ExpectedTypeInfo[]> types,
List<String> expectedMethodNames,
List<String> expectedFieldNames) {
@@ -579,6 +579,12 @@ public class CreateFromUsageUtils {
if (!(parent instanceof PsiReferenceExpression)) {
ExpectedTypeInfo[] someExpectedTypes = ExpectedTypesProvider.getExpectedTypes(expr, false);
if (someExpectedTypes.length > 0) {
+ Arrays.sort(someExpectedTypes, new Comparator<ExpectedTypeInfo>() {
+ @Override
+ public int compare(ExpectedTypeInfo o1, ExpectedTypeInfo o2) {
+ return compareExpectedTypes(o1, o2, expression);
+ }
+ });
types.add(someExpectedTypes);
}
continue;
@@ -595,6 +601,12 @@ public class CreateFromUsageUtils {
if (refName.equals("equals")) {
ExpectedTypeInfo[] someExpectedTypes = equalsExpectedTypes((PsiMethodCallExpression)pparent);
if (someExpectedTypes.length > 0) {
+ Arrays.sort(someExpectedTypes, new Comparator<ExpectedTypeInfo>() {
+ @Override
+ public int compare(ExpectedTypeInfo o1, ExpectedTypeInfo o2) {
+ return compareExpectedTypes(o1, o2, expression);
+ }
+ });
types.add(someExpectedTypes);
}
}
@@ -609,6 +621,14 @@ public class CreateFromUsageUtils {
}
}
+ private static int compareExpectedTypes(ExpectedTypeInfo o1, ExpectedTypeInfo o2, PsiExpression expression) {
+ PsiClass c1 = PsiUtil.resolveClassInType(o1.getDefaultType());
+ PsiClass c2 = PsiUtil.resolveClassInType(o2.getDefaultType());
+ if (c1 == null && c2 == null) return 0;
+ if (c1 == null || c2 == null) return c1 == null ? -1 : 1;
+ return compareMembers(c1, c2, expression);
+ }
+
private static ExpectedTypeInfo[] equalsExpectedTypes(PsiMethodCallExpression methodCall) {
final PsiType[] argumentTypes = methodCall.getArgumentList().getExpressionTypes();
if (argumentTypes.length != 1) {
@@ -781,25 +801,7 @@ public class CreateFromUsageUtils {
Arrays.sort(members, new Comparator<PsiMember>() {
@Override
public int compare(final PsiMember m1, final PsiMember m2) {
- ProgressManager.checkCanceled();
- int result = JavaStatisticsManager.createInfo(null, m2).getUseCount() - JavaStatisticsManager.createInfo(null, m1).getUseCount();
- if (result != 0) return result;
- final PsiClass aClass = m1.getContainingClass();
- final PsiClass bClass = m2.getContainingClass();
- if (aClass == null || bClass == null) return 0;
- result = JavaStatisticsManager.createInfo(null, bClass).getUseCount() - JavaStatisticsManager.createInfo(null, aClass).getUseCount();
- if (result != 0) return result;
-
- WeighingComparable<PsiElement,ProximityLocation> proximity1 = PsiProximityComparator.getProximity(m1, expression);
- WeighingComparable<PsiElement,ProximityLocation> proximity2 = PsiProximityComparator.getProximity(m2, expression);
- if (proximity1 != null && proximity2 != null) {
- result = proximity2.compareTo(proximity1);
- if (result != 0) return result;
- }
-
- String name1 = StaticImportMethodFix.getMemberQualifiedName(m1);
- String name2 = StaticImportMethodFix.getMemberQualifiedName(m2);
- return name1 == null || name2 == null ? 0 : name1.compareTo(name2);
+ return compareMembers(m1, m2, expression);
}
});
@@ -836,6 +838,29 @@ public class CreateFromUsageUtils {
}
}
+ private static int compareMembers(PsiMember m1, PsiMember m2, PsiExpression context) {
+ ProgressManager.checkCanceled();
+ int result = JavaStatisticsManager.createInfo(null, m2).getUseCount() - JavaStatisticsManager.createInfo(null, m1).getUseCount();
+ if (result != 0) return result;
+ final PsiClass aClass = m1.getContainingClass();
+ final PsiClass bClass = m2.getContainingClass();
+ if (aClass != null && bClass != null) {
+ result = JavaStatisticsManager.createInfo(null, bClass).getUseCount() - JavaStatisticsManager.createInfo(null, aClass).getUseCount();
+ if (result != 0) return result;
+ }
+
+ WeighingComparable<PsiElement,ProximityLocation> proximity1 = PsiProximityComparator.getProximity(m1, context);
+ WeighingComparable<PsiElement,ProximityLocation> proximity2 = PsiProximityComparator.getProximity(m2, context);
+ if (proximity1 != null && proximity2 != null) {
+ result = proximity2.compareTo(proximity1);
+ if (result != 0) return result;
+ }
+
+ String name1 = PsiUtil.getMemberQualifiedName(m1);
+ String name2 = PsiUtil.getMemberQualifiedName(m2);
+ return name1 == null || name2 == null ? 0 : name1.compareTo(name2);
+ }
+
public static boolean isAccessedForWriting(final PsiExpression[] expressionOccurences) {
for (PsiExpression expression : expressionOccurences) {
if(PsiUtil.isAccessedForWriting(expression)) return true;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java
index 3225968c3dd9..11bab8017903 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java
@@ -17,13 +17,13 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.QuickFixBundle;
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PropertyUtil;
-import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -116,16 +116,12 @@ public class CreateGetterOrSetterFix implements IntentionAction, LowPriorityActi
PsiClass aClass = myField.getContainingClass();
final List<PsiMethod> methods = new ArrayList<PsiMethod>();
if (myCreateGetter) {
- methods.add(PropertyUtil.generateGetterPrototype(myField));
+ methods.add(GenerateMembersUtil.generateGetterPrototype(myField));
}
if (myCreateSetter) {
- methods.add(PropertyUtil.generateSetterPrototype(myField));
+ methods.add(GenerateMembersUtil.generateSetterPrototype(myField));
}
for (PsiMethod method : methods) {
- String modifier = PsiUtil.getMaximumModifierForMember(aClass);
- if (modifier != null) {
- PsiUtil.setModifierProperty(method, modifier, true);
- }
aClass.add(method);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterSetterPropertyFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterSetterPropertyFromUsageFix.java
index eeae2b08c245..c5bd0289d4e3 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterSetterPropertyFromUsageFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterSetterPropertyFromUsageFix.java
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.daemon.impl.quickfix;
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
@@ -55,13 +56,13 @@ public class CreateGetterSetterPropertyFromUsageFix extends CreatePropertyFromUs
@Override
protected void beforeTemplateFinished(PsiClass aClass, PsiField field) {
- PsiMethod getterPrototype = PropertyUtil.generateGetterPrototype(field);
+ PsiMethod getterPrototype = GenerateMembersUtil.generateGetterPrototype(field);
if (aClass.findMethodsBySignature(getterPrototype, false).length == 0) {
aClass.add(getterPrototype);
}
- PsiMethod setterPrototype = PropertyUtil.generateSetterPrototype(field);
+ PsiMethod setterPrototype = GenerateMembersUtil.generateSetterPrototype(field);
if (aClass.findMethodsBySignature(setterPrototype, false).length == 0) {
aClass.add(setterPrototype);
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java
index c61685914cce..6567a9a478cc 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.CodeInsightUtilCore;
import com.intellij.codeInsight.completion.JavaLookupElementBuilder;
import com.intellij.codeInsight.daemon.QuickFixBundle;
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.codeInsight.intention.impl.TypeExpression;
import com.intellij.codeInsight.lookup.LookupElement;
@@ -226,7 +227,7 @@ public class CreatePropertyFromUsageFix extends CreateFromUsageBaseFix implement
PsiElement typeReference;
PsiCodeBlock body;
if (callText.startsWith(GET_PREFIX) || callText.startsWith(IS_PREFIX)) {
- accessor = (PsiMethod)targetClass.add(PropertyUtil.generateGetterPrototype(field));
+ accessor = (PsiMethod)targetClass.add(GenerateMembersUtil.generateGetterPrototype(field));
body = accessor.getBody();
LOG.assertTrue(body != null, accessor.getText());
fieldReference = ((PsiReturnStatement)body.getStatements()[0]).getReturnValue();
@@ -242,10 +243,6 @@ public class CreatePropertyFromUsageFix extends CreateFromUsageBaseFix implement
}
accessor.setName(callText);
PsiUtil.setModifierProperty(accessor, PsiModifier.STATIC, isStatic);
- final String modifier = PsiUtil.getMaximumModifierForMember(targetClass);
- if (modifier != null) {
- PsiUtil.setModifierProperty(accessor, modifier, true);
- }
TemplateBuilderImpl builder = new TemplateBuilderImpl(accessor);
builder.replaceElement(typeReference, TYPE_VARIABLE, new TypeExpression(project, expectedTypes), true);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java
index 2e23f7ef65e4..17871d103816 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java
@@ -119,6 +119,9 @@ public class ImportClassFix extends ImportClassFixBase<PsiJavaCodeReferenceEleme
return filterAssignableFrom(initializer.getType(), candidates);
}
}
+ if (var instanceof PsiParameter) {
+ return filterBySuperMethods((PsiParameter)var, candidates);
+ }
}
return super.filterByContext(candidates, ref);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
index bfb7c45bf3c8..5de72527f379 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
@@ -43,7 +43,9 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.HashSet;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -125,6 +127,18 @@ public abstract class ImportClassFixBase<T extends PsiElement, R extends PsiRefe
}
}
+ classList = filterByRequiredMemberName(classList);
+
+ List<PsiClass> filtered = filterByContext(classList, myElement);
+ if (!filtered.isEmpty()) {
+ classList = filtered;
+ }
+
+ filterAlreadyImportedButUnresolved(classList);
+ return classList;
+ }
+
+ private List<PsiClass> filterByRequiredMemberName(List<PsiClass> classList) {
final String memberName = getRequiredMemberName(myElement);
if (memberName != null) {
List<PsiClass> filtered = ContainerUtil.findAll(classList, new Condition<PsiClass>() {
@@ -146,13 +160,6 @@ public abstract class ImportClassFixBase<T extends PsiElement, R extends PsiRefe
classList = filtered;
}
}
-
- List<PsiClass> filtered = filterByContext(classList, myElement);
- if (!filtered.isEmpty()) {
- classList = filtered;
- }
-
- filterAlreadyImportedButUnresolved(classList);
return classList;
}
@@ -206,6 +213,41 @@ public abstract class ImportClassFixBase<T extends PsiElement, R extends PsiRefe
return candidates;
}
+ protected static List<PsiClass> filterBySuperMethods(PsiParameter parameter, List<PsiClass> candidates) {
+ PsiElement parent = parameter.getParent();
+ if (parent instanceof PsiParameterList) {
+ PsiElement granny = parent.getParent();
+ if (granny instanceof PsiMethod) {
+ final PsiMethod method = (PsiMethod)granny;
+ if (method.getModifierList().findAnnotation(CommonClassNames.JAVA_LANG_OVERRIDE) != null) {
+ PsiClass aClass = method.getContainingClass();
+ final Set<PsiClass> probableTypes = new HashSet<PsiClass>();
+ InheritanceUtil.processSupers(aClass, false, new Processor<PsiClass>() {
+ @Override
+ public boolean process(PsiClass psiClass) {
+ for (PsiMethod psiMethod : psiClass.findMethodsByName(method.getName(), false)) {
+ for (PsiParameter psiParameter : psiMethod.getParameterList().getParameters()) {
+ ContainerUtil.addIfNotNull(probableTypes, PsiUtil.resolveClassInClassTypeOnly(psiParameter.getType()));
+ }
+ }
+ return true;
+ }
+ });
+ List<PsiClass> filtered = ContainerUtil.filter(candidates, new Condition<PsiClass>() {
+ @Override
+ public boolean value(PsiClass psiClass) {
+ return probableTypes.contains(psiClass);
+ }
+ });
+ if (!filtered.isEmpty()) {
+ return filtered;
+ }
+ }
+ }
+ }
+ return candidates;
+ }
+
public enum Result {
POPUP_SHOWN,
CLASS_AUTO_IMPORTED,
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceInaccessibleFieldWithGetterSetterFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceInaccessibleFieldWithGetterSetterFix.java
index 8e0621898dfc..12176d337f0f 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceInaccessibleFieldWithGetterSetterFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplaceInaccessibleFieldWithGetterSetterFix.java
@@ -17,6 +17,7 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
@@ -98,7 +99,7 @@ public class ReplaceInaccessibleFieldWithGetterSetterFix extends LocalQuickFixAn
}
}
else if (PsiUtil.isAccessedForReading((PsiExpression)place)) {
- final PsiMethod getterPrototype = PropertyUtil.generateGetterPrototype(psiField);
+ final PsiMethod getterPrototype = GenerateMembersUtil.generateGetterPrototype(psiField);
final PsiMethod getter = containingClass.findMethodBySignature(getterPrototype, true);
if (getter != null && PsiUtil.isAccessible(getter, place, accessObjectClass)) {
QuickFixAction.registerQuickFixAction(error, new ReplaceInaccessibleFieldWithGetterSetterFix(place, getter, false));
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java
index 9c9af0f9f410..9461af0067ef 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java
@@ -44,7 +44,6 @@ import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ObjectUtils;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -233,7 +232,7 @@ public class StaticImportMethodFix implements IntentionAction {
}
public static boolean isExcluded(PsiMember method) {
- String name = getMemberQualifiedName(method);
+ String name = PsiUtil.getMemberQualifiedName(method);
if (name == null) return false;
CodeInsightSettings cis = CodeInsightSettings.getInstance();
for (String excluded : cis.EXCLUDED_PACKAGES) {
@@ -301,7 +300,7 @@ public class StaticImportMethodFix implements IntentionAction {
return FINAL_CHOICE;
}
- String qname = getMemberQualifiedName(selectedValue);
+ String qname = PsiUtil.getMemberQualifiedName(selectedValue);
if (qname == null) return FINAL_CHOICE;
List<String> excludableStrings = AddImportAction.getAllExcludableStrings(qname);
return new BaseListPopupStep<String>(null, excludableStrings) {
@@ -371,19 +370,6 @@ public class StaticImportMethodFix implements IntentionAction {
popup.showInBestPositionFor(editor);
}
- @Nullable
- public static String getMemberQualifiedName(PsiMember member) {
- if (member instanceof PsiClass) {
- return ((PsiClass)member).getQualifiedName();
- }
-
- PsiClass containingClass = member.getContainingClass();
- if (containingClass == null) return null;
- String className = containingClass.getQualifiedName();
- if (className == null) return null;
- return className + "." + member.getName();
- }
-
@Override
public boolean startInWriteAction() {
return true;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java
index 8483946e292e..1070533e94ca 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java
@@ -312,7 +312,8 @@ public class VariableAccessFromInnerClassFix implements IntentionAction {
Map<PsiElement, Collection<ControlFlowUtil.VariableInfo>> finalVarProblems = new THashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>();
for (PsiReferenceExpression expression : references) {
if (ControlFlowUtil.isVariableAssignedInLoop(expression, variable)) return false;
- HighlightInfo highlightInfo = HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(expression, variable, uninitializedVarProblems);
+ HighlightInfo highlightInfo = HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(expression, variable, uninitializedVarProblems,
+ variable.getContainingFile());
if (highlightInfo != null) return false;
highlightInfo = HighlightControlFlowUtil.checkFinalVariableMightAlreadyHaveBeenAssignedTo(variable, expression, finalVarProblems);
if (highlightInfo != null) return false;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableParameterizedTypeFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableParameterizedTypeFix.java
index a7a666c13bf7..a8b3b2847865 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableParameterizedTypeFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableParameterizedTypeFix.java
@@ -18,10 +18,12 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.analysis.GenericsHighlightUtil;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
+import com.intellij.openapi.project.DumbService;
+import com.intellij.openapi.projectRoots.JavaSdkVersion;
+import com.intellij.openapi.projectRoots.JavaSdkVersionUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
-import com.intellij.openapi.project.DumbService;
import java.util.HashMap;
@@ -38,8 +40,9 @@ public class VariableParameterizedTypeFix {
PsiShortNamesCache shortNamesCache = PsiShortNamesCache.getInstance(parameterList.getProject());
PsiClass[] classes = shortNamesCache.getClassesByName(shortName, GlobalSearchScope.allScope(manager.getProject()));
PsiElementFactory factory = facade.getElementFactory();
+ JavaSdkVersion version = JavaSdkVersionUtil.getJavaSdkVersion(parameterList);
for (PsiClass aClass : classes) {
- if (GenericsHighlightUtil.checkReferenceTypeArgumentList(aClass, parameterList, PsiSubstitutor.EMPTY, false) == null) {
+ if (GenericsHighlightUtil.checkReferenceTypeArgumentList(aClass, parameterList, PsiSubstitutor.EMPTY, false, version) == null) {
PsiType[] actualTypeParameters = parameterList.getTypeArguments();
PsiTypeParameter[] classTypeParameters = aClass.getTypeParameters();
HashMap<PsiTypeParameter, PsiType> map = new HashMap<PsiTypeParameter, PsiType>();
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandler.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandler.java
index 03b8075f3b2a..ae7dfb95f2ca 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaTypedHandler.java
@@ -142,7 +142,7 @@ public class JavaTypedHandler extends TypedHandlerDelegate {
}
@Override
- public Result charTyped(final char c, final Project project, final Editor editor, @NotNull final PsiFile file) {
+ public Result charTyped(final char c, final Project project, @NotNull final Editor editor, @NotNull final PsiFile file) {
if (myJavaLTTyped) {
myJavaLTTyped = false;
handleAfterJavaLT(editor, JavaTokenType.LT, JavaTokenType.GT, INVALID_INSIDE_REFERENCE);
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavadocTypedHandler.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavadocTypedHandler.java
index af0a06c0b09e..f957efb1ecf4 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavadocTypedHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavadocTypedHandler.java
@@ -41,7 +41,7 @@ public class JavadocTypedHandler extends TypedHandlerDelegate {
private static final char SLASH = '/';
@Override
- public Result charTyped(char c, Project project, Editor editor, PsiFile file) {
+ public Result charTyped(char c, Project project, @NotNull Editor editor, @NotNull PsiFile file) {
if (project == null || editor == null || file == null) {
return Result.CONTINUE;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java
index cfb40848e403..eebf0663aaf4 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java
@@ -30,6 +30,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -154,7 +155,7 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor {
}
protected String getLineBreaker(PsiElement token) {
- CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(token.getProject());
+ CommonCodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(token.getProject()).getCommonSettings(token.getLanguage());
return codeStyleSettings.BINARY_OPERATION_SIGN_ON_NEXT_LINE ? "\\n\"\n+ \"" : "\\n\" +\n\"";
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/DocTagSelectioner.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/DocTagSelectioner.java
index c64d304249cb..d706a2d60ab0 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/DocTagSelectioner.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/DocTagSelectioner.java
@@ -36,7 +36,11 @@ public class DocTagSelectioner extends WordSelectioner {
@Override
public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
List<TextRange> result = super.select(e, editorText, cursorOffset, editor);
+ result.add(getDocTagRange((PsiDocTag)e, editorText, cursorOffset));
+ return result;
+ }
+ public static TextRange getDocTagRange(PsiDocTag e, CharSequence documentText, int minOffset) {
TextRange range = e.getTextRange();
int endOffset = range.getEndOffset();
@@ -49,7 +53,7 @@ public class DocTagSelectioner extends WordSelectioner {
int childStartOffset = child.getTextRange().getStartOffset();
- if (childStartOffset <= cursorOffset) {
+ if (childStartOffset <= minOffset) {
break;
}
@@ -71,10 +75,8 @@ public class DocTagSelectioner extends WordSelectioner {
endOffset = Math.min(childStartOffset, endOffset);
}
- startOffset = CharArrayUtil.shiftBackward(editorText, startOffset - 1, "* \t") + 1;
+ startOffset = CharArrayUtil.shiftBackward(documentText, startOffset - 1, "* \t") + 1;
- result.add(new TextRange(startOffset, endOffset));
-
- return result;
+ return new TextRange(startOffset, endOffset);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java b/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java
index 538b713d550b..1b088879f59b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java
+++ b/java/java-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilder.java
@@ -19,10 +19,7 @@ import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.ExpectedTypesProvider;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.PsiAnonymousClass;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiNewExpression;
-import com.intellij.psi.PsiReferenceExpression;
+import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
@@ -38,7 +35,8 @@ public class JavaFoldingBuilder extends JavaFoldingBuilderBase {
@Override
protected boolean shouldShowExplicitLambdaType(PsiAnonymousClass anonymousClass, PsiNewExpression expression) {
- if (expression.getParent() instanceof PsiReferenceExpression) {
+ PsiElement parent = expression.getParent();
+ if (parent instanceof PsiReferenceExpression || parent instanceof PsiAssignmentExpression) {
return 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 a3c52e718a9b..de7261d60641 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java
@@ -106,6 +106,12 @@ public class GenerateEqualsHelper implements Runnable {
return id;
}
+ private static boolean shouldAddOverrideAnnotation(PsiElement context) {
+ CodeStyleSettings style = CodeStyleSettingsManager.getSettings(context.getProject());
+
+ return style.INSERT_OVERRIDE_ANNOTATION && PsiUtil.isLanguageLevel5OrHigher(context);
+ }
+
@Override
public void run() {
try {
@@ -133,8 +139,7 @@ public class GenerateEqualsHelper implements Runnable {
else {
if (!mySuperHasHashCode) {
@NonNls String text = "";
- CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(myProject);
- if (GenerateMembersUtil.shouldAddOverrideAnnotation(myClass, false)) {
+ if (shouldAddOverrideAnnotation(myClass)) {
text += "@Override\n";
}
@@ -172,7 +177,7 @@ public class GenerateEqualsHelper implements Runnable {
@NonNls StringBuffer buffer = new StringBuffer();
CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(myProject);
- if (GenerateMembersUtil.shouldAddOverrideAnnotation(myClass, false)) {
+ if (shouldAddOverrideAnnotation(myClass)) {
buffer.append("@Override\n");
}
buffer.append("public boolean equals(Object ").append(myParameterName).append(") {\n");
@@ -327,8 +332,7 @@ public class GenerateEqualsHelper implements Runnable {
private PsiMethod createHashCode() throws IncorrectOperationException {
@NonNls StringBuilder buffer = new StringBuilder();
- CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(myProject);
- if (GenerateMembersUtil.shouldAddOverrideAnnotation(myClass, false)) {
+ if (shouldAddOverrideAnnotation(myClass)) {
buffer.append("@Override\n");
}
buffer.append("public int hashCode() {\n");
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateFieldOrPropertyHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateFieldOrPropertyHandler.java
index 8b3dd21a5fd0..632dd6d7b688 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateFieldOrPropertyHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateFieldOrPropertyHandler.java
@@ -21,8 +21,11 @@ import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.util.PropertyMemberType;
+import com.intellij.psi.util.PropertyUtil;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collections;
@@ -54,31 +57,38 @@ public class GenerateFieldOrPropertyHandler extends GenerateMembersHandlerBase {
@Override
@NotNull
public List<? extends GenerationInfo> generateMemberPrototypes(PsiClass aClass, ClassMember[] members) throws IncorrectOperationException {
- final PsiElementFactory psiElementFactory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory();
+ PsiElementFactory psiElementFactory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory();
try {
- final String name = myMemberType == PropertyMemberType.FIELD? myAttributeName : JavaCodeStyleManager.getInstance(aClass.getProject()).propertyNameToVariableName(myAttributeName, VariableKind.FIELD);
- final PsiField psiField = psiElementFactory.createField(name, myType);
- final GenerationInfo[] objects = new GenerateGetterAndSetterHandler().generateMemberPrototypes(aClass, new PsiFieldMember(psiField));
- final GenerationInfo getter = objects[0];
- final GenerationInfo setter = objects[1];
+ String fieldName = getFieldName(aClass);
+ PsiField psiField = psiElementFactory.createField(fieldName, myType);
+ GenerationInfo[] infos = new GenerateGetterAndSetterHandler().generateMemberPrototypes(aClass, new PsiFieldMember(psiField));
if (myAnnotations.length > 0) {
- final PsiMember targetMember;
- switch (myMemberType) {
- case FIELD: targetMember = psiField;
- break;
- case GETTER: targetMember = getter.getPsiMember();
- break;
- case SETTER: targetMember = setter.getPsiMember();
- break;
- default: targetMember = null;
- break;
+ PsiMember targetMember = null;
+ if (myMemberType == PropertyMemberType.FIELD) {
+ targetMember = psiField;
}
- assert targetMember != null;
- for (PsiAnnotation annotation : myAnnotations) {
- targetMember.getModifierList().addAfter(annotation, null);
+ else {
+ for (GenerationInfo info : infos) {
+ PsiMember member = info.getPsiMember();
+ if (!(member instanceof PsiMethod)) continue;
+ if (myMemberType == PropertyMemberType.GETTER && PropertyUtil.isSimplePropertyGetter((PsiMethod)member) ||
+ myMemberType == PropertyMemberType.SETTER && PropertyUtil.isSimplePropertySetter((PsiMethod)member)) {
+ targetMember = member;
+ break;
+ }
+ }
+ if (targetMember == null) targetMember = findExistingMember(aClass, myMemberType);
+ }
+ PsiModifierList modifierList = targetMember != null? targetMember.getModifierList() : null;
+ if (modifierList != null) {
+ for (PsiAnnotation annotation : myAnnotations) {
+ PsiAnnotation existing = modifierList.findAnnotation(annotation.getQualifiedName());
+ if (existing != null) existing.replace(annotation);
+ else modifierList.addAfter(annotation, null);
+ }
}
}
- return Arrays.asList(new PsiGenerationInfo<PsiField>(psiField), getter, setter);
+ return ContainerUtil.concat(Collections.singletonList(new PsiGenerationInfo<PsiField>(psiField)), Arrays.asList(infos));
}
catch (IncorrectOperationException e) {
assert false : e;
@@ -86,6 +96,33 @@ public class GenerateFieldOrPropertyHandler extends GenerateMembersHandlerBase {
}
}
+ @Nullable
+ public PsiMember findExistingMember(@NotNull PsiClass aClass, @NotNull PropertyMemberType memberType) {
+ if (memberType == PropertyMemberType.FIELD) {
+ return aClass.findFieldByName(getFieldName(aClass), false);
+ }
+ else if (memberType == PropertyMemberType.GETTER) {
+ try {
+ PsiElementFactory psiElementFactory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory();
+ PsiField field = psiElementFactory.createField(myAttributeName, myType);
+ PsiMethod[] templates = GetterSetterPrototypeProvider.generateGetterSetters(field, myMemberType == PropertyMemberType.GETTER);
+ for (PsiMethod template : templates) {
+ PsiMethod existingMethod = aClass.findMethodBySignature(template, true);
+ if (existingMethod != null) return existingMethod;
+ }
+ }
+ catch (IncorrectOperationException e) {
+ assert false : e;
+ }
+ }
+ return null;
+ }
+
+ private String getFieldName(PsiClass aClass) {
+ return myMemberType == PropertyMemberType.FIELD? myAttributeName : JavaCodeStyleManager
+ .getInstance(aClass.getProject()).propertyNameToVariableName(myAttributeName, VariableKind.FIELD);
+ }
+
@Override
protected ClassMember[] getAllOriginalMembers(PsiClass aClass) {
throw new UnsupportedOperationException();
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java
index a58dfe3dae2a..27c53252c09c 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java
@@ -33,6 +33,7 @@ import com.intellij.psi.impl.light.LightTypeElement;
import com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
@@ -260,7 +261,7 @@ public class GenerateMembersUtil {
try {
final PsiMethod resultMethod = createMethod(factory, sourceMethod, target);
- copyDocComment(sourceMethod, resultMethod);
+ copyDocComment(sourceMethod, resultMethod, factory);
copyModifiers(sourceMethod.getModifierList(), resultMethod.getModifierList());
final PsiSubstitutor collisionResolvedSubstitutor =
substituteTypeParameters(factory, target, sourceMethod.getTypeParameterList(), resultMethod.getTypeParameterList(), substitutor, sourceMethod);
@@ -305,7 +306,8 @@ public class GenerateMembersUtil {
for (PsiTypeParameter typeParam : sourceTypeParameterList.getTypeParameters()) {
final PsiTypeParameter substitutedTypeParam = substituteTypeParameter(factory, typeParam, substitutor, sourceMethod);
- final PsiTypeParameter resolvedTypeParam = resolveTypeParametersCollision(factory, sourceTypeParameterList, target, substitutedTypeParam, substitutor);
+ final PsiTypeParameter resolvedTypeParam = resolveTypeParametersCollision(factory, sourceTypeParameterList, target,
+ substitutedTypeParam, substitutor);
targetTypeParameterList.add(resolvedTypeParam);
if (substitutedTypeParam != resolvedTypeParam) {
substitutionMap.put(typeParam, factory.createType(resolvedTypeParam));
@@ -328,7 +330,7 @@ public class GenerateMembersUtil {
return newTypeParameter;
}
}
- return typeParam;
+ return factory.createTypeParameter(typeParam.getName(), typeParam.getSuperTypes());
}
@NotNull
@@ -383,8 +385,8 @@ public class GenerateMembersUtil {
@NotNull PsiSubstitutor substitutor, PsiElement target) {
PsiParameter[] parameters = sourceParameterList.getParameters();
UniqueNameGenerator generator = new UniqueNameGenerator();
- for (int i = 0; i < parameters.length; i++) {
- PsiParameter parameter = parameters[i];
+
+ for (PsiParameter parameter : parameters) {
final PsiType parameterType = parameter.getType();
final PsiType substituted = substituteType(substitutor, parameterType, (PsiMethod)parameter.getDeclarationScope());
@NonNls String paramName = parameter.getName();
@@ -394,14 +396,20 @@ public class GenerateMembersUtil {
isBaseNameGenerated = false;
}
- if (paramName == null || isBaseNameGenerated && !isSubstituted && isBaseNameGenerated(codeStyleManager, parameterType, paramName)) {
+ if (paramName == null ||
+ isBaseNameGenerated && !isSubstituted && isBaseNameGenerated(codeStyleManager, parameterType, paramName) ||
+ !factory.isValidParameterName(paramName)) {
String[] names = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, null, null, substituted).names;
if (names.length > 0) {
paramName = generator.generateUniqueName(names[0]);
}
+ else {
+ paramName = generator.generateUniqueName("p");
+ }
+ }
+ else if (!generator.value(paramName)) {
+ paramName = generator.generateUniqueName(paramName);
}
-
- if (paramName == null) paramName = "p" + i;
generator.addExistingName(paramName);
final PsiParameter newParameter = factory.createParameter(paramName, substituted, target);
copyOrReplaceModifierList(parameter, newParameter);
@@ -419,12 +427,12 @@ public class GenerateMembersUtil {
}
}
- private static void copyDocComment(PsiMethod source, PsiMethod target) {
+ private static void copyDocComment(PsiMethod source, PsiMethod target, JVMElementFactory factory) {
final PsiElement navigationElement = source.getNavigationElement();
if (navigationElement instanceof PsiDocCommentOwner) {
final PsiDocComment docComment = ((PsiDocCommentOwner)navigationElement).getDocComment();
if (docComment != null) {
- target.addAfter(docComment, null);
+ target.addAfter(factory.createDocCommentFromText(docComment.getText()), null);
}
}
}
@@ -488,14 +496,6 @@ public class GenerateMembersUtil {
}
}
- public static boolean shouldAddOverrideAnnotation(PsiElement context, boolean interfaceMethod) {
- CodeStyleSettings style = CodeStyleSettingsManager.getSettings(context.getProject());
- if (!style.INSERT_OVERRIDE_ANNOTATION) return false;
-
- if (interfaceMethod) return PsiUtil.isLanguageLevel6OrHigher(context);
- return PsiUtil.isLanguageLevel5OrHigher(context);
- }
-
public static void setupGeneratedMethod(PsiMethod method) {
PsiClass base = method.getContainingClass().getSuperClass();
PsiMethod overridden = base == null ? null : base.findMethodBySignature(method, true);
@@ -551,4 +551,27 @@ public class GenerateMembersUtil {
}
}
}
+
+ @Nullable
+ public static PsiMethod generateGetterPrototype(@NotNull PsiField field) {
+ return annotateOnOverrideImplement(field.getContainingClass(), PropertyUtil.generateGetterPrototype(field));
+ }
+
+ @Nullable
+ public static PsiMethod generateSetterPrototype(@NotNull PsiField field) {
+ return annotateOnOverrideImplement(field.getContainingClass(), PropertyUtil.generateSetterPrototype(field));
+ }
+
+ @Nullable
+ private static PsiMethod annotateOnOverrideImplement(@Nullable PsiClass targetClass, @Nullable PsiMethod generated) {
+ if (generated == null || targetClass == null) return generated;
+
+ if (CodeStyleSettingsManager.getSettings(targetClass.getProject()).INSERT_OVERRIDE_ANNOTATION) {
+ PsiMethod superMethod = targetClass.findMethodBySignature(generated, true);
+ if (superMethod != null && superMethod.getContainingClass() != targetClass) {
+ OverrideImplementUtil.annotateOnOverrideImplement(generated, targetClass, superMethod, true);
+ }
+ }
+ return generated;
+ }
}
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 53630f602ef1..01d71877265a 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 0-2 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.
@@ -119,34 +119,22 @@ public class OverrideImplementUtil extends OverrideImplementExploreUtil {
return !superClass.isInterface();
}
- @NotNull
- private static List<PsiMethod> overrideOrImplementMethod(PsiClass aClass,
- PsiMethod method,
- PsiSubstitutor substitutor,
- boolean toCopyJavaDoc,
- boolean insertOverrideIfPossible) throws IncorrectOperationException {
- return overrideOrImplementMethod(aClass, method, substitutor, createDefaultDecorator(aClass, method, toCopyJavaDoc, insertOverrideIfPossible));
- }
-
public static List<PsiMethod> overrideOrImplementMethod(PsiClass aClass,
- PsiMethod method,
- PsiSubstitutor substitutor,
- Consumer<PsiMethod> decorator) throws IncorrectOperationException {
+ PsiMethod method,
+ PsiSubstitutor substitutor,
+ boolean toCopyJavaDoc,
+ boolean insertOverrideIfPossible) throws IncorrectOperationException {
if (!method.isValid() || !substitutor.isValid()) return Collections.emptyList();
List<PsiMethod> results = new ArrayList<PsiMethod>();
for (final MethodImplementor implementor : getImplementors()) {
final PsiMethod[] prototypes = implementor.createImplementationPrototypes(aClass, method);
- if (implementor.isBodyGenerated()) {
- ContainerUtil.addAll(results, prototypes);
- }
- else {
- for (PsiMethod prototype : prototypes) {
- decorator.consume(prototype);
- results.add(prototype);
- }
+ for (PsiMethod prototype : prototypes) {
+ implementor.createDecorator(aClass, method, toCopyJavaDoc, insertOverrideIfPossible).consume(prototype);
+ results.add(prototype);
}
}
+
if (results.isEmpty()) {
PsiMethod method1 = GenerateMembersUtil.substituteGenericMethod(method, substitutor, aClass);
@@ -163,6 +151,7 @@ public class OverrideImplementUtil extends OverrideImplementExploreUtil {
defaultValue.getParent().deleteChildRange(defaultKeyword, defaultValue);
}
}
+ Consumer<PsiMethod> decorator = createDefaultDecorator(aClass, method, toCopyJavaDoc, insertOverrideIfPossible);
decorator.consume(result);
results.add(result);
}
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 a14108b0fdd2..0f64be3a38ce 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/PsiFieldMember.java
@@ -83,17 +83,6 @@ public class PsiFieldMember extends PsiElementClassMember<PsiField> implements P
@Nullable
private static PsiMethod createMethodIfNotExists(PsiClass aClass, final PsiMethod template) {
PsiMethod existing = aClass.findMethodBySignature(template, false);
- if (existing == null) {
- if (template != null) {
- String modifier = aClass.isEnum() && aClass.hasModifierProperty(PsiModifier.PUBLIC) ? null : PsiUtil.getMaximumModifierForMember(aClass);
- if (modifier != null) {
- PsiUtil.setModifierProperty(template, modifier, true);
- }
- }
- return template;
- }
- else {
- return null;
- }
+ return existing == null ? template : null;
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java
index 9d6fe8845a82..2707501ad13d 100644
--- a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java
@@ -131,11 +131,11 @@ public class HighlightSuppressedWarningsHandler extends HighlightUsagesHandlerBa
Runnable inspect = new Runnable() {
@Override
public void run() {
- pass.doInspectInBatch(managerEx, Collections.<LocalInspectionToolWrapper>singletonList(toolWrapper));
+ pass.doInspectInBatch(context, managerEx, Collections.<LocalInspectionToolWrapper>singletonList(toolWrapper));
}
};
if (indicator == null) {
- ((ProgressManagerImpl)ProgressManager.getInstance()).executeProcessUnderProgress(inspect, new ProgressIndicatorBase());
+ ProgressManager.getInstance().executeProcessUnderProgress(inspect, new ProgressIndicatorBase());
}
else {
inspect.run();
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveFieldAssignmentToInitializerAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveFieldAssignmentToInitializerAction.java
index 3b4127777f2e..c8a94ed44a08 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveFieldAssignmentToInitializerAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveFieldAssignmentToInitializerAction.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.
@@ -53,8 +53,10 @@ public class MoveFieldAssignmentToInitializerAction extends BaseIntentionAction
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- final PsiAssignmentExpression assignment = getAssignmentUnderCaret(editor, file);
+ PsiAssignmentExpression assignment = getAssignmentUnderCaret(editor, file);
if (assignment == null) return false;
+ PsiElement parent = assignment.getParent();
+ if (!(parent instanceof PsiExpressionStatement)) return false;
PsiField field = getAssignedField(assignment);
if (field == null || field.hasInitializer()) return false;
PsiClass psiClass = field.getContainingClass();
@@ -74,11 +76,12 @@ public class MoveFieldAssignmentToInitializerAction extends BaseIntentionAction
if (initializer == null) return false;
final Ref<Boolean> result = new Ref<Boolean>(Boolean.TRUE);
initializer.accept(new JavaRecursiveElementWalkingVisitor() {
- @Override public void visitReferenceExpression(PsiReferenceExpression expression) {
+ @Override
+ public void visitReferenceExpression(PsiReferenceExpression expression) {
PsiElement resolved = expression.resolve();
if (resolved == null) return;
if (PsiTreeUtil.isAncestor(ctrOrInitializer, resolved, false) && !PsiTreeUtil.isAncestor(initializer, resolved, false)) {
- // resolved somewhere inside construcor but outside initializer
+ // resolved somewhere inside constructor but outside initializer
result.set(Boolean.FALSE);
}
}
@@ -97,16 +100,21 @@ public class MoveFieldAssignmentToInitializerAction extends BaseIntentionAction
}
}
- private static boolean isInitializedWithSameExpression(final PsiField field, final PsiAssignmentExpression assignment, final Collection<PsiAssignmentExpression> initializingAssignments) {
+ private static boolean isInitializedWithSameExpression(final PsiField field,
+ final PsiAssignmentExpression assignment,
+ final Collection<PsiAssignmentExpression> initializingAssignments) {
final PsiExpression expression = assignment.getRExpression();
+ if (expression == null) return false;
+ PsiClass containingClass = field.getContainingClass();
+ if (containingClass == null) return false;
+
final Ref<Boolean> result = new Ref<Boolean>(Boolean.TRUE);
final List<PsiAssignmentExpression> totalUsages = new ArrayList<PsiAssignmentExpression>();
- PsiClass containingClass = field.getContainingClass();
- assert containingClass != null;
- containingClass.accept(new JavaRecursiveElementVisitor(){
+ containingClass.accept(new JavaRecursiveElementVisitor() {
private PsiCodeBlock currentInitializingBlock; //ctr or class initializer
- @Override public void visitCodeBlock(PsiCodeBlock block) {
+ @Override
+ public void visitCodeBlock(PsiCodeBlock block) {
PsiElement parent = block.getParent();
if (parent instanceof PsiClassInitializer || parent instanceof PsiMethod && ((PsiMethod)parent).isConstructor()) {
currentInitializingBlock = block;
@@ -118,7 +126,8 @@ public class MoveFieldAssignmentToInitializerAction extends BaseIntentionAction
}
}
- @Override public void visitReferenceExpression(PsiReferenceExpression reference) {
+ @Override
+ public void visitReferenceExpression(PsiReferenceExpression reference) {
if (!result.get().booleanValue()) return;
super.visitReferenceExpression(reference);
if (!PsiUtil.isOnAssignmentLeftHand(reference)) return;
@@ -126,7 +135,7 @@ public class MoveFieldAssignmentToInitializerAction extends BaseIntentionAction
if (resolved != field) return;
PsiExpression rValue = ((PsiAssignmentExpression)reference.getParent()).getRExpression();
if (currentInitializingBlock != null) {
- // ignore usages other than intializing
+ // ignore usages other than initializing
if (rValue == null || !PsiEquivalenceUtil.areElementsEquivalent(rValue, expression)) {
result.set(Boolean.FALSE);
}
@@ -160,13 +169,13 @@ public class MoveFieldAssignmentToInitializerAction extends BaseIntentionAction
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
- final PsiAssignmentExpression assignment = getAssignmentUnderCaret(editor, file);
+ PsiAssignmentExpression assignment = getAssignmentUnderCaret(editor, file);
if (assignment == null) return;
PsiField field = getAssignedField(assignment);
if (field == null) return;
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
- ArrayList<PsiAssignmentExpression> assignments = new ArrayList<PsiAssignmentExpression>();
+ List<PsiAssignmentExpression> assignments = new ArrayList<PsiAssignmentExpression>();
if (!isInitializedWithSameExpression(field, assignment, assignments)) return;
PsiExpression initializer = assignment.getRExpression();
field.setInitializer(initializer);
@@ -174,10 +183,10 @@ public class MoveFieldAssignmentToInitializerAction extends BaseIntentionAction
for (PsiAssignmentExpression assignmentExpression : assignments) {
PsiElement statement = assignmentExpression.getParent();
PsiElement parent = statement.getParent();
- if (parent instanceof PsiIfStatement
- || parent instanceof PsiWhileStatement
- || parent instanceof PsiForStatement
- || parent instanceof PsiForeachStatement) {
+ if (parent instanceof PsiIfStatement ||
+ parent instanceof PsiWhileStatement ||
+ parent instanceof PsiForStatement ||
+ parent instanceof PsiForeachStatement) {
PsiStatement emptyStatement =
JavaPsiFacade.getInstance(file.getProject()).getElementFactory().createStatementFromText(";", statement);
statement.replace(emptyStatement);
@@ -187,8 +196,7 @@ public class MoveFieldAssignmentToInitializerAction extends BaseIntentionAction
}
}
- EditorColorsManager manager = EditorColorsManager.getInstance();
- TextAttributes attributes = manager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
- HighlightManager.getInstance(project).addOccurrenceHighlights(editor, new PsiElement[] {field.getInitializer()}, attributes, false,null);
+ TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
+ HighlightManager.getInstance(project).addOccurrenceHighlights(editor, new PsiElement[]{field.getInitializer()}, attributes, false, null);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java
index 19f3322cc9eb..550da7277f81 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java
@@ -16,7 +16,7 @@
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.CodeInsightBundle;
-import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
+import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.openapi.editor.Editor;
@@ -69,7 +69,7 @@ public class MoveInitializerToConstructorAction extends BaseMoveInitializerToMet
final Iterator<PsiMethod> iterator = result.iterator();
//noinspection ForLoopThatDoesntUseLoopVariable
for (PsiMethod constructor = iterator.next(); iterator.hasNext(); constructor = iterator.next()) {
- final List<PsiMethod> chained = HighlightControlFlowUtil.getChainedConstructors(constructor);
+ final List<PsiMethod> chained = JavaHighlightUtil.getChainedConstructors(constructor);
if (chained != null) {
iterator.remove();
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/lookup/PackageLookupItem.java b/java/java-impl/src/com/intellij/codeInsight/lookup/PackageLookupItem.java
index 168d5444ca71..0ccd769911c3 100644
--- a/java/java-impl/src/com/intellij/codeInsight/lookup/PackageLookupItem.java
+++ b/java/java-impl/src/com/intellij/codeInsight/lookup/PackageLookupItem.java
@@ -34,7 +34,7 @@ class PackageLookupItem extends LookupItem<PsiPackage> {
public void handleInsert(InsertionContext context) {
super.handleInsert(context);
if (getTailType() == TailType.DOT || context.getCompletionChar() == '.') {
- AutoPopupController.getInstance(context.getProject()).scheduleAutoPopup(context.getEditor(), null);
+ AutoPopupController.getInstance(context.getProject()).scheduleAutoPopup(context.getEditor());
}
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java b/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java
index 9e89d7ac0126..49befb363437 100644
--- a/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java
+++ b/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java
@@ -17,7 +17,7 @@ package com.intellij.codeInsight.lookup;
import com.intellij.codeInsight.completion.*;
import com.intellij.diagnostic.LogMessageEx;
-import com.intellij.diagnostic.errordialog.Attachment;
+import com.intellij.diagnostic.AttachmentFactory;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
@@ -300,7 +300,7 @@ public class PsiTypeLookupItem extends LookupItem {
"file.length=" + file.getTextLength() + "\n" +
"document=" + context.getDocument() + "\n" +
DebugUtil.currentStackTrace(),
- new Attachment(context.getDocument())));
+ AttachmentFactory.createAttachment(context.getDocument())));
return;
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java b/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
deleted file mode 100644
index 354af57cf7d1..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/RedundantSuppressInspection.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInspection;
-
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInsight.daemon.impl.RemoveSuppressWarningAction;
-import com.intellij.codeInspection.ex.*;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.codeInspection.ui.InspectionToolPresentation;
-import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.WriteExternalException;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.containers.BidirectionalMap;
-import gnu.trove.THashMap;
-import gnu.trove.THashSet;
-import org.jdom.Element;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.util.*;
-
-/**
- * @author cdr
- */
-public class RedundantSuppressInspection extends GlobalInspectionTool{
- private BidirectionalMap<String, QuickFix> myQuickFixes = null;
- private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.RedundantSuppressInspection");
-
- public boolean IGNORE_ALL = false;
-
- @Override
- @NotNull
- public String getGroupDisplayName() {
- return GroupNames.DECLARATION_REDUNDANCY;
- }
-
- @Override
- @NotNull
- public String getDisplayName() {
- return InspectionsBundle.message("inspection.redundant.suppression.name");
- }
-
- @Override
- @NotNull
- @NonNls
- public String getShortName() {
- return "RedundantSuppression";
- }
-
- @Override
- public JComponent createOptionsPanel() {
- return new SingleCheckboxOptionsPanel("Ignore @SuppressWarning(\"ALL\")", this, "IGNORE_ALL");
- }
-
- @Override
- public void writeSettings(@NotNull Element node) throws WriteExternalException {
- if (IGNORE_ALL) {
- super.writeSettings(node);
- }
- }
-
- @Override
- public void runInspection(@NotNull final AnalysisScope scope,
- @NotNull final InspectionManager manager,
- @NotNull final GlobalInspectionContext globalContext,
- @NotNull final ProblemDescriptionsProcessor problemDescriptionsProcessor) {
- globalContext.getRefManager().iterate(new RefJavaVisitor() {
- @Override public void visitClass(@NotNull RefClass refClass) {
- if (!globalContext.shouldCheck(refClass, RedundantSuppressInspection.this)) return;
- CommonProblemDescriptor[] descriptors = checkElement(refClass, manager, globalContext.getProject());
- if (descriptors != null) {
- for (CommonProblemDescriptor descriptor : descriptors) {
- if (descriptor instanceof ProblemDescriptor) {
- final PsiElement psiElement = ((ProblemDescriptor)descriptor).getPsiElement();
- final PsiMember member = PsiTreeUtil.getParentOfType(psiElement, PsiMember.class);
- final RefElement refElement = globalContext.getRefManager().getReference(member);
- if (refElement != null) {
- problemDescriptionsProcessor.addProblemElement(refElement, descriptor);
- continue;
- }
- }
- problemDescriptionsProcessor.addProblemElement(refClass, descriptor);
- }
- }
- }
- });
- }
-
- @Nullable
- private CommonProblemDescriptor[] checkElement(@NotNull RefClass refEntity, @NotNull InspectionManager manager, @NotNull Project project) {
- final PsiClass psiClass = refEntity.getElement();
- if (psiClass == null) return null;
- return checkElement(psiClass, manager, project);
- }
-
- public CommonProblemDescriptor[] checkElement(@NotNull final PsiElement psiElement, @NotNull final InspectionManager manager, @NotNull Project project) {
- final Map<PsiElement, Collection<String>> suppressedScopes = new THashMap<PsiElement, Collection<String>>();
- psiElement.accept(new JavaRecursiveElementWalkingVisitor() {
- @Override public void visitModifierList(PsiModifierList list) {
- super.visitModifierList(list);
- final PsiElement parent = list.getParent();
- if (parent instanceof PsiModifierListOwner && !(parent instanceof PsiClass)) {
- checkElement(parent);
- }
- }
-
- @Override public void visitComment(PsiComment comment) {
- checkElement(comment);
- }
-
- @Override public void visitClass(PsiClass aClass) {
- if (aClass == psiElement) {
- super.visitClass(aClass);
- checkElement(aClass);
- }
- }
-
-
- private void checkElement(final PsiElement owner) {
- String idsString = SuppressManager.getInstance().getSuppressedInspectionIdsIn(owner);
- if (idsString != null && !idsString.isEmpty()) {
- List<String> ids = StringUtil.split(idsString, ",");
- if (IGNORE_ALL && (ids.contains(SuppressionUtil.ALL) || ids.contains(SuppressionUtil.ALL.toLowerCase()))) return;
- Collection<String> suppressed = suppressedScopes.get(owner);
- if (suppressed == null) {
- suppressed = ids;
- }
- else {
- for (String id : ids) {
- if (!suppressed.contains(id)) {
- suppressed.add(id);
- }
- }
- }
- suppressedScopes.put(owner, suppressed);
- }
- }
- });
-
- if (suppressedScopes.values().isEmpty()) return null;
- // have to visit all file from scratch since inspections can be written in any perversive way including checkFile() overriding
- Collection<InspectionToolWrapper> suppressedTools = new THashSet<InspectionToolWrapper>();
- InspectionToolWrapper[] toolWrappers = getInspectionTools(psiElement, manager);
- for (Collection<String> ids : suppressedScopes.values()) {
- for (Iterator<String> iterator = ids.iterator(); iterator.hasNext(); ) {
- final String shortName = iterator.next().trim();
- for (InspectionToolWrapper toolWrapper : toolWrappers) {
- if (toolWrapper instanceof LocalInspectionToolWrapper && ((LocalInspectionToolWrapper)toolWrapper).getTool().getID().equals(shortName)) {
- if (((LocalInspectionToolWrapper)toolWrapper).isUnfair()) {
- iterator.remove();
- break;
- }
- else {
- suppressedTools.add(toolWrapper);
- }
- }
- else if (toolWrapper.getShortName().equals(shortName)) {
- //ignore global unused as it won't be checked anyway
- if (toolWrapper instanceof LocalInspectionToolWrapper || toolWrapper instanceof GlobalInspectionToolWrapper) {
- suppressedTools.add(toolWrapper);
- }
- else {
- iterator.remove();
- break;
- }
- }
- }
- }
- }
-
- final AnalysisScope scope = new AnalysisScope(psiElement.getContainingFile());
- final InspectionManagerEx inspectionManagerEx = (InspectionManagerEx)InspectionManager.getInstance(project);
- final GlobalInspectionContextImpl globalContext = inspectionManagerEx.createNewGlobalContext(false);
- globalContext.setCurrentScope(scope);
- final RefManagerImpl refManager = (RefManagerImpl)globalContext.getRefManager();
- refManager.inspectionReadActionStarted();
- final List<ProblemDescriptor> result;
- try {
- result = new ArrayList<ProblemDescriptor>();
- for (InspectionToolWrapper toolWrapper : suppressedTools) {
- String toolId = toolWrapper instanceof LocalInspectionToolWrapper ? ((LocalInspectionToolWrapper)toolWrapper).getTool().getID() : toolWrapper.getShortName();
- toolWrapper.initialize(globalContext);
- Collection<CommonProblemDescriptor> descriptors;
- final InspectionToolPresentation presentation = globalContext.getPresentation(toolWrapper);
- if (toolWrapper instanceof LocalInspectionToolWrapper) {
- LocalInspectionToolWrapper local = (LocalInspectionToolWrapper)toolWrapper;
- if (local.isUnfair()) continue; //cant't work with passes other than LocalInspectionPass
- List<ProblemDescriptor> results = local.getTool().processFile(psiElement.getContainingFile(), manager);
- InspectionToolPresentation toolPresentation = globalContext.getPresentation(local);
- LocalDescriptorsUtil.addProblemDescriptors(results, toolPresentation, false, globalContext, local.getTool());
- descriptors = presentation.getProblemDescriptors();
- }
- else if (toolWrapper instanceof GlobalInspectionToolWrapper) {
- final GlobalInspectionToolWrapper global = (GlobalInspectionToolWrapper)toolWrapper;
- GlobalInspectionTool globalTool = global.getTool();
- if (globalTool.isGraphNeeded()) {
- refManager.findAllDeclarations();
- }
- final InspectionToolPresentation toolPresentation = globalContext.getPresentation(global);
- globalContext.getRefManager().iterate(new RefVisitor() {
- @Override public void visitElement(@NotNull RefEntity refEntity) {
- CommonProblemDescriptor[]
- descriptors1 = global.getTool().checkElement(refEntity, scope, manager, globalContext, toolPresentation);
- if (descriptors1 != null) {
- toolPresentation.addProblemElement(refEntity, false, descriptors1);
- }
- }
- });
- descriptors = presentation.getProblemDescriptors();
- }
- else {
- continue;
- }
- for (PsiElement suppressedScope : suppressedScopes.keySet()) {
- Collection<String> suppressedIds = suppressedScopes.get(suppressedScope);
- if (!suppressedIds.contains(toolId)) continue;
- for (CommonProblemDescriptor descriptor : descriptors) {
- if (!(descriptor instanceof ProblemDescriptor)) continue;
- PsiElement element = ((ProblemDescriptor)descriptor).getPsiElement();
- if (element == null) continue;
- PsiElement annotation = SuppressManager.getInstance().getElementToolSuppressedIn(element, toolId);
- if (annotation != null && PsiTreeUtil.isAncestor(suppressedScope, annotation, false) || annotation == null && !PsiTreeUtil.isAncestor(suppressedScope, element, false)) {
- suppressedIds.remove(toolId);
- break;
- }
- }
- }
- }
- for (PsiElement suppressedScope : suppressedScopes.keySet()) {
- Collection<String> suppressedIds = suppressedScopes.get(suppressedScope);
- for (String toolId : suppressedIds) {
- PsiMember psiMember;
- String problemLine = null;
- if (suppressedScope instanceof PsiMember) {
- psiMember = (PsiMember)suppressedScope;
- }
- else {
- psiMember = PsiTreeUtil.getParentOfType(suppressedScope, PsiDocCommentOwner.class);
- final PsiStatement statement = PsiTreeUtil.getNextSiblingOfType(suppressedScope, PsiStatement.class);
- problemLine = statement != null ? statement.getText() : null;
- }
- if (psiMember != null && psiMember.isValid()) {
- String description = InspectionsBundle.message("inspection.redundant.suppression.description");
- if (myQuickFixes == null) myQuickFixes = new BidirectionalMap<String, QuickFix>();
- final String key = toolId + (problemLine != null ? ";" + problemLine : "");
- QuickFix fix = myQuickFixes.get(key);
- if (fix == null) {
- fix = new RemoveSuppressWarningAction(toolId, problemLine);
- myQuickFixes.put(key, fix);
- }
- PsiElement identifier = null;
- if (psiMember instanceof PsiMethod) {
- identifier = ((PsiMethod)psiMember).getNameIdentifier();
- }
- else if (psiMember instanceof PsiField) {
- identifier = ((PsiField)psiMember).getNameIdentifier();
- }
- else if (psiMember instanceof PsiClass) {
- identifier = ((PsiClass)psiMember).getNameIdentifier();
- }
- if (identifier == null) {
- identifier = psiMember;
- }
- result.add(
- manager.createProblemDescriptor(identifier, description, (LocalQuickFix)fix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
- false));
- }
- }
- }
- }
- finally {
- refManager.inspectionReadActionFinished();
- globalContext.close(true);
- }
- return result.toArray(new ProblemDescriptor[result.size()]);
- }
-
- protected InspectionToolWrapper[] getInspectionTools(PsiElement psiElement, @NotNull InspectionManager manager) {
- ModifiableModel model = InspectionProjectProfileManager.getInstance(manager.getProject()).getInspectionProfile().getModifiableModel();
- InspectionProfileWrapper profile = new InspectionProfileWrapper((InspectionProfile)model);
- profile.init(manager.getProject());
-
- return profile.getInspectionTools(psiElement);
- }
-
-
- @Override
- @Nullable
- public QuickFix getQuickFix(final String hint) {
- return myQuickFixes != null ? myQuickFixes.get(hint) : new RemoveSuppressWarningAction(hint);
- }
-
-
- @Override
- @Nullable
- public String getHint(@NotNull final QuickFix fix) {
- if (myQuickFixes != null) {
- final List<String> list = myQuickFixes.getKeysByValue(fix);
- if (list != null) {
- LOG.assertTrue(list.size() == 1);
- return list.get(0);
- }
- }
- return null;
- }
-
- @Override
- public boolean isEnabledByDefault() {
- return false;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java b/java/java-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
index de7f6dcd3228..18ba50a4675f 100644
--- a/java/java-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
@@ -41,7 +41,7 @@ public class SuppressManagerImpl extends SuppressManager {
}
@NotNull
- private static SuppressIntentionAction[] convertBatchToSuppressIntentionActions(@NotNull SuppressQuickFix[] actions) {
+ public static SuppressIntentionAction[] convertBatchToSuppressIntentionActions(@NotNull SuppressQuickFix[] actions) {
return ContainerUtil.map2Array(actions, SuppressIntentionAction.class, new Function<SuppressQuickFix, SuppressIntentionAction>() {
@Override
public SuppressIntentionAction fun(SuppressQuickFix fix) {
diff --git a/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalAnnotator.java b/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalAnnotator.java
deleted file mode 100644
index 3b322ff616ee..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalAnnotator.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright 2000-2009 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.canBeFinal;
-
-import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.psi.*;
-import com.intellij.psi.controlFlow.*;
-import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-
-/**
- * User: anna
- * Date: 27-Dec-2005
- */
-class CanBeFinalAnnotator extends RefGraphAnnotatorEx {
- private final RefManager myManager;
- public static int CAN_BE_FINAL_MASK;
-
- public CanBeFinalAnnotator(@NotNull RefManager manager) {
- myManager = manager;
- }
-
- @Override
- public void initialize(RefManager refManager) {
- CAN_BE_FINAL_MASK = refManager.getLastUsedMask();
- }
-
- @Override
- public void onInitialize(RefElement refElement) {
- ((RefElementImpl)refElement).setFlag(true, CAN_BE_FINAL_MASK);
- if (refElement instanceof RefClass) {
- final RefClass refClass = (RefClass)refElement;
- final PsiClass psiClass = refClass.getElement();
- if (refClass.isEntry()) {
- ((RefClassImpl)refClass).setFlag(false, CAN_BE_FINAL_MASK);
- return;
- }
- if (refClass.isAbstract() || refClass.isAnonymous() || refClass.isInterface()) {
- ((RefClassImpl)refClass).setFlag(false, CAN_BE_FINAL_MASK);
- return;
- }
- if (!refClass.isSelfInheritor(psiClass)) {
- for (PsiClass psiSuperClass : psiClass.getSupers()) {
- if (myManager.belongsToScope(psiSuperClass)) {
- RefClass refSuperClass = (RefClass)myManager.getReference(psiSuperClass);
- if (refSuperClass != null) {
- ((RefClassImpl)refSuperClass).setFlag(false, CAN_BE_FINAL_MASK);
- }
- }
- }
- }
- }
- else if (refElement instanceof RefMethod) {
- final RefMethod refMethod = (RefMethod)refElement;
- final PsiElement element = refMethod.getElement();
- if (element instanceof PsiMethod) {
- PsiMethod psiMethod = (PsiMethod)element;
- if (refMethod.isConstructor() || refMethod.isAbstract() || refMethod.isStatic() ||
- PsiModifier.PRIVATE.equals(refMethod.getAccessModifier()) || refMethod.getOwnerClass().isAnonymous() ||
- refMethod.getOwnerClass().isInterface()) {
- ((RefMethodImpl)refMethod).setFlag(false, CAN_BE_FINAL_MASK);
- }
- if (PsiModifier.PRIVATE.equals(refMethod.getAccessModifier()) && refMethod.getOwner() != null &&
- !(refMethod.getOwnerClass().getOwner() instanceof RefElement)) {
- ((RefMethodImpl)refMethod).setFlag(false, CAN_BE_FINAL_MASK);
- }
- for (PsiMethod psiSuperMethod : psiMethod.findSuperMethods()) {
- if (myManager.belongsToScope(psiSuperMethod)) {
- RefMethod refSuperMethod = (RefMethod)myManager.getReference(psiSuperMethod);
- if (refSuperMethod != null) {
- ((RefMethodImpl)refSuperMethod).setFlag(false, CAN_BE_FINAL_MASK);
- }
- }
- }
- }
- }
- }
-
-
- @Override
- public void onMarkReferenced(RefElement refWhat,
- RefElement refFrom,
- boolean referencedFromClassInitializer,
- boolean forReading,
- boolean forWriting) {
- if (!(refWhat instanceof RefField)) return;
- if (!(refFrom instanceof RefMethod) ||
- !((RefMethod)refFrom).isConstructor() ||
- ((PsiField)refWhat.getElement()).hasInitializer() ||
- ((RefMethod)refFrom).getOwnerClass() != ((RefField)refWhat).getOwnerClass() ||
- ((RefField)refWhat).isStatic()) {
- if (!referencedFromClassInitializer && forWriting) {
- ((RefFieldImpl)refWhat).setFlag(false, CAN_BE_FINAL_MASK);
- }
- }
- }
-
- @Override
- public void onReferencesBuild(RefElement refElement) {
- if (refElement instanceof RefClass) {
- final PsiClass psiClass = (PsiClass)refElement.getElement();
- if (psiClass != null) {
-
- if (refElement.isEntry()) {
- ((RefClassImpl)refElement).setFlag(false, CAN_BE_FINAL_MASK);
- }
-
- PsiMethod[] psiMethods = psiClass.getMethods();
- PsiField[] psiFields = psiClass.getFields();
-
- HashSet<PsiVariable> allFields = new HashSet<PsiVariable>();
- ContainerUtil.addAll(allFields, psiFields);
- ArrayList<PsiVariable> instanceInitializerInitializedFields = new ArrayList<PsiVariable>();
- boolean hasInitializers = false;
- for (PsiClassInitializer initializer : psiClass.getInitializers()) {
- PsiCodeBlock body = initializer.getBody();
- hasInitializers = true;
- ControlFlow flow;
- try {
- flow = ControlFlowFactory.getInstance(body.getProject())
- .getControlFlow(body, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false);
- }
- catch (AnalysisCanceledException e) {
- flow = ControlFlow.EMPTY;
- }
- Collection<PsiVariable> writtenVariables = new ArrayList<PsiVariable>();
- ControlFlowUtil.getWrittenVariables(flow, 0, flow.getSize(), false, writtenVariables);
- for (PsiVariable psiVariable : writtenVariables) {
- if (allFields.contains(psiVariable)) {
- if (instanceInitializerInitializedFields.contains(psiVariable)) {
- allFields.remove(psiVariable);
- instanceInitializerInitializedFields.remove(psiVariable);
- }
- else {
- instanceInitializerInitializedFields.add(psiVariable);
- }
- }
- }
- for (PsiVariable psiVariable : writtenVariables) {
- if (!instanceInitializerInitializedFields.contains(psiVariable)) {
- allFields.remove(psiVariable);
- }
- }
- }
-
- for (PsiMethod psiMethod : psiMethods) {
- if (psiMethod.isConstructor()) {
- PsiCodeBlock body = psiMethod.getBody();
- if (body != null) {
- hasInitializers = true;
- ControlFlow flow;
- try {
- flow = ControlFlowFactory.getInstance(body.getProject())
- .getControlFlow(body, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false);
- }
- catch (AnalysisCanceledException e) {
- flow = ControlFlow.EMPTY;
- }
-
- Collection<PsiVariable> writtenVariables = ControlFlowUtil.getWrittenVariables(flow, 0, flow.getSize(), false);
- for (PsiVariable psiVariable : writtenVariables) {
- if (instanceInitializerInitializedFields.contains(psiVariable)) {
- allFields.remove(psiVariable);
- instanceInitializerInitializedFields.remove(psiVariable);
- }
- }
- List<PsiMethod> redirectedConstructors = HighlightControlFlowUtil.getChainedConstructors(psiMethod);
- if (redirectedConstructors == null || redirectedConstructors.isEmpty()) {
- List<PsiVariable> ssaVariables = ControlFlowUtil.getSSAVariables(flow);
- ArrayList<PsiVariable> good = new ArrayList<PsiVariable>(ssaVariables);
- good.addAll(instanceInitializerInitializedFields);
- allFields.retainAll(good);
- }
- else {
- allFields.removeAll(writtenVariables);
- }
- }
- }
- }
-
- for (PsiField psiField : psiFields) {
- if ((!hasInitializers || !allFields.contains(psiField)) && psiField.getInitializer() == null) {
- final RefFieldImpl refField = (RefFieldImpl)myManager.getReference(psiField);
- if (refField != null) {
- refField.setFlag(false, CAN_BE_FINAL_MASK);
- }
- }
- }
-
- }
- }
- else if (refElement instanceof RefMethod) {
- final RefMethod refMethod = (RefMethod)refElement;
- if (refMethod.isEntry()) {
- ((RefMethodImpl)refMethod).setFlag(false, CAN_BE_FINAL_MASK);
- }
- }
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java b/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java
deleted file mode 100644
index 105bee1c4449..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Dec 24, 2001
- * Time: 2:46:32 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.canBeFinal;
-
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.FileModificationService;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import java.awt.*;
-
-public class CanBeFinalInspection extends GlobalJavaInspectionTool {
- private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.canBeFinal.CanBeFinalInspection");
-
- public boolean REPORT_CLASSES = false;
- public boolean REPORT_METHODS = false;
- public boolean REPORT_FIELDS = true;
- public static final String DISPLAY_NAME = InspectionsBundle.message("inspection.can.be.final.display.name");
- @NonNls public static final String SHORT_NAME = "CanBeFinal";
- @NonNls private static final String QUICK_FIX_NAME = InspectionsBundle.message("inspection.can.be.final.accept.quickfix");
-
- private class OptionsPanel extends JPanel {
- private final JCheckBox myReportClassesCheckbox;
- private final JCheckBox myReportMethodsCheckbox;
- private final JCheckBox myReportFieldsCheckbox;
-
- private OptionsPanel() {
- super(new GridBagLayout());
-
- GridBagConstraints gc = new GridBagConstraints();
- gc.weighty = 0;
- gc.weightx = 1;
- gc.fill = GridBagConstraints.HORIZONTAL;
- gc.anchor = GridBagConstraints.NORTHWEST;
-
-
- myReportClassesCheckbox = new JCheckBox(InspectionsBundle.message("inspection.can.be.final.option"));
- myReportClassesCheckbox.setSelected(REPORT_CLASSES);
- myReportClassesCheckbox.getModel().addChangeListener(new ChangeListener() {
- @Override
- public void stateChanged(ChangeEvent e) {
- REPORT_CLASSES = myReportClassesCheckbox.isSelected();
- }
- });
- gc.gridy = 0;
- add(myReportClassesCheckbox, gc);
-
- myReportMethodsCheckbox = new JCheckBox(InspectionsBundle.message("inspection.can.be.final.option1"));
- myReportMethodsCheckbox.setSelected(REPORT_METHODS);
- myReportMethodsCheckbox.getModel().addChangeListener(new ChangeListener() {
- @Override
- public void stateChanged(ChangeEvent e) {
- REPORT_METHODS = myReportMethodsCheckbox.isSelected();
- }
- });
- gc.gridy++;
- add(myReportMethodsCheckbox, gc);
-
- myReportFieldsCheckbox = new JCheckBox(InspectionsBundle.message("inspection.can.be.final.option2"));
- myReportFieldsCheckbox.setSelected(REPORT_FIELDS);
- myReportFieldsCheckbox.getModel().addChangeListener(new ChangeListener() {
- @Override
- public void stateChanged(ChangeEvent e) {
- REPORT_FIELDS = myReportFieldsCheckbox.isSelected();
- }
- });
-
- gc.weighty = 1;
- gc.gridy++;
- add(myReportFieldsCheckbox, gc);
- }
- }
-
- public boolean isReportClasses() {
- return REPORT_CLASSES;
- }
-
- public boolean isReportMethods() {
- return REPORT_METHODS;
- }
-
- public boolean isReportFields() {
- return REPORT_FIELDS;
- }
-
- @Override
- public JComponent createOptionsPanel() {
- return new OptionsPanel();
- }
-
- @Override
- @Nullable
- public RefGraphAnnotator getAnnotator(@NotNull final RefManager refManager) {
- return new CanBeFinalAnnotator(refManager);
- }
-
-
- @Override
- @Nullable
- public CommonProblemDescriptor[] checkElement(@NotNull final RefEntity refEntity,
- @NotNull final AnalysisScope scope,
- @NotNull final InspectionManager manager,
- @NotNull final GlobalInspectionContext globalContext,
- @NotNull final ProblemDescriptionsProcessor processor) {
- if (refEntity instanceof RefJavaElement) {
- final RefJavaElement refElement = (RefJavaElement)refEntity;
- if (refElement instanceof RefParameter) return null;
- if (!refElement.isReferenced()) return null;
- if (refElement.isSyntheticJSP()) return null;
- if (refElement.isFinal()) return null;
- if (!((RefElementImpl)refElement).checkFlag(CanBeFinalAnnotator.CAN_BE_FINAL_MASK)) return null;
-
- final PsiMember psiMember = (PsiMember)refElement.getElement();
- if (psiMember == null || !CanBeFinalHandler.allowToBeFinal(psiMember)) return null;
-
- PsiIdentifier psiIdentifier = null;
- if (refElement instanceof RefClass) {
- RefClass refClass = (RefClass)refElement;
- if (refClass.isInterface() || refClass.isAnonymous() || refClass.isAbstract()) return null;
- if (!isReportClasses()) return null;
- psiIdentifier = ((PsiClass)psiMember).getNameIdentifier();
- }
- else if (refElement instanceof RefMethod) {
- RefMethod refMethod = (RefMethod)refElement;
- if (refMethod.getOwnerClass().isFinal()) return null;
- if (!isReportMethods()) return null;
- psiIdentifier = ((PsiMethod)psiMember).getNameIdentifier();
- }
- else if (refElement instanceof RefField) {
- if (!isReportFields()) return null;
- psiIdentifier = ((PsiField)psiMember).getNameIdentifier();
- }
-
-
- if (psiIdentifier != null) {
- return new ProblemDescriptor[]{manager.createProblemDescriptor(psiIdentifier, InspectionsBundle.message(
- "inspection.export.results.can.be.final.description"), new AcceptSuggested(globalContext.getRefManager()),
- ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false)};
- }
- }
- return null;
- }
-
- @Override
- protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager,
- @NotNull final GlobalJavaInspectionContext globalContext,
- @NotNull final ProblemDescriptionsProcessor problemsProcessor) {
- for (RefElement entryPoint : globalContext.getEntryPointsManager(manager).getEntryPoints()) {
- problemsProcessor.ignoreElement(entryPoint);
- }
-
- manager.iterate(new RefJavaVisitor() {
- @Override public void visitElement(@NotNull RefEntity refEntity) {
- if (problemsProcessor.getDescriptions(refEntity) == null) return;
- refEntity.accept(new RefJavaVisitor() {
- @Override public void visitMethod(@NotNull final RefMethod refMethod) {
- if (!refMethod.isStatic() && !PsiModifier.PRIVATE.equals(refMethod.getAccessModifier()) &&
- !(refMethod instanceof RefImplicitConstructor)) {
- globalContext.enqueueDerivedMethodsProcessor(refMethod, new GlobalJavaInspectionContext.DerivedMethodsProcessor() {
- @Override
- public boolean process(PsiMethod derivedMethod) {
- ((RefElementImpl)refMethod).setFlag(false, CanBeFinalAnnotator.CAN_BE_FINAL_MASK);
- problemsProcessor.ignoreElement(refMethod);
- return false;
- }
- });
- }
- }
-
- @Override public void visitClass(@NotNull final RefClass refClass) {
- if (!refClass.isAnonymous()) {
- globalContext.enqueueDerivedClassesProcessor(refClass, new GlobalJavaInspectionContext.DerivedClassesProcessor() {
- @Override
- public boolean process(PsiClass inheritor) {
- ((RefClassImpl)refClass).setFlag(false, CanBeFinalAnnotator.CAN_BE_FINAL_MASK);
- problemsProcessor.ignoreElement(refClass);
- return false;
- }
- });
- }
- }
-
- @Override public void visitField(@NotNull final RefField refField) {
- globalContext.enqueueFieldUsagesProcessor(refField, new GlobalJavaInspectionContext.UsagesProcessor() {
- @Override
- public boolean process(PsiReference psiReference) {
- PsiElement expression = psiReference.getElement();
- if (expression instanceof PsiReferenceExpression && PsiUtil.isAccessedForWriting((PsiExpression)expression)) {
- ((RefFieldImpl)refField).setFlag(false, CanBeFinalAnnotator.CAN_BE_FINAL_MASK);
- problemsProcessor.ignoreElement(refField);
- return false;
- }
- return true;
- }
- });
- }
- });
-
- }
- });
-
- return false;
- }
-
-
- @Override
- @Nullable
- public QuickFix getQuickFix(final String hint) {
- return new AcceptSuggested(null);
- }
-
- @Override
- @NotNull
- public String getDisplayName() {
- return DISPLAY_NAME;
- }
-
- @Override
- @NotNull
- public String getGroupDisplayName() {
- return GroupNames.DECLARATION_REDUNDANCY;
- }
-
- @Override
- @NotNull
- public String getShortName() {
- return SHORT_NAME;
- }
-
- private static class AcceptSuggested implements LocalQuickFix {
- private final RefManager myManager;
-
- public AcceptSuggested(final RefManager manager) {
- myManager = manager;
- }
-
- @Override
- @NotNull
- public String getName() {
- return QUICK_FIX_NAME;
- }
-
- @Override
- @NotNull
- public String getFamilyName() {
- return getName();
- }
-
- @Override
- public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
- if (!FileModificationService.getInstance().preparePsiElementForWrite(descriptor.getPsiElement())) return;
- final PsiElement element = descriptor.getPsiElement();
- final PsiModifierListOwner psiElement = PsiTreeUtil.getParentOfType(element, PsiModifierListOwner.class);
- if (psiElement != null) {
- RefJavaElement refElement = (RefJavaElement)(myManager != null ? myManager.getReference(psiElement) : null);
- try {
- if (psiElement instanceof PsiVariable) {
- ((PsiVariable)psiElement).normalizeDeclaration();
- }
- final PsiModifierList modifierList = psiElement.getModifierList();
- LOG.assertTrue(modifierList != null);
- modifierList.setModifierProperty(PsiModifier.FINAL, true);
- }
- catch (IncorrectOperationException e) {
- LOG.error(e);
- }
-
- if (refElement != null) {
- RefJavaUtil.getInstance().setIsFinal(refElement, true);
- }
- }
- }
- }
-
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java
index c22571a65287..8943e59c4192 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java
@@ -47,6 +47,7 @@ public class DataFlowInspection extends DataFlowInspectionBase {
private class OptionsPanel extends JPanel {
private final JCheckBox myIgnoreAssertions;
+ private final JCheckBox myReportConstantReferences;
private final JCheckBox mySuggestNullables;
private final JCheckBox myDontReportTrueAsserts;
@@ -88,6 +89,15 @@ public class DataFlowInspection extends DataFlowInspectionBase {
}
});
+ myReportConstantReferences = new JCheckBox("Warn when reading a value guaranteed to be constant");
+ myReportConstantReferences.setSelected(REPORT_CONSTANT_REFERENCE_VALUES);
+ myReportConstantReferences.getModel().addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ REPORT_CONSTANT_REFERENCE_VALUES = myReportConstantReferences.isSelected();
+ }
+ });
+
gc.insets = new Insets(0, 0, 0, 0);
gc.gridy = 0;
add(mySuggestNullables, gc);
@@ -134,6 +144,9 @@ public class DataFlowInspection extends DataFlowInspectionBase {
gc.gridy++;
add(myIgnoreAssertions, gc);
+
+ gc.gridy++;
+ add(myReportConstantReferences, gc);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsEP.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsEP.java
new file mode 100644
index 000000000000..01f982f07b45
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsEP.java
@@ -0,0 +1,36 @@
+/*
+ * 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.codeInspection.deadCode;
+
+import com.intellij.codeInspection.InspectionEP;
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.intellij.codeInspection.InspectionsBundle;
+import org.jetbrains.annotations.NotNull;
+
+public class DummyEntryPointsEP extends InspectionEP {
+ public DummyEntryPointsEP() {
+ presentation = DummyEntryPointsPresentation.class.getName();
+ displayName = InspectionsBundle.message("inspection.dead.code.entry.points.display.name");
+ implementationClass = "";
+ shortName = "";
+ }
+
+ @NotNull
+ @Override
+ public InspectionProfileEntry instantiateTool() {
+ return new DummyEntryPointsTool();
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java
index 531c88c03f62..04fe0f2125d1 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInspection.deadCode;
+import com.intellij.codeInspection.GlobalJavaInspectionContext;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ex.*;
import com.intellij.codeInspection.reference.RefElement;
@@ -28,8 +29,8 @@ public class DummyEntryPointsPresentation extends UnusedDeclarationPresentation
private static final RefEntryPointFilter myFilter = new RefEntryPointFilter();
private QuickFixAction[] myQuickFixActions;
- public DummyEntryPointsPresentation(UnusedDeclarationInspection inspection, @NotNull InspectionToolWrapper toolWrapper) {
- super(toolWrapper);
+ public DummyEntryPointsPresentation(@NotNull InspectionToolWrapper toolWrapper, @NotNull GlobalInspectionContextImpl context) {
+ super(toolWrapper, context);
}
@Override
@@ -51,9 +52,9 @@ public class DummyEntryPointsPresentation extends UnusedDeclarationPresentation
}
@Override
- protected boolean applyFix(RefEntity[] refElements) {
+ protected boolean applyFix(@NotNull RefEntity[] refElements) {
final EntryPointsManager entryPointsManager =
- getContext().getExtension(GlobalJavaInspectionContextImpl.CONTEXT).getEntryPointsManager(getContext().getRefManager());
+ getContext().getExtension(GlobalJavaInspectionContext.CONTEXT).getEntryPointsManager(getContext().getRefManager());
for (RefEntity refElement : refElements) {
if (refElement instanceof RefElement) {
entryPointsManager.removeEntryPoint((RefElement)refElement);
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java
index 524f3338fad1..2b216dc844de 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsTool.java
@@ -20,17 +20,14 @@ import com.intellij.codeInspection.GlobalInspectionContext;
import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ProblemDescriptionsProcessor;
-import com.intellij.codeInspection.ex.InspectionPresentationProvider;
-import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.codeInspection.ex.JobDescriptor;
-import com.intellij.codeInspection.ui.InspectionToolPresentation;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author max
*/
-public class DummyEntryPointsTool extends UnusedDeclarationInspection implements InspectionPresentationProvider {
+public class DummyEntryPointsTool extends UnusedDeclarationInspection {
public DummyEntryPointsTool() {
}
@@ -64,10 +61,4 @@ public class DummyEntryPointsTool extends UnusedDeclarationInspection implements
public String getShortName() {
return "";
}
-
- @NotNull
- @Override
- public InspectionToolPresentation createPresentation(@NotNull InspectionToolWrapper toolWrapper) {
- return new DummyEntryPointsPresentation(this, toolWrapper);
- }
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/RefEntryPointFilter.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/RefEntryPointFilter.java
index 02731b765fbc..03ab97994afd 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/RefEntryPointFilter.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/RefEntryPointFilter.java
@@ -27,10 +27,11 @@ package com.intellij.codeInspection.deadCode;
import com.intellij.codeInspection.reference.RefJavaElement;
import com.intellij.codeInspection.reference.RefParameter;
import com.intellij.codeInspection.util.RefFilter;
+import org.jetbrains.annotations.NotNull;
public class RefEntryPointFilter extends RefFilter {
@Override
- public int getElementProblemCount(RefJavaElement refElement) {
+ public int getElementProblemCount(@NotNull RefJavaElement refElement) {
if (refElement instanceof RefParameter) return 0;
return refElement.isEntry() && !refElement.isSyntheticJSP() ? 1 : 0;
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java
deleted file mode 100644
index b00d7490ecc7..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/RefUnreachableFilter.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Dec 2, 2001
- * Time: 12:07:30 AM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.deadCode;
-
-import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.codeInspection.util.RefFilter;
-import org.jetbrains.annotations.NotNull;
-
-public class RefUnreachableFilter extends RefFilter {
- @NotNull
- protected UnusedDeclarationInspection myTool;
- @NotNull protected final GlobalInspectionContextImpl myContext;
-
- public RefUnreachableFilter(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) {
- myTool = tool;
- myContext = context;
- }
-
- @Override
- public int getElementProblemCount(RefJavaElement refElement) {
- if (refElement instanceof RefParameter) return 0;
- if (refElement.isSyntheticJSP()) return 0;
- if (!(refElement instanceof RefMethod || refElement instanceof RefClass || refElement instanceof RefField)) return 0;
- if (!myContext.isToCheckMember(refElement, myTool)) return 0;
- return ((RefElementImpl)refElement).isSuspicious() ? 1 : 0;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java
deleted file mode 100644
index 923e5777f6d1..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnreferencedFilter.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Dec 2, 2001
- * Time: 12:14:37 AM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.deadCode;
-
-import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
-import com.intellij.codeInspection.reference.*;
-import org.jetbrains.annotations.NotNull;
-
-public class UnreferencedFilter extends RefUnreachableFilter {
- public UnreferencedFilter(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) {
- super(tool, context);
- }
-
- @Override
- public int getElementProblemCount(RefJavaElement refElement) {
- if (refElement instanceof RefParameter) return 0;
- if (refElement.isEntry() || !((RefElementImpl)refElement).isSuspicious() || refElement.isSyntheticJSP()) return 0;
-
- if (!(refElement instanceof RefMethod || refElement instanceof RefClass || refElement instanceof RefField)) return 0;
- if (!myContext.isToCheckMember(refElement, myTool)) return 0;
-
- if (refElement instanceof RefField) {
- RefField refField = (RefField) refElement;
- if (refField.isUsedForReading() && !refField.isUsedForWriting()) return 1;
- if (refField.isUsedForWriting() && !refField.isUsedForReading()) return 1;
- }
-
- if (refElement instanceof RefClass && ((RefClass)refElement).isAnonymous()) return 0;
- return -1;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java
deleted file mode 100644
index 7799cc205f67..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java
+++ /dev/null
@@ -1,820 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Oct 12, 2001
- * Time: 9:40:45 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-
-package com.intellij.codeInspection.deadCode;
-
-import com.intellij.ExtensionPoints;
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.AnnotationUtil;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
-import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtilBase;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.ex.*;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.codeInspection.ui.InspectionToolPresentation;
-import com.intellij.codeInspection.util.RefFilter;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.extensions.ExtensionPoint;
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.InvalidDataException;
-import com.intellij.openapi.util.WriteExternalException;
-import com.intellij.psi.*;
-import com.intellij.psi.impl.PsiClassImplUtil;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.PsiNonJavaFileReferenceProcessor;
-import com.intellij.psi.search.PsiSearchHelper;
-import com.intellij.psi.util.PsiMethodUtil;
-import com.intellij.ui.IdeBorderFactory;
-import com.intellij.ui.SeparatorFactory;
-import com.intellij.util.containers.HashMap;
-import org.jdom.Element;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.*;
-import java.util.List;
-
-public class UnusedDeclarationInspection extends GlobalInspectionTool implements InspectionPresentationProvider {
- public boolean ADD_MAINS_TO_ENTRIES = true;
-
- public boolean ADD_APPLET_TO_ENTRIES = true;
- public boolean ADD_SERVLET_TO_ENTRIES = true;
- public boolean ADD_NONJAVA_TO_ENTRIES = true;
-
- private Set<RefElement> myProcessedSuspicious = null;
- private int myPhase;
- public static final String DISPLAY_NAME = InspectionsBundle.message("inspection.dead.code.display.name");
- @NonNls public static final String SHORT_NAME = "UnusedDeclaration";
- @NonNls private static final String ALTERNATIVE_ID = "unused";
-
- public final EntryPoint[] myExtensions;
- private static final Logger LOG = Logger.getInstance("#" + UnusedDeclarationInspection.class.getName());
- private GlobalInspectionContextImpl myContext;
-
- public UnusedDeclarationInspection() {
- ExtensionPoint<EntryPoint> point = Extensions.getRootArea().getExtensionPoint(ExtensionPoints.DEAD_CODE_TOOL);
- final EntryPoint[] deadCodeAddins = new EntryPoint[point.getExtensions().length];
- EntryPoint[] extensions = point.getExtensions();
- for (int i = 0, extensionsLength = extensions.length; i < extensionsLength; i++) {
- EntryPoint entryPoint = extensions[i];
- try {
- deadCodeAddins[i] = entryPoint.clone();
- }
- catch (CloneNotSupportedException e) {
- LOG.error(e);
- }
- }
- Arrays.sort(deadCodeAddins, new Comparator<EntryPoint>() {
- @Override
- public int compare(final EntryPoint o1, final EntryPoint o2) {
- return o1.getDisplayName().compareToIgnoreCase(o2.getDisplayName());
- }
- });
- myExtensions = deadCodeAddins;
- }
-
- private GlobalInspectionContextImpl getContext() {
- return myContext;
- }
-
- private class OptionsPanel extends JPanel {
- private final JCheckBox myMainsCheckbox;
- private final JCheckBox myAppletToEntries;
- private final JCheckBox myServletToEntries;
- private final JCheckBox myNonJavaCheckbox;
-
- private OptionsPanel() {
- super(new GridBagLayout());
- GridBagConstraints gc = new GridBagConstraints();
- gc.weightx = 1;
- gc.weighty = 0;
- gc.insets = new Insets(0, IdeBorderFactory.TITLED_BORDER_INDENT, 2, 0);
- gc.fill = GridBagConstraints.HORIZONTAL;
- gc.anchor = GridBagConstraints.NORTHWEST;
-
- myMainsCheckbox = new JCheckBox(InspectionsBundle.message("inspection.dead.code.option"));
- myMainsCheckbox.setSelected(ADD_MAINS_TO_ENTRIES);
- myMainsCheckbox.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- ADD_MAINS_TO_ENTRIES = myMainsCheckbox.isSelected();
- }
- });
-
- gc.gridy = 0;
- add(myMainsCheckbox, gc);
-
- myAppletToEntries = new JCheckBox(InspectionsBundle.message("inspection.dead.code.option3"));
- myAppletToEntries.setSelected(ADD_APPLET_TO_ENTRIES);
- myAppletToEntries.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- ADD_APPLET_TO_ENTRIES = myAppletToEntries.isSelected();
- }
- });
- gc.gridy++;
- add(myAppletToEntries, gc);
-
- myServletToEntries = new JCheckBox(InspectionsBundle.message("inspection.dead.code.option4"));
- myServletToEntries.setSelected(ADD_SERVLET_TO_ENTRIES);
- myServletToEntries.addActionListener(new ActionListener(){
- @Override
- public void actionPerformed(ActionEvent e) {
- ADD_SERVLET_TO_ENTRIES = myServletToEntries.isSelected();
- }
- });
- gc.gridy++;
- add(myServletToEntries, gc);
-
- for (final EntryPoint extension : myExtensions) {
- if (extension.showUI()) {
- final JCheckBox extCheckbox = new JCheckBox(extension.getDisplayName());
- extCheckbox.setSelected(extension.isSelected());
- extCheckbox.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- extension.setSelected(extCheckbox.isSelected());
- }
- });
- gc.gridy++;
- add(extCheckbox, gc);
- }
- }
-
- myNonJavaCheckbox =
- new JCheckBox(InspectionsBundle.message("inspection.dead.code.option5"));
- myNonJavaCheckbox.setSelected(ADD_NONJAVA_TO_ENTRIES);
- myNonJavaCheckbox.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- ADD_NONJAVA_TO_ENTRIES = myNonJavaCheckbox.isSelected();
- }
- });
-
- gc.gridy++;
- add(myNonJavaCheckbox, gc);
-
- final JButton configureAnnotations = EntryPointsManagerImpl.createConfigureAnnotationsBtn(this);
- gc.fill = GridBagConstraints.NONE;
- gc.gridy++;
- gc.insets.top = 10;
- gc.weighty = 1;
-
- add(configureAnnotations, gc);
- }
- }
-
- @Override
- public JComponent createOptionsPanel() {
- final JPanel scrollPane = new JPanel(new BorderLayout());
- scrollPane.add(SeparatorFactory.createSeparator("Entry points", null), BorderLayout.NORTH);
- scrollPane.add(new OptionsPanel(), BorderLayout.CENTER);
- return scrollPane;
- }
-
- private boolean isAddMainsEnabled() {
- return ADD_MAINS_TO_ENTRIES;
- }
-
- private boolean isAddAppletEnabled() {
- return ADD_APPLET_TO_ENTRIES;
- }
-
- private boolean isAddServletEnabled() {
- return ADD_SERVLET_TO_ENTRIES;
- }
-
- private boolean isAddNonJavaUsedEnabled() {
- return ADD_NONJAVA_TO_ENTRIES;
- }
-
- @Override
- @NotNull
- public String getDisplayName() {
- return DISPLAY_NAME;
- }
-
- @Override
- @NotNull
- public String getGroupDisplayName() {
- return GroupNames.DECLARATION_REDUNDANCY;
- }
-
- @Override
- @NotNull
- public String getShortName() {
- return SHORT_NAME;
- }
-
- @Override
- public void readSettings(@NotNull Element node) throws InvalidDataException {
- super.readSettings(node);
- for (EntryPoint extension : myExtensions) {
- extension.readExternal(node);
- }
- }
-
- @Override
- public void writeSettings(@NotNull Element node) throws WriteExternalException {
- super.writeSettings(node);
- for (EntryPoint extension : myExtensions) {
- extension.writeExternal(node);
- }
- }
-
- private static boolean isExternalizableNoParameterConstructor(PsiMethod method, RefClass refClass) {
- if (!method.isConstructor()) return false;
- if (!method.hasModifierProperty(PsiModifier.PUBLIC)) return false;
- final PsiParameterList parameterList = method.getParameterList();
- if (parameterList.getParametersCount() != 0) return false;
- final PsiClass aClass = method.getContainingClass();
- return aClass == null || isExternalizable(aClass, refClass);
- }
-
- private static boolean isSerializationImplicitlyUsedField(PsiField field) {
- @NonNls final String name = field.getName();
- if (!HighlightUtilBase.SERIAL_VERSION_UID_FIELD_NAME.equals(name) && !"serialPersistentFields".equals(name)) return false;
- if (!field.hasModifierProperty(PsiModifier.STATIC)) return false;
- PsiClass aClass = field.getContainingClass();
- return aClass == null || isSerializable(aClass, null);
- }
-
- private static boolean isWriteObjectMethod(PsiMethod method, RefClass refClass) {
- @NonNls final String name = method.getName();
- if (!"writeObject".equals(name)) return false;
- PsiParameter[] parameters = method.getParameterList().getParameters();
- if (parameters.length != 1) return false;
- if (!parameters[0].getType().equalsToText("java.io.ObjectOutputStream")) return false;
- if (method.hasModifierProperty(PsiModifier.STATIC)) return false;
- PsiClass aClass = method.getContainingClass();
- return !(aClass != null && !isSerializable(aClass, refClass));
- }
-
- private static boolean isReadObjectMethod(PsiMethod method, RefClass refClass) {
- @NonNls final String name = method.getName();
- if (!"readObject".equals(name)) return false;
- PsiParameter[] parameters = method.getParameterList().getParameters();
- if (parameters.length != 1) return false;
- if (!parameters[0].getType().equalsToText("java.io.ObjectInputStream")) return false;
- if (method.hasModifierProperty(PsiModifier.STATIC)) return false;
- PsiClass aClass = method.getContainingClass();
- return !(aClass != null && !isSerializable(aClass, refClass));
- }
-
- private static boolean isWriteReplaceMethod(PsiMethod method, RefClass refClass) {
- @NonNls final String name = method.getName();
- if (!"writeReplace".equals(name)) return false;
- PsiParameter[] parameters = method.getParameterList().getParameters();
- if (parameters.length != 0) return false;
- if (!method.getReturnType().equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return false;
- if (method.hasModifierProperty(PsiModifier.STATIC)) return false;
- PsiClass aClass = method.getContainingClass();
- return !(aClass != null && !isSerializable(aClass, refClass));
- }
-
- private static boolean isReadResolveMethod(PsiMethod method, RefClass refClass) {
- @NonNls final String name = method.getName();
- if (!"readResolve".equals(name)) return false;
- PsiParameter[] parameters = method.getParameterList().getParameters();
- if (parameters.length != 0) return false;
- if (!method.getReturnType().equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return false;
- if (method.hasModifierProperty(PsiModifier.STATIC)) return false;
- final PsiClass aClass = method.getContainingClass();
- return !(aClass != null && !isSerializable(aClass, refClass));
- }
-
- private static boolean isSerializable(PsiClass aClass, @Nullable RefClass refClass) {
- final PsiClass serializableClass = JavaPsiFacade.getInstance(aClass.getProject()).findClass("java.io.Serializable", aClass.getResolveScope());
- return serializableClass != null && isSerializable(aClass, refClass, serializableClass);
- }
-
- private static boolean isExternalizable(PsiClass aClass, RefClass refClass) {
- final GlobalSearchScope scope = aClass.getResolveScope();
- final PsiClass externalizableClass = JavaPsiFacade.getInstance(aClass.getProject()).findClass("java.io.Externalizable", scope);
- return externalizableClass != null && isSerializable(aClass, refClass, externalizableClass);
- }
-
- private static boolean isSerializable(PsiClass aClass, RefClass refClass, PsiClass serializableClass) {
- if (aClass == null) return false;
- if (aClass.isInheritor(serializableClass, true)) return true;
- if (refClass != null) {
- final Set<RefClass> subClasses = refClass.getSubClasses();
- for (RefClass subClass : subClasses) {
- if (isSerializable(subClass.getElement(), subClass, serializableClass)) return true;
- }
- }
- return false;
- }
-
- @Override
- public void runInspection(@NotNull final AnalysisScope scope,
- @NotNull InspectionManager manager,
- @NotNull final GlobalInspectionContext globalContext,
- @NotNull ProblemDescriptionsProcessor problemDescriptionsProcessor) {
- globalContext.getRefManager().iterate(new RefJavaVisitor() {
- @Override
- public void visitElement(@NotNull final RefEntity refEntity) {
- if (refEntity instanceof RefJavaElement) {
- final RefElementImpl refElement = (RefElementImpl)refEntity;
- if (!refElement.isSuspicious()) return;
-
- PsiFile file = refElement.getContainingFile();
-
- if (file == null) return;
- final boolean isSuppressed = refElement.isSuppressed(getShortName(), ALTERNATIVE_ID);
- if (!((GlobalInspectionContextImpl)globalContext).isToCheckFile(file, UnusedDeclarationInspection.this) || isSuppressed) {
- if (isSuppressed || !scope.contains(file)) {
- getEntryPointsManager().addEntryPoint(refElement, false);
- }
- return;
- }
-
- refElement.accept(new RefJavaVisitor() {
- @Override
- public void visitMethod(@NotNull RefMethod method) {
- if (isAddMainsEnabled() && method.isAppMain()) {
- getEntryPointsManager().addEntryPoint(method, false);
- }
- }
-
- @Override
- public void visitClass(@NotNull RefClass aClass) {
- if (isAddAppletEnabled() && aClass.isApplet() ||
- isAddServletEnabled() && aClass.isServlet()) {
- getEntryPointsManager().addEntryPoint(aClass, false);
- }
- }
- });
- }
- }
- });
-
- if (isAddNonJavaUsedEnabled()) {
- checkForReachables();
- final StrictUnreferencedFilter strictUnreferencedFilter = new StrictUnreferencedFilter(this,
- (GlobalInspectionContextImpl)globalContext);
- ProgressManager.getInstance().runProcess(new Runnable() {
- @Override
- public void run() {
- final PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(globalContext.getRefManager().getProject());
- globalContext.getRefManager().iterate(new RefJavaVisitor() {
- @Override
- public void visitElement(@NotNull final RefEntity refEntity) {
- if (refEntity instanceof RefClass && strictUnreferencedFilter.accepts((RefClass)refEntity)) {
- findExternalClassReferences((RefClass)refEntity);
- }
- else if (refEntity instanceof RefMethod) {
- RefMethod refMethod = (RefMethod)refEntity;
- if (refMethod.isConstructor() && strictUnreferencedFilter.accepts(refMethod)) {
- findExternalClassReferences(refMethod.getOwnerClass());
- }
- }
- }
-
- private void findExternalClassReferences(final RefClass refElement) {
- PsiClass psiClass = refElement.getElement();
- String qualifiedName = psiClass.getQualifiedName();
- if (qualifiedName != null) {
- helper.processUsagesInNonJavaFiles(qualifiedName,
- new PsiNonJavaFileReferenceProcessor() {
- @Override
- public boolean process(PsiFile file, int startOffset, int endOffset) {
- getEntryPointsManager().addEntryPoint(refElement, false);
- return false;
- }
- },
- GlobalSearchScope.projectScope(globalContext.getProject()));
- }
- }
- });
- }
- }, null);
- }
-
- myProcessedSuspicious = new HashSet<RefElement>();
- myPhase = 1;
- }
-
- public boolean isEntryPoint(final RefElement owner) {
- final PsiElement element = owner.getElement();
- if (RefUtil.isImplicitUsage(element)) return true;
- if (element instanceof PsiModifierListOwner) {
- final EntryPointsManagerImpl entryPointsManager = EntryPointsManagerImpl.getInstance(element.getProject());
- if (entryPointsManager.isEntryPoint((PsiModifierListOwner)element)) {
- return true;
- }
- }
- for (EntryPoint extension : myExtensions) {
- if (extension.isEntryPoint(owner, element)) {
- return true;
- }
- }
- return false;
- }
-
- public boolean isEntryPoint(@NotNull PsiElement element) {
- final Project project = element.getProject();
- final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
- if (element instanceof PsiMethod && isAddMainsEnabled() && PsiClassImplUtil.isMainOrPremainMethod((PsiMethod)element)) {
- return true;
- }
- if (element instanceof PsiClass) {
- PsiClass aClass = (PsiClass)element;
- /*
- if (aClass.isAnnotationType()) {
- return true;
- }
-
- if (aClass.isEnum()) {
- return true;
- }
- */
- final PsiClass applet = psiFacade.findClass("java.applet.Applet", GlobalSearchScope.allScope(project));
- if (isAddAppletEnabled() && applet != null && aClass.isInheritor(applet, true)) {
- return true;
- }
-
- final PsiClass servlet = psiFacade.findClass("javax.servlet.Servlet", GlobalSearchScope.allScope(project));
- if (isAddServletEnabled() && servlet != null && aClass.isInheritor(servlet, true)) {
- return true;
- }
- if (isAddMainsEnabled() && PsiMethodUtil.hasMainMethod(aClass)) return true;
- }
- if (element instanceof PsiModifierListOwner) {
- final EntryPointsManagerImpl entryPointsManager = EntryPointsManagerImpl.getInstance(project);
- if (AnnotationUtil
- .checkAnnotatedUsingPatterns((PsiModifierListOwner)element, entryPointsManager.ADDITIONAL_ANNOTATIONS) ||
- AnnotationUtil
- .checkAnnotatedUsingPatterns((PsiModifierListOwner)element, entryPointsManager.getAdditionalAnnotations())) {
- return true;
- }
- }
- for (EntryPoint extension : myExtensions) {
- if (extension.isEntryPoint(element)) {
- return true;
- }
- }
- final ImplicitUsageProvider[] implicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);
- for (ImplicitUsageProvider provider : implicitUsageProviders) {
- if (provider.isImplicitUsage(element)) return true;
- }
- return false;
- }
-
-
- private static class StrictUnreferencedFilter extends UnreferencedFilter {
- private StrictUnreferencedFilter(@NotNull UnusedDeclarationInspection tool, @NotNull GlobalInspectionContextImpl context) {
- super(tool, context);
- }
-
- @Override
- public int getElementProblemCount(RefJavaElement refElement) {
- final int problemCount = super.getElementProblemCount(refElement);
- if (problemCount > -1) return problemCount;
- return refElement.isReferenced() ? 0 : 1;
- }
- }
-
- @Override
- public boolean queryExternalUsagesRequests(@NotNull InspectionManager manager,
- @NotNull GlobalInspectionContext globalContext,
- @NotNull ProblemDescriptionsProcessor problemDescriptionsProcessor) {
- checkForReachables();
- final RefFilter filter = myPhase == 1 ? new StrictUnreferencedFilter(this, (GlobalInspectionContextImpl)globalContext) :
- new RefUnreachableFilter(this, (GlobalInspectionContextImpl)globalContext);
- final boolean[] requestAdded = {false};
-
- globalContext.getRefManager().iterate(new RefJavaVisitor() {
- @Override
- public void visitElement(@NotNull RefEntity refEntity) {
- if (!(refEntity instanceof RefJavaElement)) return;
- if (refEntity instanceof RefClass && ((RefClass)refEntity).isAnonymous()) return;
- RefJavaElement refElement = (RefJavaElement)refEntity;
- if (filter.accepts(refElement) && !myProcessedSuspicious.contains(refElement)) {
- refEntity.accept(new RefJavaVisitor() {
- @Override
- public void visitField(@NotNull final RefField refField) {
- myProcessedSuspicious.add(refField);
- PsiField psiField = refField.getElement();
- if (isSerializationImplicitlyUsedField(psiField)) {
- getEntryPointsManager().addEntryPoint(refField, false);
- }
- else {
- getJavaContext().enqueueFieldUsagesProcessor(refField, new GlobalJavaInspectionContext.UsagesProcessor() {
- @Override
- public boolean process(PsiReference psiReference) {
- getEntryPointsManager().addEntryPoint(refField, false);
- return false;
- }
- });
- requestAdded[0] = true;
- }
- }
-
- @Override
- public void visitMethod(@NotNull final RefMethod refMethod) {
- myProcessedSuspicious.add(refMethod);
- if (refMethod instanceof RefImplicitConstructor) {
- visitClass(refMethod.getOwnerClass());
- }
- else {
- PsiMethod psiMethod = (PsiMethod)refMethod.getElement();
- if (isSerializablePatternMethod(psiMethod, refMethod.getOwnerClass())) {
- getEntryPointsManager().addEntryPoint(refMethod, false);
- }
- else if (!refMethod.isExternalOverride() && !PsiModifier.PRIVATE.equals(refMethod.getAccessModifier())) {
- for (final RefMethod derivedMethod : refMethod.getDerivedMethods()) {
- myProcessedSuspicious.add(derivedMethod);
- }
-
- enqueueMethodUsages(refMethod);
- requestAdded[0] = true;
- }
- }
- }
-
- @Override
- public void visitClass(@NotNull final RefClass refClass) {
- myProcessedSuspicious.add(refClass);
- if (!refClass.isAnonymous()) {
- getJavaContext().enqueueDerivedClassesProcessor(refClass, new GlobalJavaInspectionContext.DerivedClassesProcessor() {
- @Override
- public boolean process(PsiClass inheritor) {
- getEntryPointsManager().addEntryPoint(refClass, false);
- return false;
- }
- });
-
- getJavaContext().enqueueClassUsagesProcessor(refClass, new GlobalJavaInspectionContext.UsagesProcessor() {
- @Override
- public boolean process(PsiReference psiReference) {
- getEntryPointsManager().addEntryPoint(refClass, false);
- return false;
- }
- });
- requestAdded[0] = true;
- }
- }
- });
- }
- }
- });
-
- if (!requestAdded[0]) {
- if (myPhase == 2) {
- myProcessedSuspicious = null;
- return false;
- }
- else {
- myPhase = 2;
- }
- }
-
- return true;
- }
-
- private static boolean isSerializablePatternMethod(PsiMethod psiMethod, RefClass refClass) {
- return isReadObjectMethod(psiMethod, refClass) || isWriteObjectMethod(psiMethod, refClass) || isReadResolveMethod(psiMethod, refClass) ||
- isWriteReplaceMethod(psiMethod, refClass) || isExternalizableNoParameterConstructor(psiMethod, refClass);
- }
-
- private void enqueueMethodUsages(final RefMethod refMethod) {
- if (refMethod.getSuperMethods().isEmpty()) {
- getJavaContext().enqueueMethodUsagesProcessor(refMethod, new GlobalJavaInspectionContext.UsagesProcessor() {
- @Override
- public boolean process(PsiReference psiReference) {
- getEntryPointsManager().addEntryPoint(refMethod, false);
- return false;
- }
- });
- }
- else {
- for (RefMethod refSuper : refMethod.getSuperMethods()) {
- enqueueMethodUsages(refSuper);
- }
- }
- }
-
- private GlobalJavaInspectionContext getJavaContext() {
- return getContext().getExtension(GlobalJavaInspectionContext.CONTEXT);
- }
-
- @Nullable
- @Override
- public JobDescriptor[] getAdditionalJobs() {
- return new JobDescriptor[]{getContext().getStdJobDescriptors().BUILD_GRAPH, getContext().getStdJobDescriptors().FIND_EXTERNAL_USAGES};
- }
-
-
- void checkForReachables() {
- CodeScanner codeScanner = new CodeScanner();
-
- // Cleanup previous reachability information.
- getContext().getRefManager().iterate(new RefJavaVisitor() {
- @Override
- public void visitElement(@NotNull RefEntity refEntity) {
- if (refEntity instanceof RefJavaElement) {
- final RefJavaElementImpl refElement = (RefJavaElementImpl)refEntity;
- if (!getContext().isToCheckMember(refElement, UnusedDeclarationInspection.this)) return;
- refElement.setReachable(false);
- }
- }
- });
-
-
- for (RefElement entry : getEntryPointsManager().getEntryPoints()) {
- entry.accept(codeScanner);
- }
-
- while (codeScanner.newlyInstantiatedClassesCount() != 0) {
- codeScanner.cleanInstantiatedClassesCount();
- codeScanner.processDelayedMethods();
- }
- }
-
- private EntryPointsManager getEntryPointsManager() {
- return getContext().getExtension(GlobalJavaInspectionContext.CONTEXT).getEntryPointsManager(getContext().getRefManager());
- }
-
- private static class CodeScanner extends RefJavaVisitor {
- private final HashMap<RefClass, HashSet<RefMethod>> myClassIDtoMethods;
- private final HashSet<RefClass> myInstantiatedClasses;
- private int myInstantiatedClassesCount;
- private final HashSet<RefMethod> myProcessedMethods;
-
- private CodeScanner() {
- myClassIDtoMethods = new HashMap<RefClass, HashSet<RefMethod>>();
- myInstantiatedClasses = new HashSet<RefClass>();
- myProcessedMethods = new HashSet<RefMethod>();
- myInstantiatedClassesCount = 0;
- }
-
- @Override public void visitMethod(@NotNull RefMethod method) {
- if (!myProcessedMethods.contains(method)) {
- // Process class's static intitializers
- if (method.isStatic() || method.isConstructor()) {
- if (method.isConstructor()) {
- addInstantiatedClass(method.getOwnerClass());
- }
- else {
- ((RefClassImpl)method.getOwnerClass()).setReachable(true);
- }
- myProcessedMethods.add(method);
- makeContentReachable((RefJavaElementImpl)method);
- makeClassInitializersReachable(method.getOwnerClass());
- }
- else {
- if (isClassInstantiated(method.getOwnerClass())) {
- myProcessedMethods.add(method);
- makeContentReachable((RefJavaElementImpl)method);
- }
- else {
- addDelayedMethod(method);
- }
-
- for (RefMethod refSub : method.getDerivedMethods()) {
- visitMethod(refSub);
- }
- }
- }
- }
-
- @Override public void visitClass(@NotNull RefClass refClass) {
- boolean alreadyActive = refClass.isReachable();
- ((RefClassImpl)refClass).setReachable(true);
-
- if (!alreadyActive) {
- // Process class's static intitializers.
- makeClassInitializersReachable(refClass);
- }
-
- addInstantiatedClass(refClass);
- }
-
- @Override public void visitField(@NotNull RefField field) {
- // Process class's static intitializers.
- if (!field.isReachable()) {
- makeContentReachable((RefJavaElementImpl)field);
- makeClassInitializersReachable(field.getOwnerClass());
- }
- }
-
- private void addInstantiatedClass(RefClass refClass) {
- if (myInstantiatedClasses.add(refClass)) {
- ((RefClassImpl)refClass).setReachable(true);
- myInstantiatedClassesCount++;
-
- final List<RefMethod> refMethods = refClass.getLibraryMethods();
- for (RefMethod refMethod : refMethods) {
- refMethod.accept(this);
- }
- for (RefClass baseClass : refClass.getBaseClasses()) {
- addInstantiatedClass(baseClass);
- }
- }
- }
-
- private void makeContentReachable(RefJavaElementImpl refElement) {
- refElement.setReachable(true);
- for (RefElement refCallee : refElement.getOutReferences()) {
- refCallee.accept(this);
- }
- }
-
- private void makeClassInitializersReachable(RefClass refClass) {
- for (RefElement refCallee : refClass.getOutReferences()) {
- refCallee.accept(this);
- }
- }
-
- private void addDelayedMethod(RefMethod refMethod) {
- HashSet<RefMethod> methods = myClassIDtoMethods.get(refMethod.getOwnerClass());
- if (methods == null) {
- methods = new HashSet<RefMethod>();
- myClassIDtoMethods.put(refMethod.getOwnerClass(), methods);
- }
- methods.add(refMethod);
- }
-
- private boolean isClassInstantiated(RefClass refClass) {
- return myInstantiatedClasses.contains(refClass);
- }
-
- private int newlyInstantiatedClassesCount() {
- return myInstantiatedClassesCount;
- }
-
- private void cleanInstantiatedClassesCount() {
- myInstantiatedClassesCount = 0;
- }
-
- private void processDelayedMethods() {
- RefClass[] instClasses = myInstantiatedClasses.toArray(new RefClass[myInstantiatedClasses.size()]);
- for (RefClass refClass : instClasses) {
- if (isClassInstantiated(refClass)) {
- HashSet<RefMethod> methods = myClassIDtoMethods.get(refClass);
- if (methods != null) {
- RefMethod[] arMethods = methods.toArray(new RefMethod[methods.size()]);
- for (RefMethod arMethod : arMethods) {
- arMethod.accept(this);
- }
- }
- }
- }
- }
- }
-
-
- @NotNull
- @Override
- public InspectionToolPresentation createPresentation(@NotNull InspectionToolWrapper toolWrapper) {
- return new UnusedDeclarationPresentation(toolWrapper);
- }
-
- @Override
- public void initialize(@NotNull GlobalInspectionContext context) {
- super.initialize(context);
- myContext = (GlobalInspectionContextImpl)context;
- }
-
- @Override
- public void cleanup() {
- super.cleanup();
- myContext = null;
- }
-
- @Override
- public boolean isGraphNeeded() {
- return true;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java
index 29f0578073ff..0db0532cac90 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java
@@ -65,9 +65,10 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
@NonNls private static final String COMMENT = "comment";
@NonNls private static final String [] HINTS = {COMMENT, DELETE};
- public UnusedDeclarationPresentation(@NotNull InspectionToolWrapper toolWrapper) {
- super(toolWrapper);
+ public UnusedDeclarationPresentation(@NotNull InspectionToolWrapper toolWrapper, @NotNull GlobalInspectionContextImpl context) {
+ super(toolWrapper, context);
myQuickFixActions = createQuickFixes(toolWrapper);
+ ((EntryPointsManagerBase)getEntryPointsManager()).setAddNonJavaEntries(getTool().ADD_NONJAVA_TO_ENTRIES);
}
public RefFilter getFilter() {
@@ -82,7 +83,7 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
}
@Override
- public int getElementProblemCount(final RefJavaElement refElement) {
+ public int getElementProblemCount(@NotNull final RefJavaElement refElement) {
final int problemCount = super.getElementProblemCount(refElement);
if (problemCount > - 1) return problemCount;
if (!((RefElementImpl)refElement).hasSuspiciousCallers() || ((RefJavaElementImpl)refElement).isSuspiciousRecursive()) return 1;
@@ -91,7 +92,7 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
}
@NotNull
- UnusedDeclarationInspection getTool() {
+ private UnusedDeclarationInspection getTool() {
return (UnusedDeclarationInspection)getToolWrapper().getTool();
}
@@ -162,7 +163,7 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
}
@Override
- protected boolean applyFix(final RefEntity[] refElements) {
+ protected boolean applyFix(@NotNull final RefEntity[] refElements) {
if (!super.applyFix(refElements)) return false;
final ArrayList<PsiElement> psiElements = new ArrayList<PsiElement>();
for (RefEntity refElement : refElements) {
@@ -176,6 +177,7 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
@Override
public void run() {
final Project project = getContext().getProject();
+ if (isDisposed() || project.isDisposed()) return;
SafeDeleteHandler.invoke(project, PsiUtilCore.toPsiElementArray(psiElements), false, new Runnable() {
@Override
public void run() {
@@ -199,7 +201,7 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
}
@Override
- protected boolean applyFix(RefEntity[] refElements) {
+ protected boolean applyFix(@NotNull RefEntity[] refElements) {
final EntryPointsManager entryPointsManager = getEntryPointsManager();
for (RefEntity refElement : refElements) {
if (refElement instanceof RefElement) {
@@ -218,9 +220,9 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
}
@Override
- protected boolean applyFix(RefEntity[] refElements) {
+ protected boolean applyFix(@NotNull RefEntity[] refElements) {
if (!super.applyFix(refElements)) return false;
- ArrayList<RefElement> deletedRefs = new ArrayList<RefElement>(1);
+ List<RefElement> deletedRefs = new ArrayList<RefElement>(1);
for (RefEntity refElement : refElements) {
PsiElement psiElement = refElement instanceof RefElement ? ((RefElement)refElement).getElement() : null;
if (psiElement == null) continue;
@@ -331,12 +333,6 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
}
@Override
- public void initialize(@NotNull GlobalInspectionContextImpl context) {
- super.initialize(context);
- ((EntryPointsManagerImpl)getEntryPointsManager()).setAddNonJavaEntries(getTool().ADD_NONJAVA_TO_ENTRIES);
- }
-
- @Override
public void updateContent() {
getTool().checkForReachables();
myPackageContents = new HashMap<String, Set<RefEntity>>();
@@ -360,7 +356,7 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
@Override
public boolean hasReportedProblems() {
final GlobalInspectionContextImpl context = getContext();
- if (context != null && context.getUIOptions().SHOW_ONLY_DIFF){
+ if (!isDisposed() && context.getUIOptions().SHOW_ONLY_DIFF){
return containsOnlyDiff(myPackageContents) ||
myOldPackageContents != null && containsOnlyDiff(myOldPackageContents);
}
@@ -438,7 +434,7 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
@Override
public FileStatus getElementStatus(final RefEntity element) {
final GlobalInspectionContextImpl context = getContext();
- if (context != null && context.getUIOptions().SHOW_DIFF_WITH_PREVIOUS_RUN){
+ if (!isDisposed() && context.getUIOptions().SHOW_DIFF_WITH_PREVIOUS_RUN){
if (myOldPackageContents != null){
final boolean old = RefUtil.contains(element, collectRefElements(myOldPackageContents));
final boolean current = RefUtil.contains(element, collectRefElements(myPackageContents));
diff --git a/java/java-impl/src/com/intellij/codeInspection/emptyMethod/EmptyMethodInspection.java b/java/java-impl/src/com/intellij/codeInspection/emptyMethod/EmptyMethodInspection.java
index a2a95d734ec2..a35c30d9c09e 100644
--- a/java/java-impl/src/com/intellij/codeInspection/emptyMethod/EmptyMethodInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/emptyMethod/EmptyMethodInspection.java
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInspection.emptyMethod;
-import com.intellij.ExtensionPoints;
+import com.intellij.ToolExtensionPoints;
import com.intellij.analysis.AnalysisScope;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.daemon.GroupNames;
@@ -51,7 +51,7 @@ import java.util.List;
/**
* @author max
*/
-public class EmptyMethodInspection extends GlobalJavaInspectionTool {
+public class EmptyMethodInspection extends GlobalJavaBatchInspectionTool {
private static final String DISPLAY_NAME = InspectionsBundle.message("inspection.empty.method.display.name");
@NonNls private static final String SHORT_NAME = "EmptyMethod";
@@ -166,7 +166,7 @@ public class EmptyMethodInspection extends GlobalJavaInspectionTool {
if (AnnotationUtil.isAnnotated(owner, EXCLUDE_ANNOS)) {
return false;
}
- for (final Object extension : Extensions.getExtensions(ExtensionPoints.EMPTY_METHOD_TOOL)) {
+ for (final Object extension : Extensions.getExtensions(ToolExtensionPoints.EMPTY_METHOD_TOOL)) {
if (((Condition<RefMethod>) extension).value(refMethod)) {
return false;
}
@@ -358,7 +358,7 @@ public class EmptyMethodInspection extends GlobalJavaInspectionTool {
}
@Override
- public void applyFix(final @NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+ public void applyFix(@NotNull final Project project, @NotNull ProblemDescriptor descriptor) {
applyFix(project, new ProblemDescriptor[]{descriptor}, new ArrayList<PsiElement>(), null);
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java b/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java
index caacfbfd622e..d8851e0f074d 100644
--- a/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java
@@ -24,339 +24,31 @@
*/
package com.intellij.codeInspection.ex;
-import com.intellij.ExtensionPoints;
-import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
-import com.intellij.codeInspection.reference.*;
import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
-import com.intellij.ide.DataManager;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.*;
-import com.intellij.openapi.extensions.ExtensionPoint;
-import com.intellij.openapi.extensions.ExtensionPointListener;
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.util.*;
-import com.intellij.profile.codeInspection.InspectionProfileManager;
-import com.intellij.psi.*;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.ui.UIUtil;
import org.jdom.Element;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
@State(
name = "EntryPointsManager",
storages = {@Storage( file = StoragePathMacros.PROJECT_FILE)}
)
-public class EntryPointsManagerImpl implements PersistentStateComponent<Element>, EntryPointsManager {
- @NonNls private static final String[] STANDARD_ANNOS = {
- "javax.ws.rs.*",
- };
-
- // null means uninitialized
- private volatile List<String> ADDITIONAL_ANNOS;
-
- public Collection<String> getAdditionalAnnotations() {
- List<String> annos = ADDITIONAL_ANNOS;
- if (annos == null) {
- annos = new ArrayList<String>();
- Collections.addAll(annos, STANDARD_ANNOS);
- final EntryPoint[] extensions = Extensions.getExtensions(ExtensionPoints.DEAD_CODE_TOOL, null);
- for (EntryPoint extension : extensions) {
- final String[] ignoredAnnotations = extension.getIgnoreAnnotations();
- if (ignoredAnnotations != null) {
- ContainerUtil.addAll(annos, ignoredAnnotations);
- }
- }
- ADDITIONAL_ANNOS = annos = Collections.unmodifiableList(annos);
- }
- return annos;
- }
- public JDOMExternalizableStringList ADDITIONAL_ANNOTATIONS = new JDOMExternalizableStringList();
- private final Map<String, SmartRefElementPointer> myPersistentEntryPoints;
- private final Set<RefElement> myTemporaryEntryPoints;
- private static final String VERSION = "2.0";
- @NonNls private static final String VERSION_ATTR = "version";
- @NonNls private static final String ENTRY_POINT_ATTR = "entry_point";
- private boolean myAddNonJavaEntries = true;
- private boolean myResolved = false;
- private final Project myProject;
- private long myLastModificationCount = -1;
-
+public class EntryPointsManagerImpl extends EntryPointsManagerBase implements PersistentStateComponent<Element> {
public EntryPointsManagerImpl(Project project) {
- myProject = project;
- myTemporaryEntryPoints = new HashSet<RefElement>();
- myPersistentEntryPoints =
- new LinkedHashMap<String, SmartRefElementPointer>(); // To keep the order between readExternal to writeExternal
- Disposer.register(project, this);
- final ExtensionPoint<EntryPoint> point = Extensions.getRootArea().getExtensionPoint(ExtensionPoints.DEAD_CODE_TOOL);
- point.addExtensionPointListener(new ExtensionPointListener<EntryPoint>() {
- @Override
- public void extensionAdded(@NotNull EntryPoint extension, @Nullable PluginDescriptor pluginDescriptor) {
- extensionRemoved(extension, pluginDescriptor);
- }
-
- @Override
- public void extensionRemoved(@NotNull EntryPoint extension, @Nullable PluginDescriptor pluginDescriptor) {
- if (ADDITIONAL_ANNOS != null) {
- ADDITIONAL_ANNOS = null;
- UIUtil.invokeLaterIfNeeded(new Runnable() {
- @Override
- public void run() {
- if (ApplicationManager.getApplication().isDisposed()) return;
- InspectionProfileManager.getInstance().fireProfileChanged(null);
- }
- });
- }
- }
- }, this);
- }
-
- public static EntryPointsManagerImpl getInstance(Project project) {
- return ServiceManager.getService(project, EntryPointsManagerImpl.class);
- }
-
- @Override
- @SuppressWarnings({"HardCodedStringLiteral"})
- public void loadState(Element element) {
- Element entryPointsElement = element.getChild("entry_points");
- if (entryPointsElement != null) {
- final String version = entryPointsElement.getAttributeValue(VERSION_ATTR);
- if (!Comparing.strEqual(version, VERSION)) {
- convert(entryPointsElement, myPersistentEntryPoints);
- }
- else {
- List content = entryPointsElement.getChildren();
- for (final Object aContent : content) {
- Element entryElement = (Element)aContent;
- if (ENTRY_POINT_ATTR.equals(entryElement.getName())) {
- SmartRefElementPointerImpl entryPoint = new SmartRefElementPointerImpl(entryElement);
- myPersistentEntryPoints.put(entryPoint.getFQName(), entryPoint);
- }
- }
- }
- }
- try {
- ADDITIONAL_ANNOTATIONS.readExternal(element);
- }
- catch (InvalidDataException ignored) {
- }
- }
-
- @Override
- @SuppressWarnings({"HardCodedStringLiteral"})
- public Element getState() {
- Element element = new Element("state");
- writeExternal(element, myPersistentEntryPoints, ADDITIONAL_ANNOTATIONS);
- return element;
- }
-
- @SuppressWarnings({"HardCodedStringLiteral"})
- public static void writeExternal(final Element element,
- final Map<String, SmartRefElementPointer> persistentEntryPoints,
- final JDOMExternalizableStringList additional_annotations) {
- Element entryPointsElement = new Element("entry_points");
- entryPointsElement.setAttribute(VERSION_ATTR, VERSION);
- for (SmartRefElementPointer entryPoint : persistentEntryPoints.values()) {
- assert entryPoint.isPersistent();
- entryPoint.writeExternal(entryPointsElement);
- }
-
- element.addContent(entryPointsElement);
- if (!additional_annotations.isEmpty()) {
- try {
- additional_annotations.writeExternal(element);
- }
- catch (WriteExternalException ignored) {
- }
- }
- }
-
- @Override
- public void resolveEntryPoints(final RefManager manager) {
- if (!myResolved) {
- myResolved = true;
- cleanup();
- validateEntryPoints();
-
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- @Override
- public void run() {
- for (SmartRefElementPointer entryPoint : myPersistentEntryPoints.values()) {
- if (entryPoint.resolve(manager)) {
- RefEntity refElement = entryPoint.getRefElement();
- ((RefElementImpl)refElement).setEntry(true);
- ((RefElementImpl)refElement).setPermanentEntry(entryPoint.isPersistent());
- }
- }
- }
- });
- }
- }
-
- private void purgeTemporaryEntryPoints() {
- for (RefElement entryPoint : myTemporaryEntryPoints) {
- ((RefElementImpl)entryPoint).setEntry(false);
- }
-
- myTemporaryEntryPoints.clear();
- }
-
- @Override
- public void addEntryPoint(RefElement newEntryPoint, boolean isPersistent) {
- if (!newEntryPoint.isValid()) return;
- if (newEntryPoint instanceof RefClass) {
- RefClass refClass = (RefClass)newEntryPoint;
-
- if (refClass.isAnonymous()) {
- // Anonymous class cannot be an entry point.
- return;
- }
-
- List<RefMethod> refConstructors = refClass.getConstructors();
- if (refConstructors.size() == 1) {
- addEntryPoint(refConstructors.get(0), isPersistent);
- return;
- }
- else if (refConstructors.size() > 1) {
- // Many constructors here. Need to ask user which ones are used
- for (int i = 0; i < refConstructors.size(); i++) {
- addEntryPoint(refConstructors.get(i), isPersistent);
- }
-
- return;
- }
- }
-
- if (!isPersistent) {
- myTemporaryEntryPoints.add(newEntryPoint);
- ((RefElementImpl)newEntryPoint).setEntry(true);
- }
- else {
- if (myPersistentEntryPoints.get(newEntryPoint.getExternalName()) == null) {
- final SmartRefElementPointerImpl entry = new SmartRefElementPointerImpl(newEntryPoint, true);
- myPersistentEntryPoints.put(entry.getFQName(), entry);
- ((RefElementImpl)newEntryPoint).setEntry(true);
- ((RefElementImpl)newEntryPoint).setPermanentEntry(true);
- if (entry.isPersistent()) { //do save entry points
- final EntryPointsManagerImpl entryPointsManager = getInstance(newEntryPoint.getElement().getProject());
- if (this != entryPointsManager) {
- entryPointsManager.addEntryPoint(newEntryPoint, true);
- }
- }
- }
- }
- }
-
- @Override
- public void removeEntryPoint(RefElement anEntryPoint) {
- if (anEntryPoint instanceof RefClass) {
- RefClass refClass = (RefClass)anEntryPoint;
- if (!refClass.isInterface()) {
- anEntryPoint = refClass.getDefaultConstructor();
- }
- }
-
- if (anEntryPoint == null) return;
-
- myTemporaryEntryPoints.remove(anEntryPoint);
-
- Set<Map.Entry<String, SmartRefElementPointer>> set = myPersistentEntryPoints.entrySet();
- String key = null;
- for (Map.Entry<String, SmartRefElementPointer> entry : set) {
- SmartRefElementPointer value = entry.getValue();
- if (value.getRefElement() == anEntryPoint) {
- key = entry.getKey();
- break;
- }
- }
-
- if (key != null) {
- myPersistentEntryPoints.remove(key);
- ((RefElementImpl)anEntryPoint).setEntry(false);
- }
-
- if (anEntryPoint.isPermanentEntry() && anEntryPoint.isValid()) {
- final Project project = anEntryPoint.getElement().getProject();
- final EntryPointsManagerImpl entryPointsManager = getInstance(project);
- if (this != entryPointsManager) {
- entryPointsManager.removeEntryPoint(anEntryPoint);
- }
- }
- }
-
- @Override
- public RefElement[] getEntryPoints() {
- validateEntryPoints();
- List<RefElement> entries = new ArrayList<RefElement>();
- Collection<SmartRefElementPointer> collection = myPersistentEntryPoints.values();
- for (SmartRefElementPointer refElementPointer : collection) {
- final RefEntity elt = refElementPointer.getRefElement();
- if (elt instanceof RefElement) {
- entries.add((RefElement)elt);
- }
- }
- entries.addAll(myTemporaryEntryPoints);
-
- return entries.toArray(new RefElement[entries.size()]);
- }
-
- @Override
- public void dispose() {
- cleanup();
- }
-
- private void validateEntryPoints() {
- long count = PsiManager.getInstance(myProject).getModificationTracker().getModificationCount();
- if (count != myLastModificationCount) {
- myLastModificationCount = count;
- Collection<SmartRefElementPointer> collection = myPersistentEntryPoints.values();
- SmartRefElementPointer[] entries = collection.toArray(new SmartRefElementPointer[collection.size()]);
- for (SmartRefElementPointer entry : entries) {
- RefElement refElement = (RefElement)entry.getRefElement();
- if (refElement != null && !refElement.isValid()) {
- myPersistentEntryPoints.remove(entry.getFQName());
- }
- }
-
- final Iterator<RefElement> it = myTemporaryEntryPoints.iterator();
- while (it.hasNext()) {
- RefElement refElement = it.next();
- if (!refElement.isValid()) {
- it.remove();
- }
- }
- }
- }
-
- @Override
- public void cleanup() {
- purgeTemporaryEntryPoints();
- Collection<SmartRefElementPointer> entries = myPersistentEntryPoints.values();
- for (SmartRefElementPointer entry : entries) {
- entry.freeReference();
- }
- }
-
- @Override
- public boolean isAddNonJavaEntries() {
- return myAddNonJavaEntries;
+ super(project);
}
@Override
public void configureAnnotations() {
- final ArrayList<String> list = new ArrayList<String>(ADDITIONAL_ANNOTATIONS);
+ final List<String> list = new ArrayList<String>(ADDITIONAL_ANNOTATIONS);
final JPanel listPanel = SpecialAnnotationsUtil.createSpecialAnnotationsListControl(list, "Do not check if annotated by", true);
new DialogWrapper(myProject) {
{
@@ -379,77 +71,15 @@ public class EntryPointsManagerImpl implements PersistentStateComponent<Element>
}.show();
}
- public static JButton createConfigureAnnotationsBtn(final JComponent parent) {
+ @Override
+ public JButton createConfigureAnnotationsBtn() {
final JButton configureAnnotations = new JButton("Configure annotations...");
configureAnnotations.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- Project project = PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(parent));
- if (project == null) project = ProjectManager.getInstance().getDefaultProject();
- EntryPointsManagerImpl.getInstance(project).configureAnnotations();
+ configureAnnotations();
}
});
return configureAnnotations;
}
-
- public void addAllPersistentEntries(EntryPointsManagerImpl manager) {
- myPersistentEntryPoints.putAll(manager.myPersistentEntryPoints);
- }
-
- public static void convert(Element element, final Map<String, SmartRefElementPointer> persistentEntryPoints) {
- List content = element.getChildren();
- for (final Object aContent : content) {
- Element entryElement = (Element)aContent;
- if (ENTRY_POINT_ATTR.equals(entryElement.getName())) {
- String fqName = entryElement.getAttributeValue(SmartRefElementPointerImpl.FQNAME_ATTR);
- final String type = entryElement.getAttributeValue(SmartRefElementPointerImpl.TYPE_ATTR);
- if (Comparing.strEqual(type, RefJavaManager.METHOD)) {
-
- int spaceIdx = fqName.indexOf(' ');
- int lastDotIdx = fqName.lastIndexOf('.');
-
- int parenIndex = fqName.indexOf('(');
-
- while (lastDotIdx > parenIndex) lastDotIdx = fqName.lastIndexOf('.', lastDotIdx - 1);
-
- boolean notype = false;
- if (spaceIdx < 0 || spaceIdx + 1 > lastDotIdx || spaceIdx > parenIndex) {
- notype = true;
- }
-
- final String className = fqName.substring(notype ? 0 : spaceIdx + 1, lastDotIdx);
- final String methodSignature =
- notype ? fqName.substring(lastDotIdx + 1) : fqName.substring(0, spaceIdx) + ' ' + fqName.substring(lastDotIdx + 1);
-
- fqName = className + " " + methodSignature;
- }
- else if (Comparing.strEqual(type, RefJavaManager.FIELD)) {
- final int lastDotIdx = fqName.lastIndexOf('.');
- if (lastDotIdx > 0 && lastDotIdx < fqName.length() - 2) {
- String className = fqName.substring(0, lastDotIdx);
- String fieldName = fqName.substring(lastDotIdx + 1);
- fqName = className + " " + fieldName;
- }
- else {
- continue;
- }
- }
- SmartRefElementPointerImpl entryPoint = new SmartRefElementPointerImpl(type, fqName);
- persistentEntryPoints.put(entryPoint.getFQName(), entryPoint);
- }
- }
- }
-
- public void setAddNonJavaEntries(final boolean addNonJavaEntries) {
- myAddNonJavaEntries = addNonJavaEntries;
- }
-
- public boolean isEntryPoint(@NotNull PsiModifierListOwner element) {
- if (!ADDITIONAL_ANNOTATIONS.isEmpty() && ADDITIONAL_ANNOTATIONS.contains(Deprecated.class.getName()) &&
- element instanceof PsiDocCommentOwner && ((PsiDocCommentOwner)element).isDeprecated()) {
- return true;
- }
- return AnnotationUtil.isAnnotated(element, ADDITIONAL_ANNOTATIONS) ||
- AnnotationUtil.isAnnotated(element, getAdditionalAnnotations());
- }
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/inconsistentLanguageLevel/InconsistentLanguageLevelInspection.java b/java/java-impl/src/com/intellij/codeInspection/inconsistentLanguageLevel/InconsistentLanguageLevelInspection.java
index 4c0e2227e038..ecd1dcad59cd 100644
--- a/java/java-impl/src/com/intellij/codeInspection/inconsistentLanguageLevel/InconsistentLanguageLevelInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/inconsistentLanguageLevel/InconsistentLanguageLevelInspection.java
@@ -27,7 +27,7 @@ import com.intellij.codeInspection.reference.RefManager;
import com.intellij.codeInspection.reference.RefModule;
import com.intellij.codeInspection.unnecessaryModuleDependency.UnnecessaryModuleDependencyInspection;
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.project.ProjectBundle;
import com.intellij.openapi.roots.*;
@@ -44,6 +44,11 @@ import java.util.Set;
public class InconsistentLanguageLevelInspection extends GlobalInspectionTool {
@Override
+ public boolean isGraphNeeded() {
+ return false;
+ }
+
+ @Override
public void runInspection(@NotNull AnalysisScope scope,
@NotNull InspectionManager manager,
@NotNull GlobalInspectionContext globalContext,
@@ -52,7 +57,7 @@ public class InconsistentLanguageLevelInspection extends GlobalInspectionTool {
scope.accept(new PsiElementVisitor(){
@Override
public void visitElement(PsiElement element) {
- final Module module = ModuleUtil.findModuleForPsiElement(element);
+ final Module module = ModuleUtilCore.findModuleForPsiElement(element);
if (module != null) {
modules.add(module);
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicCompletionContributor.java b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicCompletionContributor.java
index 2a82958eb202..4f9fa882be6e 100644
--- a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicCompletionContributor.java
@@ -51,6 +51,10 @@ public class MagicCompletionContributor extends CompletionContributor {
PsiElement pos = parameters.getPosition();
MagicConstantInspection.AllowedValues allowedValues = null;
+ if (JavaCompletionData.AFTER_DOT.accepts(pos)) {
+ return;
+ }
+
if (IN_METHOD_CALL_ARGUMENT.accepts(pos)) {
PsiCall call = PsiTreeUtil.getParentOfType(pos, PsiCall.class);
if (!(call instanceof PsiExpression)) return;
diff --git a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java
index f185806be3c6..7193cc96ffed 100644
--- a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java
@@ -55,6 +55,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
public class MagicConstantInspection extends BaseJavaLocalInspectionTool {
+ public static final Key<Boolean> NO_ANNOTATIONS_FOUND = Key.create("REPORTED_NO_ANNOTATIONS_FOUND");
+
@Nls
@NotNull
@Override
@@ -152,8 +154,19 @@ public class MagicConstantInspection extends BaseJavaLocalInspectionTool {
};
}
+ @Override
+ public void cleanup(Project project) {
+ super.cleanup(project);
+ project.putUserData(NO_ANNOTATIONS_FOUND, null);
+ }
+
private static void checkAnnotationsJarAttached(@NotNull PsiFile file, @NotNull ProblemsHolder holder) {
final Project project = file.getProject();
+ if (!holder.isOnTheFly()) {
+ final Boolean found = project.getUserData(NO_ANNOTATIONS_FOUND);
+ if (found != null) return;
+ }
+
PsiClass event = JavaPsiFacade.getInstance(project).findClass("java.awt.event.InputEvent", GlobalSearchScope.allScope(project));
if (event == null) return; // no jdk to attach
PsiMethod[] methods = event.findMethodsByName("getModifiers", false);
@@ -172,6 +185,11 @@ public class MagicConstantInspection extends BaseJavaLocalInspectionTool {
}
}
if (jdk == null) return; // no jdk to attach
+
+ if (!holder.isOnTheFly()) {
+ project.putUserData(NO_ANNOTATIONS_FOUND, Boolean.TRUE);
+ }
+
final Sdk finalJdk = jdk;
String path = finalJdk.getHomePath();
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java
deleted file mode 100644
index 8c9cda6eb582..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Oct 21, 2001
- * Time: 4:29:19 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.codeInsight.TestFrameworks;
-import com.intellij.lang.injection.InjectedLanguageManager;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
-import com.intellij.psi.*;
-import com.intellij.psi.util.ClassUtil;
-import com.intellij.psi.util.PsiFormatUtil;
-import gnu.trove.THashSet;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-public class RefClassImpl extends RefJavaElementImpl implements RefClass {
- private static final Set<RefElement> EMPTY_SET = Collections.emptySet();
- private static final Set<RefClass> EMPTY_CLASS_SET = Collections.emptySet();
- private static final List<RefMethod> EMPTY_METHOD_LIST = new ArrayList<RefMethod>(0);
- private static final int IS_ANONYMOUS_MASK = 0x10000;
- private static final int IS_INTERFACE_MASK = 0x20000;
- private static final int IS_UTILITY_MASK = 0x40000;
- private static final int IS_ABSTRACT_MASK = 0x80000;
-
- private static final int IS_APPLET_MASK = 0x200000;
- private static final int IS_SERVLET_MASK = 0x400000;
- private static final int IS_TESTCASE_MASK = 0x800000;
- private static final int IS_LOCAL_MASK = 0x1000000;
-
- private Set<RefClass> myBases; // singleton (to conserve the memory) or THashSet
- private Set<RefClass> mySubClasses; // singleton (to conserve the memory) or THashSet
- private List<RefMethod> myConstructors;
- private RefMethodImpl myDefaultConstructor;
- private List<RefMethod> myOverridingMethods;
- private Set<RefElement> myInTypeReferences;
- private Set<RefElement> myInstanceReferences;
- private List<RefJavaElement> myClassExporters;
-
- RefClassImpl(PsiClass psiClass, RefManager manager) {
- super(psiClass, manager);
- }
-
- @Override
- protected void initialize() {
- myDefaultConstructor = null;
-
- final PsiClass psiClass = getElement();
-
- LOG.assertTrue(psiClass != null);
-
- PsiElement psiParent = psiClass.getParent();
- if (psiParent instanceof PsiFile) {
- if (isSyntheticJSP()) {
- final RefFileImpl refFile = (RefFileImpl)getRefManager().getReference(JspPsiUtil.getJspFile(psiClass));
- LOG.assertTrue(refFile != null);
- refFile.add(this);
- } else if (psiParent instanceof PsiJavaFile) {
- PsiJavaFile psiFile = (PsiJavaFile) psiParent;
- String packageName = psiFile.getPackageName();
- if (!"".equals(packageName)) {
- ((RefPackageImpl)getRefJavaManager().getPackage(packageName)).add(this);
- } else {
- ((RefPackageImpl)getRefJavaManager().getDefaultPackage()).add(this);
- }
- }
- final Module module = ModuleUtil.findModuleForPsiElement(psiClass);
- LOG.assertTrue(module != null);
- final RefModuleImpl refModule = ((RefModuleImpl)getRefManager().getRefModule(module));
- LOG.assertTrue(refModule != null);
- refModule.add(this);
- } else {
- while (!(psiParent instanceof PsiClass || psiParent instanceof PsiMethod || psiParent instanceof PsiField)) {
- psiParent = psiParent.getParent();
- }
- RefElement refParent = getRefManager().getReference(psiParent);
- LOG.assertTrue (refParent != null);
- ((RefElementImpl)refParent).add(this);
-
- }
-
- setAbstract(psiClass.hasModifierProperty(PsiModifier.ABSTRACT));
-
- setAnonymous(psiClass instanceof PsiAnonymousClass);
- setIsLocal(!(isAnonymous() || psiParent instanceof PsiClass || psiParent instanceof PsiFile));
- setInterface(psiClass.isInterface());
-
- initializeSuperReferences(psiClass);
-
- PsiMethod[] psiMethods = psiClass.getMethods();
- PsiField[] psiFields = psiClass.getFields();
-
- setUtilityClass(psiMethods.length > 0 || psiFields.length > 0);
-
- for (PsiField psiField : psiFields) {
- getRefManager().getReference(psiField);
- }
-
- if (!isApplet()) {
- final PsiClass servlet = getRefJavaManager().getServlet();
- setServlet(servlet != null && psiClass.isInheritor(servlet, true));
- }
- if (!isApplet() && !isServlet()) {
- final boolean isTestClass = TestFrameworks.getInstance().isTestClass(psiClass);
- setTestCase(isTestClass);
- if (isTestClass) {
- for (RefClass refBase : getBaseClasses()) {
- ((RefClassImpl)refBase).setTestCase(true);
- }
- }
- }
-
- for (PsiMethod psiMethod : psiMethods) {
- RefMethod refMethod = (RefMethod)getRefManager().getReference(psiMethod);
-
- if (refMethod != null) {
- if (psiMethod.isConstructor()) {
- if (psiMethod.getParameterList().getParametersCount() > 0 || !psiMethod.hasModifierProperty(PsiModifier.PRIVATE)) {
- setUtilityClass(false);
- }
-
- addConstructor(refMethod);
- if (psiMethod.getParameterList().getParametersCount() == 0) {
- setDefaultConstructor((RefMethodImpl)refMethod);
- }
- }
- else {
- if (!psiMethod.hasModifierProperty(PsiModifier.STATIC)) {
- setUtilityClass(false);
- }
- }
- }
- }
-
- if (getConstructors().isEmpty() && !isInterface() && !isAnonymous()) {
- RefImplicitConstructorImpl refImplicitConstructor = new RefImplicitConstructorImpl(this);
- setDefaultConstructor(refImplicitConstructor);
- addConstructor(refImplicitConstructor);
- }
-
- if (isInterface()) {
- for (int i = 0; i < psiFields.length && isUtilityClass(); i++) {
- PsiField psiField = psiFields[i];
- if (!psiField.hasModifierProperty(PsiModifier.STATIC)) {
- setUtilityClass(false);
- }
- }
- }
-
-
- final PsiClass applet = getRefJavaManager().getApplet();
- setApplet(applet != null && psiClass.isInheritor(applet, true));
- PsiManager psiManager = getRefManager().getPsiManager();
- psiManager.dropResolveCaches();
- PsiFile file = psiClass.getContainingFile();
- if (file != null) {
- InjectedLanguageManager.getInstance(file.getProject()).dropFileCaches(file);
- }
- }
-
- private void initializeSuperReferences(PsiClass psiClass) {
- if (!isSelfInheritor(psiClass)) {
- for (PsiClass psiSuperClass : psiClass.getSupers()) {
- if (getRefManager().belongsToScope(psiSuperClass)) {
- RefClassImpl refClass = (RefClassImpl)getRefManager().getReference(psiSuperClass);
- if (refClass != null) {
- addBaseClass(refClass);
- refClass.addSubClass(this);
- }
- }
- }
- }
- }
-
- @Override
- public boolean isSelfInheritor(PsiClass psiClass) {
- return isSelfInheritor(psiClass, new ArrayList<PsiClass>());
- }
-
- @Override
- public PsiClass getElement() {
- return (PsiClass)super.getElement();
- }
-
- private static boolean isSelfInheritor(PsiClass psiClass, ArrayList<PsiClass> visited) {
- if (visited.contains(psiClass)) return true;
-
- visited.add(psiClass);
- for (PsiClass aSuper : psiClass.getSupers()) {
- if (isSelfInheritor(aSuper, visited)) return true;
- }
- visited.remove(psiClass);
-
- return false;
- }
-
- private void setDefaultConstructor(RefMethodImpl defaultConstructor) {
- if (defaultConstructor != null) {
- for (RefClass superClass : getBaseClasses()) {
- RefMethodImpl superDefaultConstructor = (RefMethodImpl)superClass.getDefaultConstructor();
-
- if (superDefaultConstructor != null) {
- superDefaultConstructor.addInReference(defaultConstructor);
- defaultConstructor.addOutReference(superDefaultConstructor);
- }
- }
- }
-
- myDefaultConstructor = defaultConstructor;
- }
-
- @Override
- public void buildReferences() {
- PsiClass psiClass = getElement();
-
- if (psiClass != null) {
- for (PsiClassInitializer classInitializer : psiClass.getInitializers()) {
- RefJavaUtil.getInstance().addReferences(psiClass, this, classInitializer.getBody());
- }
-
- RefJavaUtil.getInstance().addReferences(psiClass, this, psiClass.getModifierList());
-
- PsiField[] psiFields = psiClass.getFields();
- for (PsiField psiField : psiFields) {
- getRefManager().getReference(psiField);
- final PsiExpression initializer = psiField.getInitializer();
- if (initializer != null) {
- RefJavaUtil.getInstance().addReferences(psiClass, this, initializer);
- }
- }
-
- PsiMethod[] psiMethods = psiClass.getMethods();
- for (PsiMethod psiMethod : psiMethods) {
- getRefManager().getReference(psiMethod);
- }
- getRefManager().fireBuildReferences(this);
- }
- }
-
- @Override
- public void accept(@NotNull final RefVisitor visitor) {
- if (visitor instanceof RefJavaVisitor) {
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- @Override
- public void run() {
- ((RefJavaVisitor)visitor).visitClass(RefClassImpl.this);
- }
- });
- } else {
- super.accept(visitor);
- }
- }
-
- @Override
- @NotNull
- public Set<RefClass> getBaseClasses() {
- if (myBases == null) return EMPTY_CLASS_SET;
- return myBases;
- }
-
- private void addBaseClass(RefClass refClass){
- if (myBases == null) {
- myBases = Collections.singleton(refClass);
- return;
- }
- if (myBases.size() == 1) {
- // convert from singleton
- myBases = new THashSet<RefClass>(myBases);
- }
- myBases.add(refClass);
- }
-
- @Override
- @NotNull
- public Set<RefClass> getSubClasses() {
- if (mySubClasses == null) return EMPTY_CLASS_SET;
- return mySubClasses;
- }
-
- private void addSubClass(@NotNull RefClass refClass){
- if (mySubClasses == null) {
- mySubClasses = Collections.singleton(refClass);
- return;
- }
- if (mySubClasses.size() == 1) {
- // convert from singleton
- mySubClasses = new THashSet<RefClass>(mySubClasses);
- }
- mySubClasses.add(refClass);
- }
- private void removeSubClass(RefClass refClass){
- if (mySubClasses == null) return;
- if (mySubClasses.size() == 1) {
- mySubClasses = null;
- }
- else {
- mySubClasses.remove(refClass);
- }
- }
-
- @Override
- @NotNull
- public List<RefMethod> getConstructors() {
- if (myConstructors == null) return EMPTY_METHOD_LIST;
- return myConstructors;
- }
-
- @Override
- @NotNull
- public Set<RefElement> getInTypeReferences() {
- if (myInTypeReferences == null) return EMPTY_SET;
- return myInTypeReferences;
- }
-
- public void addTypeReference(RefJavaElement from) {
- if (from != null) {
- if (myInTypeReferences == null){
- myInTypeReferences = new THashSet<RefElement>(1);
- }
- myInTypeReferences.add(from);
- ((RefJavaElementImpl)from).addOutTypeRefernce(this);
- getRefManager().fireNodeMarkedReferenced(this, from, false, false, false);
- }
- }
-
- @Override
- @NotNull
- public Set<RefElement> getInstanceReferences() {
- if (myInstanceReferences == null) return EMPTY_SET;
- return myInstanceReferences;
- }
-
- public void addInstanceReference(RefElement from) {
- if (myInstanceReferences == null){
- myInstanceReferences = new THashSet<RefElement>(1);
- }
- myInstanceReferences.add(from);
- }
-
- @Override
- public RefMethod getDefaultConstructor() {
- return myDefaultConstructor;
- }
-
- private void addConstructor(RefMethod refConstructor) {
- if (myConstructors == null){
- myConstructors = new ArrayList<RefMethod>(1);
- }
- myConstructors.add(refConstructor);
- }
-
- public void addLibraryOverrideMethod(RefMethod refMethod) {
- if (myOverridingMethods == null){
- myOverridingMethods = new ArrayList<RefMethod>(2);
- }
- myOverridingMethods.add(refMethod);
- }
-
- @Override
- @NotNull
- public List<RefMethod> getLibraryMethods() {
- if (myOverridingMethods == null) return EMPTY_METHOD_LIST;
- return myOverridingMethods;
- }
-
- @Override
- public boolean isAnonymous() {
- return checkFlag(IS_ANONYMOUS_MASK);
- }
-
- @Override
- public boolean isInterface() {
- return checkFlag(IS_INTERFACE_MASK);
- }
-
- @Override
- public boolean isSuspicious() {
- return !(isUtilityClass() && getOutReferences().isEmpty()) && super.isSuspicious();
- }
-
- @Override
- public boolean isUtilityClass() {
- return checkFlag(IS_UTILITY_MASK);
- }
-
- @Override
- public String getExternalName() {
- final String[] result = new String[1];
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- @Override
- public void run() {//todo synthetic JSP
- final PsiClass psiClass = getElement();
- LOG.assertTrue(psiClass != null);
- result[0] = PsiFormatUtil.getExternalName(psiClass);
- }
- });
- return result[0];
- }
-
-
- @Nullable
- public static RefClass classFromExternalName(RefManager manager, String externalName) {
- return (RefClass) manager.getReference(ClassUtil.findPsiClass(PsiManager.getInstance(manager.getProject()), externalName));
- }
-
- @Override
- public void referenceRemoved() {
- super.referenceRemoved();
-
- for (RefClass subClass : getSubClasses()) {
- ((RefClassImpl)subClass).removeBase(this);
- }
-
- for (RefClass superClass : getBaseClasses()) {
- ((RefClassImpl)superClass).removeSubClass(this);
- }
- }
-
- private void removeBase(RefClass superClass) {
- final Set<RefClass> baseClasses = getBaseClasses();
- if (baseClasses.contains(superClass)) {
- if (baseClasses.size() == 1) {
- myBases = null;
- return;
- }
- baseClasses.remove(superClass);
- }
- }
-
- protected void methodRemoved(RefMethod method) {
- getConstructors().remove(method);
- getLibraryMethods().remove(method);
-
- if (getDefaultConstructor() == method) {
- setDefaultConstructor(null);
- }
- }
-
- @Override
- public boolean isAbstract() {
- return checkFlag(IS_ABSTRACT_MASK);
- }
-
- @Override
- public boolean isApplet() {
- return checkFlag(IS_APPLET_MASK);
- }
-
- @Override
- public boolean isServlet() {
- return checkFlag(IS_SERVLET_MASK);
- }
-
- @Override
- public boolean isTestCase() {
- return checkFlag(IS_TESTCASE_MASK);
- }
-
- @Override
- public boolean isLocalClass() {
- return checkFlag(IS_LOCAL_MASK);
- }
-
-
- @Override
- public boolean isReferenced() {
- if (super.isReferenced()) return true;
-
- if (isInterface() || isAbstract()) {
- if (!getSubClasses().isEmpty()) return true;
- }
-
- return false;
- }
-
- @Override
- public boolean hasSuspiciousCallers() {
- if (super.hasSuspiciousCallers()) return true;
-
- if (isInterface() || isAbstract()) {
- if (!getSubClasses().isEmpty()) return true;
- }
-
- return false;
- }
-
- public void addClassExporter(RefJavaElement exporter) {
- if (myClassExporters == null) myClassExporters = new ArrayList<RefJavaElement>(1);
- if (myClassExporters.contains(exporter)) return;
- myClassExporters.add(exporter);
- }
-
- public List<RefJavaElement> getClassExporters() {
- return myClassExporters;
- }
-
- private void setAnonymous(boolean anonymous) {
- setFlag(anonymous, IS_ANONYMOUS_MASK);
- }
-
- private void setInterface(boolean anInterface) {
- setFlag(anInterface, IS_INTERFACE_MASK);
- }
-
- private void setUtilityClass(boolean utilityClass) {
- setFlag(utilityClass, IS_UTILITY_MASK);
- }
-
- private void setAbstract(boolean anAbstract) {
- setFlag(anAbstract, IS_ABSTRACT_MASK);
- }
-
- private void setApplet(boolean applet) {
- setFlag(applet, IS_APPLET_MASK);
- }
-
- private void setServlet(boolean servlet) {
- setFlag(servlet, IS_SERVLET_MASK);
- }
-
- private void setTestCase(boolean testCase) {
- setFlag(testCase, IS_TESTCASE_MASK);
- }
-
- private void setIsLocal(boolean isLocal) {
- setFlag(isLocal, IS_LOCAL_MASK);
- }
-
- @Override
- @NotNull
- public RefElement getContainingEntry() {
- RefElement defaultConstructor = getDefaultConstructor();
- if (defaultConstructor != null) return defaultConstructor;
- return super.getContainingEntry();
- }
-}
-
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java
deleted file mode 100644
index 35262e3e725c..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright 2000-2009 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.reference;
-
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.util.Computable;
-import com.intellij.psi.*;
-import com.intellij.psi.util.ClassUtil;
-import com.intellij.psi.util.PsiFormatUtil;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author max
- * Date: Oct 21, 2001
- */
-public class RefFieldImpl extends RefJavaElementImpl implements RefField {
- private static final int USED_FOR_READING_MASK = 0x10000;
- private static final int USED_FOR_WRITING_MASK = 0x20000;
- private static final int ASSIGNED_ONLY_IN_INITIALIZER = 0x40000;
-
- RefFieldImpl(@NotNull RefClass ownerClass, PsiField field, RefManager manager) {
- super(field, manager);
-
- ((RefClassImpl)ownerClass).add(this);
-
- if (ownerClass.isInterface()) {
- setIsStatic(true);
- setIsFinal(true);
- }
- }
-
- @Override
- public PsiField getElement() {
- return (PsiField)super.getElement();
- }
-
- @Override
- protected void markReferenced(RefElementImpl refFrom, PsiElement psiFrom, PsiElement psiWhat, boolean forWriting, boolean forReading, PsiReferenceExpression expressionFrom) {
- addInReference(refFrom);
-
- boolean referencedFromClassInitializer = false;
-
- if (forWriting && expressionFrom != null) {
- PsiClassInitializer initializer = PsiTreeUtil.getParentOfType(expressionFrom, PsiClassInitializer.class);
- if (initializer != null) {
- if (initializer.getParent() instanceof PsiClass && psiFrom == initializer.getParent() && !expressionFrom.isQualified()) {
- referencedFromClassInitializer = true;
- }
- }
- }
-
- if (forWriting) {
- setUsedForWriting(true);
- }
-
- if (forReading) {
- setUsedForReading(true);
- }
- getRefManager().fireNodeMarkedReferenced(this, refFrom, referencedFromClassInitializer, forReading, forWriting);
- }
-
- @Override
- public boolean isUsedForReading() {
- return checkFlag(USED_FOR_READING_MASK);
- }
-
- private void setUsedForReading(boolean usedForReading) {
- setFlag(usedForReading, USED_FOR_READING_MASK);
- }
-
- @Override
- public boolean isUsedForWriting() {
- return checkFlag(USED_FOR_WRITING_MASK);
- }
-
- private void setUsedForWriting(boolean usedForWriting) {
- setFlag(false, ASSIGNED_ONLY_IN_INITIALIZER);
- setFlag(usedForWriting, USED_FOR_WRITING_MASK);
- }
-
- @Override
- public boolean isOnlyAssignedInInitializer() {
- return checkFlag(ASSIGNED_ONLY_IN_INITIALIZER);
- }
-
- @Override
- public void accept(@NotNull final RefVisitor visitor) {
- if (visitor instanceof RefJavaVisitor) {
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- @Override
- public void run() {
- ((RefJavaVisitor)visitor).visitField(RefFieldImpl.this);
- }
- });
- } else {
- super.accept(visitor);
- }
- }
-
- @Override
- public void buildReferences() {
- PsiField psiField = getElement();
- if (psiField != null) {
- final RefJavaUtil refUtil = RefJavaUtil.getInstance();
- refUtil.addReferences(psiField, this, psiField.getInitializer());
- refUtil.addReferences(psiField, this, psiField.getModifierList());
- if (psiField instanceof PsiEnumConstant) {
- refUtil.addReferences(psiField, this, psiField);
- }
-
- if (psiField.getInitializer() != null || psiField instanceof PsiEnumConstant) {
- if (!checkFlag(USED_FOR_WRITING_MASK)) {
- setFlag(true, ASSIGNED_ONLY_IN_INITIALIZER);
- setFlag(true, USED_FOR_WRITING_MASK);
- }
- }
- PsiType psiType = psiField.getType();
- RefClass ownerClass = refUtil.getOwnerClass(getRefManager(), psiField);
-
- if (ownerClass != null) {
- psiType = psiType.getDeepComponentType();
- if (psiType instanceof PsiClassType) {
- PsiClass psiClass = PsiUtil.resolveClassInType(psiType);
- if (psiClass != null && getRefManager().belongsToScope(psiClass)) {
- RefClassImpl refClass = (RefClassImpl)getRefManager().getReference(psiClass);
- if (refClass != null) {
- refClass.addTypeReference(ownerClass);
- refClass.addClassExporter(this);
- }
- }
- }
-
- }
- getRefManager().fireBuildReferences(this);
- }
- }
-
- @Override
- public RefClass getOwnerClass() {
- return (RefClass) getOwner();
- }
-
- @Override
- public String getExternalName() {
- return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
- @Override
- public String compute() {
- PsiField psiField = getElement();
- return psiField != null ? PsiFormatUtil.getExternalName(psiField) : null;
- }
- });
- }
-
- @Nullable
- public static RefField fieldFromExternalName(RefManager manager, String externalName) {
- return (RefField)manager.getReference(findPsiField(PsiManager.getInstance(manager.getProject()), externalName));
- }
-
- @Nullable
- public static PsiField findPsiField(PsiManager manager, String externalName) {
- int classNameDelimeter = externalName.lastIndexOf(' ');
- if (classNameDelimeter > 0 && classNameDelimeter < externalName.length() - 1) {
- final String className = externalName.substring(0, classNameDelimeter);
- final String fieldName = externalName.substring(classNameDelimeter + 1);
- final PsiClass psiClass = ClassUtil.findPsiClass(manager, className);
- if (psiClass != null) {
- return psiClass.findFieldByName(fieldName, false);
- }
- }
- return null;
- }
-
- @Override
- public boolean isSuspicious() {
- if (isEntry()) return false;
- if (super.isSuspicious()) return true;
- return isUsedForReading() != isUsedForWriting();
- }
-
- @Override
- protected void initialize() {
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java
deleted file mode 100644
index 7dd92822237d..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Nov 28, 2001
- * Time: 4:17:17 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.codeInspection.InspectionsBundle;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.util.Computable;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiModifierListOwner;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public class RefImplicitConstructorImpl extends RefMethodImpl implements RefImplicitConstructor {
-
- RefImplicitConstructorImpl(RefClass ownerClass) {
- super(InspectionsBundle.message("inspection.reference.implicit.constructor.name", ownerClass.getName()), ownerClass);
- }
-
- @Override
- public void buildReferences() {
- getRefManager().fireBuildReferences(this);
- }
-
- @Override
- public boolean isSuspicious() {
- return ((RefClassImpl)getOwnerClass()).isSuspicious();
- }
-
- @NotNull
- @Override
- public String getName() {
- return InspectionsBundle.message("inspection.reference.implicit.constructor.name", getOwnerClass().getName());
- }
-
- @Override
- public String getExternalName() {
- return getOwnerClass().getExternalName();
- }
-
- @Override
- public boolean isValid() {
- return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
- @Override
- public Boolean compute() {
- return getOwnerClass().isValid();
- }
- }).booleanValue();
- }
-
- @Override
- public String getAccessModifier() {
- return getOwnerClass().getAccessModifier();
- }
-
- @Override
- public void setAccessModifier(String am) {
- RefJavaUtil.getInstance().setAccessModifier(getOwnerClass(), am);
- }
-
- @Override
- public PsiModifierListOwner getElement() {
- return getOwnerClass().getElement();
- }
-
- @Override
- @Nullable
- public PsiFile getContainingFile() {
- return ((RefClassImpl)getOwnerClass()).getContainingFile();
- }
-
- @Override
- public RefClass getOwnerClass() {
- return myOwnerClass;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java
deleted file mode 100644
index c0cd71eda18a..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * User: anna
- * Date: 20-Dec-2007
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.codeInspection.InspectionsBundle;
-import com.intellij.openapi.util.Iconable;
-import com.intellij.psi.*;
-import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
-import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
-import com.intellij.util.IconUtil;
-import com.intellij.util.containers.Stack;
-import gnu.trove.THashSet;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-
-public abstract class RefJavaElementImpl extends RefElementImpl implements RefJavaElement {
- private Set<RefClass> myOutTypeReferences;
- private static final int ACCESS_MODIFIER_MASK = 0x03;
- private static final int ACCESS_PRIVATE = 0x00;
- private static final int ACCESS_PROTECTED = 0x01;
- private static final int ACCESS_PACKAGE = 0x02;
- private static final int ACCESS_PUBLIC = 0x03;
- private static final int IS_STATIC_MASK = 0x04;
- private static final int IS_FINAL_MASK = 0x08;
- private static final int IS_USES_DEPRECATION_MASK = 0x200;
- private static final int IS_SYNTHETIC_JSP_ELEMENT = 0x400;
-
- protected RefJavaElementImpl(String name, @NotNull RefJavaElement owner) {
- super(name, owner);
- String am = owner.getAccessModifier();
- doSetAccessModifier(am);
-
- final boolean synthOwner = owner.isSyntheticJSP();
- if (synthOwner) {
- setSyntheticJSP(true);
- }
- }
-
- protected RefJavaElementImpl(PsiFile file, RefManager manager) {
- super(file, manager);
- }
-
- protected RefJavaElementImpl(PsiModifierListOwner elem, RefManager manager) {
- super(getName(elem), elem, manager);
-
- setAccessModifier(RefJavaUtil.getInstance().getAccessModifier(elem));
- final boolean isSynth = elem instanceof JspHolderMethod || elem instanceof JspClass;
- if (isSynth) {
- setSyntheticJSP(true);
- }
-
- setIsStatic(elem.hasModifierProperty(PsiModifier.STATIC));
- setIsFinal(elem.hasModifierProperty(PsiModifier.FINAL));
- }
-
- @Override
- @NotNull
- public Collection<RefClass> getOutTypeReferences() {
- if (myOutTypeReferences == null){
- return Collections.emptySet();
- }
- return myOutTypeReferences;
- }
-
- public void addOutTypeRefernce(RefClass refClass){
- if (myOutTypeReferences == null){
- myOutTypeReferences = new THashSet<RefClass>();
- }
- myOutTypeReferences.add(refClass);
- }
-
- public static String getName(PsiElement element) {
- if (element instanceof PsiAnonymousClass) {
- PsiAnonymousClass psiAnonymousClass = (PsiAnonymousClass)element;
- PsiClass psiBaseClass = psiAnonymousClass.getBaseClassType().resolve();
- return InspectionsBundle.message("inspection.reference.anonymous.name", psiBaseClass == null ? "" : psiBaseClass.getQualifiedName());
- }
-
- if (element instanceof JspClass) {
- final JspClass jspClass = (JspClass)element;
- final PsiFile jspxFile = jspClass.getContainingFile();
- return "<" + jspxFile.getName() + ">";
- }
-
- if (element instanceof JspHolderMethod) {
- return InspectionsBundle.message("inspection.reference.jsp.holder.method.anonymous.name");
- }
-
- String name = null;
- if (element instanceof PsiNamedElement) {
- name = ((PsiNamedElement)element).getName();
- }
-
- return name == null ? InspectionsBundle.message("inspection.reference.anonymous") : name;
- }
-
- @Override
- public boolean isFinal() {
- return checkFlag(IS_FINAL_MASK);
- }
-
- @Override
- public boolean isStatic() {
- return checkFlag(IS_STATIC_MASK);
- }
-
- public void setIsStatic(boolean isStatic) {
- setFlag(isStatic, IS_STATIC_MASK);
- }
-
- @Override
- public boolean isUsesDeprecatedApi() {
- return checkFlag(IS_USES_DEPRECATION_MASK);
- }
-
- public void setUsesDeprecatedApi(boolean usesDeprecatedApi) {
- setFlag(usesDeprecatedApi, IS_USES_DEPRECATION_MASK);
- }
-
- public void setIsFinal(boolean isFinal) {
- setFlag(isFinal, IS_FINAL_MASK);
- }
-
- public void setReachable(boolean reachable) {
- setFlag(reachable, IS_REACHABLE_MASK);
- }
-
- @Override
- public boolean isSyntheticJSP() {
- return checkFlag(IS_SYNTHETIC_JSP_ELEMENT);
- }
-
- public void setSyntheticJSP(boolean b) {
- setFlag(b, IS_SYNTHETIC_JSP_ELEMENT);
- }
-
- @Override
- @Nullable
- public String getAccessModifier() {
- long access_id = myFlags & ACCESS_MODIFIER_MASK;
- if (access_id == ACCESS_PRIVATE) return PsiModifier.PRIVATE;
- if (access_id == ACCESS_PUBLIC) return PsiModifier.PUBLIC;
- if (access_id == ACCESS_PACKAGE) return PsiModifier.PACKAGE_LOCAL;
- return PsiModifier.PROTECTED;
- }
-
- public void setAccessModifier(String am) {
- doSetAccessModifier(am);
- }
-
- private void doSetAccessModifier(String am) {
- final int access_id;
-
- if (PsiModifier.PRIVATE.equals(am)) {
- access_id = ACCESS_PRIVATE;
- }
- else if (PsiModifier.PUBLIC.equals(am)) {
- access_id = ACCESS_PUBLIC;
- }
- else if (PsiModifier.PACKAGE_LOCAL.equals(am)) {
- access_id = ACCESS_PACKAGE;
- }
- else {
- access_id = ACCESS_PROTECTED;
- }
-
- myFlags = myFlags & ~0x3 | access_id;
- }
-
- public boolean isSuspiciousRecursive() {
- return isCalledOnlyFrom(this, new Stack<RefJavaElement>());
- }
-
- private boolean isCalledOnlyFrom(RefJavaElement refElement, Stack<RefJavaElement> callStack) {
- if (callStack.contains(this)) return refElement == this;
- if (getInReferences().isEmpty()) return false;
-
- if (refElement instanceof RefMethod) {
- RefMethod refMethod = (RefMethod) refElement;
- for (RefMethod refSuper : refMethod.getSuperMethods()) {
- if (!refSuper.getInReferences().isEmpty()) return false;
- }
- if (refMethod.isConstructor()){
- boolean unreachable = true;
- for (RefElement refOut : refMethod.getOutReferences()){
- unreachable &= !refOut.isReachable();
- }
- if (unreachable) return true;
- }
- }
-
- callStack.push(this);
- for (RefElement refCaller : getInReferences()) {
- if (!((RefElementImpl)refCaller).isSuspicious() || !((RefJavaElementImpl)refCaller).isCalledOnlyFrom(refElement, callStack)) {
- callStack.pop();
- return false;
- }
- }
-
- callStack.pop();
- return true;
- }
-
- public void addReference(RefElement refWhat, PsiElement psiWhat, PsiElement psiFrom, boolean forWriting, boolean forReading, PsiReferenceExpression expression) {
- if (refWhat != null) {
- if (refWhat instanceof RefParameter) {
- if (forWriting) {
- ((RefParameter)refWhat).parameterReferenced(true);
- }
- if (forReading) {
- ((RefParameter)refWhat).parameterReferenced(false);
- }
- }
- addOutReference(refWhat);
- ((RefJavaElementImpl)refWhat).markReferenced(this, psiFrom, psiWhat, forWriting, forReading, expression);
- } else {
- if (psiWhat instanceof PsiMethod) {
- final PsiClass containingClass = ((PsiMethod)psiWhat).getContainingClass();
- if (containingClass != null && containingClass.isEnum() && "values".equals(((PsiMethod)psiWhat).getName())) {
- for (PsiField enumConstant : containingClass.getFields()) {
- if (enumConstant instanceof PsiEnumConstant) {
- final RefJavaElementImpl enumConstantReference = (RefJavaElementImpl)getRefManager().getReference(enumConstant);
- if (enumConstantReference != null) {
- addOutReference(enumConstantReference);
- enumConstantReference.markReferenced(this, psiFrom, enumConstant, false, true, expression);
- }
- }
- }
- }
- }
- }
- }
-
- protected void markReferenced(final RefElementImpl refFrom, PsiElement psiFrom, PsiElement psiWhat, final boolean forWriting, boolean forReading, PsiReferenceExpression expressionFrom) {
- addInReference(refFrom);
- getRefManager().fireNodeMarkedReferenced(this, refFrom, false, forReading, forWriting);
- }
-
- protected RefJavaManager getRefJavaManager() {
- return getRefManager().getExtension(RefJavaManager.MANAGER);
- }
-
- @Override
- public void referenceRemoved() {
- super.referenceRemoved();
- if (isEntry()) {
- getRefJavaManager().getEntryPointsManager().removeEntryPoint(this);
- }
- }
-
- @Override
- public Icon getIcon(final boolean expanded) {
- if (isSyntheticJSP()) {
- final PsiElement element = getElement();
- if (element != null && element.isValid()) {
- return IconUtil.getIcon(element.getContainingFile().getVirtualFile(),
- Iconable.ICON_FLAG_VISIBILITY | Iconable.ICON_FLAG_READ_STATUS, element.getProject());
- }
- }
- return super.getIcon(expanded);
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaFileImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaFileImpl.java
deleted file mode 100644
index 9bfd6f01c07d..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaFileImpl.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * User: anna
- * Date: 20-Dec-2007
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.psi.PsiJavaFile;
-
-public class RefJavaFileImpl extends RefFileImpl {
- RefJavaFileImpl(PsiJavaFile elem, RefManager manager) {
- super(elem, manager);
- ((RefPackageImpl)getRefManager().getExtension(RefJavaManager.MANAGER).getPackage(elem.getPackageName())).add(this);
- }
-} \ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
index 8ebd6ab6a87b..f53e1fb6e824 100644
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
@@ -122,11 +122,6 @@ public class RefJavaManagerImpl extends RefJavaManager {
return file != null ? DEAD_CODE_TOOL.get(file, myRefManager).get() : null;
}
- public boolean isEntryPoint(PsiElement element) {
- UnusedDeclarationInspection tool = getDeadCodeTool(element);
- return tool != null && tool.isEntryPoint(element);
- }
-
@Override
public RefPackage getDefaultPackage() {
if (myDefaultPackage == null) {
@@ -349,7 +344,7 @@ public class RefJavaManagerImpl extends RefJavaManager {
private static void appendPackageElement(final Element element, final String packageName) {
final Element packageElement = new Element("package");
- packageElement.addContent(packageName.length() > 0 ? packageName : InspectionsBundle.message("inspection.export.results.default"));
+ packageElement.addContent(packageName.isEmpty() ? InspectionsBundle.message("inspection.export.results.default") : packageName);
element.addContent(packageElement);
}
@@ -358,7 +353,7 @@ public class RefJavaManagerImpl extends RefJavaManager {
if (myEntryPointsManager == null) {
final Project project = myRefManager.getProject();
myEntryPointsManager = new EntryPointsManagerImpl(project);
- ((EntryPointsManagerImpl)myEntryPointsManager).addAllPersistentEntries(EntryPointsManagerImpl.getInstance(project));
+ ((EntryPointsManagerBase)myEntryPointsManager).addAllPersistentEntries(EntryPointsManagerBase.getInstance(project));
}
return myEntryPointsManager;
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java
deleted file mode 100644
index 71fa80a2077f..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * User: anna
- * Date: 21-Dec-2007
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.codeInspection.InspectionsBundle;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.MethodSignatureUtil;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.VisibilityUtil;
-import org.jetbrains.annotations.Nullable;
-
-public class RefJavaUtilImpl extends RefJavaUtil{
-
- @Override
- public void addReferences(final PsiModifierListOwner psiFrom, final RefJavaElement ref, @Nullable PsiElement findIn) {
- final RefJavaElementImpl refFrom = (RefJavaElementImpl)ref;
- if (findIn != null) {
- findIn.accept(
- new JavaRecursiveElementWalkingVisitor() {
- @Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
- }
-
- @Override public void visitReferenceExpression(PsiReferenceExpression expression) {
- visitElement(expression);
-
- PsiElement psiResolved = expression.resolve();
-
- if (psiResolved instanceof PsiModifierListOwner) {
- if (isDeprecated(psiResolved)) refFrom.setUsesDeprecatedApi(true);
- }
-
- RefElement refResolved = refFrom.getRefManager().getReference(psiResolved);
- refFrom.addReference(
- refResolved, psiResolved, psiFrom, PsiUtil.isAccessedForWriting(expression),
- PsiUtil.isAccessedForReading(expression), expression
- );
-
- if (refResolved instanceof RefMethod) {
- updateRefMethod(psiResolved, refResolved, expression, psiFrom, refFrom);
- }
- }
-
-
- @Override public void visitEnumConstant(PsiEnumConstant enumConstant) {
- super.visitEnumConstant(enumConstant);
- processNewLikeConstruct(enumConstant.resolveConstructor(), enumConstant.getArgumentList());
- }
-
- @Override public void visitNewExpression(PsiNewExpression newExpr) {
- super.visitNewExpression(newExpr);
- PsiMethod psiConstructor = newExpr.resolveConstructor();
- final PsiExpressionList argumentList = newExpr.getArgumentList();
-
- RefMethod refConstructor = processNewLikeConstruct(psiConstructor, argumentList);
-
- if (refConstructor == null) { // No explicit constructor referenced. Should use default one.
- PsiType newType = newExpr.getType();
- if (newType instanceof PsiClassType) {
- processClassReference(PsiUtil.resolveClassInType(newType), refFrom, psiFrom, true);
- }
- }
- }
-
- @Nullable
- private RefMethod processNewLikeConstruct(final PsiMethod psiConstructor, final PsiExpressionList argumentList) {
- if (psiConstructor != null) {
- if (isDeprecated(psiConstructor)) refFrom.setUsesDeprecatedApi(true);
- }
-
- RefMethodImpl refConstructor = (RefMethodImpl)refFrom.getRefManager().getReference(
- psiConstructor
- );
- refFrom.addReference(refConstructor, psiConstructor, psiFrom, false, true, null);
-
- if (argumentList != null) {
- PsiExpression[] psiParams = argumentList.getExpressions();
- for (PsiExpression param : psiParams) {
- param.accept(this);
- }
-
- if (refConstructor != null) {
- refConstructor.updateParameterValues(psiParams);
- }
- }
- return refConstructor;
- }
-
- @Override public void visitAnonymousClass(PsiAnonymousClass psiClass) {
- super.visitAnonymousClass(psiClass);
- RefClassImpl refClass = (RefClassImpl)refFrom.getRefManager().getReference(psiClass);
- refFrom.addReference(refClass, psiClass, psiFrom, false, true, null);
- }
-
- @Override public void visitReturnStatement(PsiReturnStatement statement) {
- super.visitReturnStatement(statement);
-
- if (refFrom instanceof RefMethodImpl) {
- RefMethodImpl refMethod = (RefMethodImpl)refFrom;
- refMethod.updateReturnValueTemplate(statement.getReturnValue());
- }
- }
-
- @Override public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
- super.visitClassObjectAccessExpression(expression);
- final PsiTypeElement operand = expression.getOperand();
- final PsiType type = operand.getType();
- if (type instanceof PsiClassType) {
- processClassReference(((PsiClassType)type).resolve(), refFrom, psiFrom, false);
- }
- }
-
- private void processClassReference(final PsiClass psiClass,
- final RefJavaElementImpl refFrom,
- final PsiModifierListOwner psiFrom,
- boolean defaultConstructorOnly) {
- if (psiClass != null) {
- RefClassImpl refClass = (RefClassImpl)refFrom.getRefManager().getReference(psiClass);
-
- if (refClass != null) {
- boolean hasConstructorsMarked = false;
-
- if (defaultConstructorOnly) {
- RefMethodImpl refDefaultConstructor = (RefMethodImpl)refClass.getDefaultConstructor();
- if (refDefaultConstructor != null && !(refDefaultConstructor instanceof RefImplicitConstructor)) {
- refDefaultConstructor.addInReference(refFrom);
- refFrom.addOutReference(refDefaultConstructor);
- hasConstructorsMarked = true;
- }
- }
- else {
- for (RefMethod cons : refClass.getConstructors()) {
- if (cons instanceof RefImplicitConstructor) continue;
- ((RefMethodImpl)cons).addInReference(refFrom);
- refFrom.addOutReference(cons);
- hasConstructorsMarked = true;
- }
- }
-
- if (!hasConstructorsMarked) {
- refFrom.addReference(refClass, psiClass, psiFrom, false, true, null);
- }
- }
- }
- }
- }
- );
- }
- }
-
- private void updateRefMethod(PsiElement psiResolved,
- RefElement refResolved,
- PsiElement refExpression,
- final PsiElement psiFrom,
- final RefElement refFrom) {
- PsiMethod psiMethod = (PsiMethod)psiResolved;
- RefMethodImpl refMethod = (RefMethodImpl)refResolved;
-
- PsiMethodCallExpression call = PsiTreeUtil.getParentOfType(
- refExpression,
- PsiMethodCallExpression.class
- );
- if (call != null) {
- PsiType returnType = psiMethod.getReturnType();
- if (!psiMethod.isConstructor() && returnType != PsiType.VOID) {
- if (!(call.getParent() instanceof PsiExpressionStatement)) {
- refMethod.setReturnValueUsed(true);
- }
-
- addTypeReference(psiFrom, returnType, refFrom.getRefManager());
- }
-
- PsiExpressionList argumentList = call.getArgumentList();
- if (argumentList.getExpressions().length > 0) {
- refMethod.updateParameterValues(argumentList.getExpressions());
- }
-
- final PsiExpression psiExpression = call.getMethodExpression().getQualifierExpression();
- if (psiExpression != null) {
- final PsiType usedType = psiExpression.getType();
- if (usedType != null) {
- final String fqName = psiMethod.getContainingClass().getQualifiedName();
- if (fqName != null) {
- final PsiClassType methodOwnerType = JavaPsiFacade.getInstance(call.getProject()).getElementFactory()
- .createTypeByFQClassName(fqName, GlobalSearchScope.allScope(psiMethod.getProject()));
- if (!usedType.equals(methodOwnerType)) {
- refMethod.setCalledOnSubClass(true);
- }
- }
- }
- }
- }
- }
-
-
-
-
- @Override
- public RefClass getTopLevelClass(RefElement refElement) {
- RefEntity refParent = refElement.getOwner();
-
- while (refParent != null && refParent instanceof RefElement && !(refParent instanceof RefFile)) {
- refElement = (RefElementImpl)refParent;
- refParent = refParent.getOwner();
- }
-
- return (RefClass)refElement;
- }
-
- @Override
- public boolean isInheritor(RefClass subClass, RefClass superClass) {
- if (subClass == superClass) return true;
-
- for (RefClass baseClass : subClass.getBaseClasses()) {
- if (isInheritor(baseClass, superClass)) return true;
- }
-
- return false;
- }
-
- @Override
- @Nullable
- public String getPackageName(RefEntity refEntity) {
- if (refEntity instanceof RefProject) {
- return null;
- }
- RefPackage refPackage = getPackage(refEntity);
-
- return refPackage == null ? InspectionsBundle.message("inspection.reference.default.package") : refPackage.getQualifiedName();
- }
-
- @Override
- public String getAccessModifier(PsiModifierListOwner psiElement) {
- if (psiElement instanceof PsiParameter) return PsiModifier.PACKAGE_LOCAL;
-
- PsiModifierList list = psiElement.getModifierList();
- String result = PsiModifier.PACKAGE_LOCAL;
-
- if (list != null) {
- if (list.hasModifierProperty(PsiModifier.PRIVATE)) {
- result = PsiModifier.PRIVATE;
- }
- else if (list.hasModifierProperty(PsiModifier.PROTECTED)) {
- result = PsiModifier.PROTECTED;
- }
- else if (list.hasModifierProperty(PsiModifier.PUBLIC)) {
- result = PsiModifier.PUBLIC;
- }
- else if (psiElement.getParent() instanceof PsiClass) {
- PsiClass ownerClass = (PsiClass)psiElement.getParent();
- if (ownerClass.isInterface()) {
- result = PsiModifier.PUBLIC;
- }
- }
- }
-
- return result;
- }
-
- @Override
- @Nullable public RefClass getOwnerClass(RefManager refManager, PsiElement psiElement) {
- while (psiElement != null && !(psiElement instanceof PsiClass)) {
- psiElement = psiElement.getParent();
- }
-
- return psiElement != null ? (RefClass)refManager.getReference(psiElement) : null;
- }
-
- @Override
- @Nullable public RefClass getOwnerClass(RefElement refElement) {
- RefEntity parent = refElement.getOwner();
-
- while (!(parent instanceof RefClass) && parent instanceof RefElement) {
- parent = parent.getOwner();
- }
-
- if (parent instanceof RefClass) return (RefClass)parent;
-
- return null;
- }
-
-
-
- @Override
- public boolean isMethodOnlyCallsSuper(PsiMethod method) {
- boolean hasStatements = false;
- PsiCodeBlock body = method.getBody();
- if (body != null) {
- PsiStatement[] statements = body.getStatements();
- for (PsiStatement statement : statements) {
- boolean isCallToSameSuper = false;
- if (statement instanceof PsiExpressionStatement) {
- isCallToSameSuper = isCallToSuperMethod(((PsiExpressionStatement)statement).getExpression(), method);
- }
- else if (statement instanceof PsiReturnStatement) {
- PsiExpression expression = ((PsiReturnStatement)statement).getReturnValue();
- isCallToSameSuper = expression == null || isCallToSuperMethod(expression, method);
- }
-
- hasStatements = true;
- if (isCallToSameSuper) continue;
-
- return false;
- }
- }
-
- if (hasStatements) {
- final PsiMethod[] superMethods = method.findSuperMethods();
- for (PsiMethod superMethod : superMethods) {
- if (VisibilityUtil.compare(VisibilityUtil.getVisibilityModifier(superMethod.getModifierList()),
- VisibilityUtil.getVisibilityModifier(method.getModifierList())) > 0) return false;
- }
- }
- return hasStatements;
- }
-
- @Override
- public boolean isCallToSuperMethod(PsiExpression expression, PsiMethod method) {
- if (expression instanceof PsiMethodCallExpression) {
- PsiMethodCallExpression methodCall = (PsiMethodCallExpression)expression;
- if (methodCall.getMethodExpression().getQualifierExpression() instanceof PsiSuperExpression) {
- PsiMethod superMethod = (PsiMethod)methodCall.getMethodExpression().resolve();
- if (superMethod == null || !MethodSignatureUtil.areSignaturesEqual(method, superMethod)) return false;
- PsiExpression[] args = methodCall.getArgumentList().getExpressions();
- PsiParameter[] parms = method.getParameterList().getParameters();
-
- for (int i = 0; i < args.length; i++) {
- PsiExpression arg = args[i];
- if (!(arg instanceof PsiReferenceExpression)) return false;
- if (!parms[i].equals(((PsiReferenceExpression)arg).resolve())) return false;
- }
-
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public int compareAccess(String a1, String a2) {
- int i1 = getAccessNumber(a1);
- int i2 = getAccessNumber(a2);
-
- if (i1 == i2) return 0;
- if (i1 < i2) return -1;
- return 1;
- }
-
- @SuppressWarnings("StringEquality")
- private static int getAccessNumber(String a) {
- if (a == PsiModifier.PRIVATE) {
- return 0;
- }
- else if (a == PsiModifier.PACKAGE_LOCAL) {
- return 1;
- }
- else if (a == PsiModifier.PROTECTED) {
- return 2;
- }
- else if (a == PsiModifier.PUBLIC) return 3;
-
- return -1;
- }
-
- @Override
- public void setAccessModifier(RefJavaElement refElement, String newAccess) {
- ((RefJavaElementImpl)refElement).setAccessModifier(newAccess);
- }
-
- @Override
- public void setIsStatic(RefJavaElement refElement, boolean isStatic) {
- ((RefJavaElementImpl)refElement).setIsStatic(isStatic);
- }
-
- @Override
- public void setIsFinal(RefJavaElement refElement, boolean isFinal) {
- ((RefJavaElementImpl)refElement).setIsFinal(isFinal);
- }
-
- @Override
- public void addTypeReference(PsiElement psiElement, PsiType psiType, RefManager refManager) {
- RefClass ownerClass = getOwnerClass(refManager, psiElement);
-
- if (ownerClass != null) {
- psiType = psiType.getDeepComponentType();
-
- if (psiType instanceof PsiClassType) {
- PsiClass psiClass = PsiUtil.resolveClassInType(psiType);
- if (psiClass != null && refManager.belongsToScope(psiClass)) {
- RefClassImpl refClass = (RefClassImpl)refManager.getReference(psiClass);
- if (refClass != null) {
- refClass.addTypeReference(ownerClass);
- }
- }
- }
- }
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java
deleted file mode 100644
index bca7bd179d03..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java
+++ /dev/null
@@ -1,687 +0,0 @@
-/*
- * Copyright 2000-2009 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.reference;
-
-import com.intellij.codeInsight.ExceptionUtil;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.psi.*;
-import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.*;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.SmartList;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.*;
-
-/**
- * @author max
- * Date: Oct 21, 2001
- */
-public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
- private static final List<RefMethod> EMPTY_METHOD_LIST = Collections.emptyList();
- private static final RefParameter[] EMPTY_PARAMS_ARRAY = new RefParameter[0];
-
- private static final int IS_APPMAIN_MASK = 0x10000;
- private static final int IS_LIBRARY_OVERRIDE_MASK = 0x20000;
- private static final int IS_CONSTRUCTOR_MASK = 0x40000;
- private static final int IS_ABSTRACT_MASK = 0x80000;
- private static final int IS_BODY_EMPTY_MASK = 0x100000;
- private static final int IS_ONLY_CALLS_SUPER_MASK = 0x200000;
- private static final int IS_RETURN_VALUE_USED_MASK = 0x400000;
-
- private static final int IS_TEST_METHOD_MASK = 0x4000000;
- private static final int IS_CALLED_ON_SUBCLASS = 0x8000000;
-
- private static final String RETURN_VALUE_UNDEFINED = "#";
-
- private List<RefMethod> mySuperMethods;
- private List<RefMethod> myDerivedMethods;
- private List<String> myUnThrownExceptions;
-
- private RefParameter[] myParameters;
- private String myReturnValueTemplate;
- protected final RefClass myOwnerClass;
-
- RefMethodImpl(@NotNull RefClass ownerClass, PsiMethod method, RefManager manager) {
- super(method, manager);
-
- ((RefClassImpl)ownerClass).add(this);
-
- myOwnerClass = ownerClass;
- }
-
- // To be used only from RefImplicitConstructor.
- protected RefMethodImpl(String name, @NotNull RefClass ownerClass) {
- super(name, ownerClass);
- myOwnerClass = ownerClass;
- ((RefClassImpl)ownerClass).add(this);
-
- addOutReference(getOwnerClass());
- ((RefClassImpl)getOwnerClass()).addInReference(this);
-
- setConstructor(true);
- }
-
- @Override
- protected void initialize() {
- final PsiMethod method = (PsiMethod)getElement();
- LOG.assertTrue(method != null);
- setConstructor(method.isConstructor());
- setFlag(method.getReturnType() == null || PsiType.VOID.equals(method.getReturnType()), IS_RETURN_VALUE_USED_MASK);
-
- if (!isReturnValueUsed()) {
- myReturnValueTemplate = RETURN_VALUE_UNDEFINED;
- }
-
- if (isConstructor()) {
- addReference(getOwnerClass(), getOwnerClass().getElement(), method, false, true, null);
- }
-
- if (getOwnerClass().isInterface()) {
- setAbstract(false);
- } else {
- setAbstract(method.hasModifierProperty(PsiModifier.ABSTRACT));
- }
-
-
- setAppMain(isAppMain(method, this));
- setLibraryOverride(method.hasModifierProperty(PsiModifier.NATIVE));
-
- initializeSuperMethods(method);
- if (isExternalOverride()) {
- ((RefClassImpl)getOwnerClass()).addLibraryOverrideMethod(this);
- }
-
- @NonNls final String name = method.getName();
- if (getOwnerClass().isTestCase() && name.startsWith("test")) {
- setTestMethod(true);
- }
-
- PsiParameter[] paramList = method.getParameterList().getParameters();
- if (paramList.length > 0){
- myParameters = new RefParameterImpl[paramList.length];
- for (int i = 0; i < paramList.length; i++) {
- PsiParameter parameter = paramList[i];
- myParameters[i] = getRefJavaManager().getParameterReference(parameter, i);
- }
- }
-
- if (method.hasModifierProperty(PsiModifier.NATIVE)) {
- updateReturnValueTemplate(null);
- updateThrowsList(null);
- }
- collectUncaughtExceptions(method);
- }
-
- private static boolean isAppMain(PsiMethod psiMethod, RefMethod refMethod) {
- if (!refMethod.isStatic()) return false;
- if (!PsiType.VOID.equals(psiMethod.getReturnType())) return false;
-
- PsiMethod appMainPattern = ((RefMethodImpl)refMethod).getRefJavaManager().getAppMainPattern();
- if (MethodSignatureUtil.areSignaturesEqual(psiMethod, appMainPattern)) return true;
-
- PsiMethod appPremainPattern = ((RefMethodImpl)refMethod).getRefJavaManager().getAppPremainPattern();
- return MethodSignatureUtil.areSignaturesEqual(psiMethod, appPremainPattern);
- }
-
- private void checkForSuperCall(PsiMethod method) {
- if (isConstructor()) {
- PsiCodeBlock body = method.getBody();
- if (body == null) return;
- PsiStatement[] statements = body.getStatements();
- boolean isBaseExplicitlyCalled = false;
- if (statements.length > 0) {
- PsiStatement first = statements[0];
- if (first instanceof PsiExpressionStatement) {
- PsiExpression firstExpression = ((PsiExpressionStatement) first).getExpression();
- if (firstExpression instanceof PsiMethodCallExpression) {
- PsiExpression qualifierExpression = ((PsiMethodCallExpression)firstExpression).getMethodExpression().getQualifierExpression();
- if (qualifierExpression instanceof PsiReferenceExpression) {
- @NonNls String text = qualifierExpression.getText();
- if ("super".equals(text) || text.equals("this")) {
- isBaseExplicitlyCalled = true;
- }
- }
- }
- }
- }
-
- if (!isBaseExplicitlyCalled) {
- for (RefClass superClass : getOwnerClass().getBaseClasses()) {
- RefMethodImpl superDefaultConstructor = (RefMethodImpl)superClass.getDefaultConstructor();
-
- if (superDefaultConstructor != null) {
- superDefaultConstructor.addInReference(this);
- addOutReference(superDefaultConstructor);
- }
- }
- }
- }
- }
-
- @Override
- @NotNull
- public Collection<RefMethod> getSuperMethods() {
- if (mySuperMethods == null) return EMPTY_METHOD_LIST;
- if (mySuperMethods.size() > 10) {
- LOG.info("method: " + getName() + " owner:" + getOwnerClass().getQualifiedName());
- }
- return mySuperMethods;
- }
-
- @Override
- @NotNull
- public Collection<RefMethod> getDerivedMethods() {
- if (myDerivedMethods == null) return EMPTY_METHOD_LIST;
- return myDerivedMethods;
- }
-
- @Override
- public boolean isBodyEmpty() {
- return checkFlag(IS_BODY_EMPTY_MASK);
- }
-
- @Override
- public boolean isOnlyCallsSuper() {
- return checkFlag(IS_ONLY_CALLS_SUPER_MASK);
- }
-
- @Override
- public boolean hasBody() {
- return !isAbstract() && !getOwnerClass().isInterface() || !isBodyEmpty();
- }
-
- private void initializeSuperMethods(PsiMethod method) {
- for (PsiMethod psiSuperMethod : method.findSuperMethods()) {
- if (getRefManager().belongsToScope(psiSuperMethod)) {
- RefMethodImpl refSuperMethod = (RefMethodImpl)getRefManager().getReference(psiSuperMethod);
- if (refSuperMethod != null) {
- addSuperMethod(refSuperMethod);
- refSuperMethod.markExtended(this);
- }
- }
- else {
- setLibraryOverride(true);
- }
- }
- }
-
- public void addSuperMethod(RefMethodImpl refSuperMethod) {
- if (!getSuperMethods().contains(refSuperMethod) && !refSuperMethod.getSuperMethods().contains(this)) {
- if (mySuperMethods == null){
- mySuperMethods = new ArrayList<RefMethod>(1);
- }
- mySuperMethods.add(refSuperMethod);
- }
- }
-
- public void markExtended(RefMethodImpl method) {
- if (!getDerivedMethods().contains(method) && !method.getDerivedMethods().contains(this)) {
- if (myDerivedMethods == null) {
- myDerivedMethods = new ArrayList<RefMethod>(1);
- }
- myDerivedMethods.add(method);
- }
- }
-
- @Override
- @NotNull
- public RefParameter[] getParameters() {
- if (myParameters == null) return EMPTY_PARAMS_ARRAY;
- return myParameters;
- }
-
- @Override
- public void buildReferences() {
- // Work on code block to find what we're referencing...
- PsiMethod method = (PsiMethod) getElement();
- if (method == null) return;
- PsiCodeBlock body = method.getBody();
- final RefJavaUtil refUtil = RefJavaUtil.getInstance();
- refUtil.addReferences(method, this, body);
- refUtil.addReferences(method, this, method.getModifierList());
- checkForSuperCall(method);
- setOnlyCallsSuper(refUtil.isMethodOnlyCallsSuper(method));
-
- setBodyEmpty(isOnlyCallsSuper() || !isExternalOverride() && (body == null || body.getStatements().length == 0));
-
- PsiType retType = method.getReturnType();
- if (retType != null) {
- PsiType psiType = retType;
- RefClass ownerClass = refUtil.getOwnerClass(getRefManager(), method);
-
- if (ownerClass != null) {
- psiType = psiType.getDeepComponentType();
-
- if (psiType instanceof PsiClassType) {
- PsiClass psiClass = PsiUtil.resolveClassInType(psiType);
- if (psiClass != null && getRefManager().belongsToScope(psiClass)) {
- RefClassImpl refClass = (RefClassImpl) getRefManager().getReference(psiClass);
- if (refClass != null) {
- refClass.addTypeReference(ownerClass);
- refClass.addClassExporter(this);
- }
- }
- }
- }
- }
-
- for (RefParameter parameter : getParameters()) {
- refUtil.setIsFinal(parameter, parameter.getElement().hasModifierProperty(PsiModifier.FINAL));
- }
-
- getRefManager().fireBuildReferences(this);
- }
-
- private void collectUncaughtExceptions(@NotNull PsiMethod method) {
- if (isExternalOverride()) return;
- @NonNls final String name = method.getName();
- if (getOwnerClass().isTestCase() && name.startsWith("test")) return;
-
- if (getSuperMethods().isEmpty()) {
- PsiClassType[] throwsList = method.getThrowsList().getReferencedTypes();
- if (throwsList.length > 0) {
- myUnThrownExceptions = throwsList.length == 1 ? new SmartList<String>() : new ArrayList<String>(throwsList.length);
- for (final PsiClassType type : throwsList) {
- PsiClass aClass = type.resolve();
- String fqn = aClass == null ? null : aClass.getQualifiedName();
- if (fqn != null) {
- myUnThrownExceptions.add(fqn);
- }
- }
- }
- }
-
- final PsiCodeBlock body = method.getBody();
- if (body == null) return;
-
- final Collection<PsiClassType> exceptionTypes = ExceptionUtil.collectUnhandledExceptions(body, method, false);
- for (final PsiClassType exceptionType : exceptionTypes) {
- updateThrowsList(exceptionType);
- }
- }
-
- public void removeUnThrownExceptions(PsiClass unThrownException) {
- if (myUnThrownExceptions != null) {
- myUnThrownExceptions.remove(unThrownException.getQualifiedName());
- }
- }
-
- @Override
- public void accept(@NotNull final RefVisitor visitor) {
- if (visitor instanceof RefJavaVisitor) {
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- @Override
- public void run() {
- ((RefJavaVisitor)visitor).visitMethod(RefMethodImpl.this);
- }
- });
- } else {
- super.accept(visitor);
- }
- }
-
- @Override
- public boolean isExternalOverride() {
- return isLibraryOverride(new HashSet<RefMethod>());
- }
-
- private boolean isLibraryOverride(Collection<RefMethod> processed) {
- if (processed.contains(this)) return false;
- processed.add(this);
-
- if (checkFlag(IS_LIBRARY_OVERRIDE_MASK)) return true;
- for (RefMethod superMethod : getSuperMethods()) {
- if (((RefMethodImpl)superMethod).isLibraryOverride(processed)) {
- setFlag(true, IS_LIBRARY_OVERRIDE_MASK);
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public boolean isAppMain() {
- return checkFlag(IS_APPMAIN_MASK);
- }
-
- @Override
- public boolean isAbstract() {
- return checkFlag(IS_ABSTRACT_MASK);
- }
-
- @Override
- public boolean hasSuperMethods() {
- return !getSuperMethods().isEmpty() || isExternalOverride();
- }
-
- @Override
- public boolean isReferenced() {
- // Directly called from somewhere..
- for (RefElement refCaller : getInReferences()) {
- if (!getDerivedMethods().contains(refCaller)) return true;
- }
-
- // Library override probably called from library code.
- return isExternalOverride();
- }
-
- @Override
- public boolean hasSuspiciousCallers() {
- // Directly called from somewhere..
- for (RefElement refCaller : getInReferences()) {
- if (((RefElementImpl)refCaller).isSuspicious() && !getDerivedMethods().contains(refCaller)) return true;
- }
-
- // Library override probably called from library code.
- if (isExternalOverride()) return true;
-
- // Class isn't instantiated. Most probably we have problem with class, not method.
- if (!isStatic() && !isConstructor()) {
- if (((RefClassImpl)getOwnerClass()).isSuspicious()) return true;
-
- // Is an override. Probably called via reference to base class.
- for (RefMethod refSuper : getSuperMethods()) {
- if (((RefMethodImpl)refSuper).isSuspicious()) return true;
- }
- }
-
- return false;
- }
-
- @Override
- public boolean isConstructor() {
- return checkFlag(IS_CONSTRUCTOR_MASK);
- }
-
- @Override
- public RefClass getOwnerClass() {
- return (RefClass) getOwner();
- }
-
- @NotNull
- @Override
- public String getName() {
- if (isValid()) {
- final String[] result = new String[1];
- final Runnable runnable = new Runnable() {
- @Override
- public void run() {
- PsiMethod psiMethod = (PsiMethod) getElement();
- if (psiMethod instanceof JspHolderMethod) {
- result[0] = psiMethod.getName();
- }
- else {
- result[0] = PsiFormatUtil.formatMethod(psiMethod,
- PsiSubstitutor.EMPTY,
- PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS,
- PsiFormatUtilBase.SHOW_TYPE
- );
- }
- }
- };
-
- ApplicationManager.getApplication().runReadAction(runnable);
-
- return result[0];
- } else {
- return super.getName();
- }
- }
-
- @Override
- public String getExternalName() {
- final String[] result = new String[1];
- final Runnable runnable = new Runnable() {
- @Override
- public void run() {
- final PsiMethod psiMethod = (PsiMethod)getElement();
- LOG.assertTrue(psiMethod != null);
- result[0] = PsiFormatUtil.getExternalName(psiMethod);
- }
- };
-
- ApplicationManager.getApplication().runReadAction(runnable);
-
- return result[0];
- }
-
- @Nullable
- public static RefMethod methodFromExternalName(RefManager manager, String externalName) {
- return (RefMethod) manager.getReference(findPsiMethod(PsiManager.getInstance(manager.getProject()), externalName));
- }
-
- @Nullable
- public static PsiMethod findPsiMethod(PsiManager manager, String externalName) {
- final int spaceIdx = externalName.indexOf(' ');
- final String className = externalName.substring(0, spaceIdx);
- final PsiClass psiClass = ClassUtil.findPsiClass(manager, className);
- if (psiClass == null) return null;
- try {
- PsiElementFactory factory = JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory();
- String methodSignature = externalName.substring(spaceIdx + 1);
- PsiMethod patternMethod = factory.createMethodFromText(methodSignature, psiClass);
- return psiClass.findMethodBySignature(patternMethod, false);
- } catch (IncorrectOperationException e) {
- // Do nothing. Returning null is acceptable in this case.
- return null;
- }
- }
-
- @Override
- public void referenceRemoved() {
- if (getOwnerClass() != null) {
- ((RefClassImpl)getOwnerClass()).methodRemoved(this);
- }
-
- super.referenceRemoved();
-
- for (RefMethod superMethod : getSuperMethods()) {
- superMethod.getDerivedMethods().remove(this);
- }
-
- for (RefMethod subMethod : getDerivedMethods()) {
- subMethod.getSuperMethods().remove(this);
- }
-
- ArrayList<RefElement> deletedRefs = new ArrayList<RefElement>();
- for (RefParameter parameter : getParameters()) {
- getRefManager().removeRefElement(parameter, deletedRefs);
- }
- }
-
- @Override
- public boolean isSuspicious() {
- if (isConstructor() && PsiModifier.PRIVATE.equals(getAccessModifier()) && getParameters().length == 0 && getOwnerClass().getConstructors().size() == 1) return false;
- return super.isSuspicious();
- }
-
- public void setReturnValueUsed(boolean value) {
- if (checkFlag(IS_RETURN_VALUE_USED_MASK) == value) return;
- setFlag(value, IS_RETURN_VALUE_USED_MASK);
- for (RefMethod refSuper : getSuperMethods()) {
- ((RefMethodImpl)refSuper).setReturnValueUsed(value);
- }
- }
-
- @Override
- public boolean isReturnValueUsed() {
- return checkFlag(IS_RETURN_VALUE_USED_MASK);
- }
-
- public void updateReturnValueTemplate(PsiExpression expression) {
- if (myReturnValueTemplate == null) return;
-
- if (!getSuperMethods().isEmpty()) {
- for (final RefMethod refMethod : getSuperMethods()) {
- RefMethodImpl refSuper = (RefMethodImpl)refMethod;
- refSuper.updateReturnValueTemplate(expression);
- }
- }else {
- String newTemplate = null;
- final RefJavaUtil refUtil = RefJavaUtil.getInstance();
- if (expression instanceof PsiLiteralExpression) {
- PsiLiteralExpression psiLiteralExpression = (PsiLiteralExpression) expression;
- newTemplate = psiLiteralExpression.getText();
- } else if (expression instanceof PsiReferenceExpression) {
- PsiReferenceExpression referenceExpression = (PsiReferenceExpression) expression;
- PsiElement resolved = referenceExpression.resolve();
- if (resolved instanceof PsiField) {
- PsiField psiField = (PsiField) resolved;
- if (psiField.hasModifierProperty(PsiModifier.STATIC) &&
- psiField.hasModifierProperty(PsiModifier.FINAL) &&
- refUtil.compareAccess(refUtil.getAccessModifier(psiField), getAccessModifier()) >= 0) {
- newTemplate = PsiFormatUtil.formatVariable(psiField, PsiFormatUtilBase.SHOW_NAME |
- PsiFormatUtilBase.SHOW_CONTAINING_CLASS |
- PsiFormatUtilBase.SHOW_FQ_NAME, PsiSubstitutor.EMPTY);
- }
- }
- } else if (refUtil.isCallToSuperMethod(expression, (PsiMethod) getElement())) return;
-
- //noinspection StringEquality
- if (myReturnValueTemplate == RETURN_VALUE_UNDEFINED) {
- myReturnValueTemplate = newTemplate;
- } else if (!Comparing.equal(myReturnValueTemplate, newTemplate)) {
- myReturnValueTemplate = null;
- }
- }
- }
-
- public void updateParameterValues(PsiExpression[] args) {
- if (isExternalOverride()) return;
-
- if (!getSuperMethods().isEmpty()) {
- for (RefMethod refSuper : getSuperMethods()) {
- ((RefMethodImpl)refSuper).updateParameterValues(args);
- }
- } else {
- final RefParameter[] params = getParameters();
- if (params.length <= args.length && params.length > 0) {
- for (int i = 0; i < args.length; i++) {
- RefParameter refParameter;
- if (params.length <= i){
- refParameter = params[params.length - 1];
- } else {
- refParameter = params[i];
- }
- ((RefParameterImpl)refParameter).updateTemplateValue(args[i]);
- }
- }
- }
- }
-
- @Override
- public String getReturnValueIfSame() {
- //noinspection StringEquality
- if (myReturnValueTemplate == RETURN_VALUE_UNDEFINED) return null;
- return myReturnValueTemplate;
- }
-
- public void updateThrowsList(PsiClassType exceptionType) {
- if (!getSuperMethods().isEmpty()) {
- for (RefMethod refSuper : getSuperMethods()) {
- ((RefMethodImpl)refSuper).updateThrowsList(exceptionType);
- }
- }
- else if (myUnThrownExceptions != null) {
- if (exceptionType == null) {
- myUnThrownExceptions = null;
- return;
- }
- PsiClass exceptionClass = exceptionType.resolve();
- JavaPsiFacade facade = JavaPsiFacade.getInstance(myManager.getProject());
- for (int i = myUnThrownExceptions.size() - 1; i >= 0; i--) {
- String exceptionFqn = myUnThrownExceptions.get(i);
- PsiClass classType = facade.findClass(exceptionFqn, GlobalSearchScope.allScope(getRefManager().getProject()));
- if (InheritanceUtil.isInheritorOrSelf(exceptionClass, classType, true) ||
- InheritanceUtil.isInheritorOrSelf(classType, exceptionClass, true)) {
- myUnThrownExceptions.remove(i);
- }
- }
-
- if (myUnThrownExceptions.isEmpty()) myUnThrownExceptions = null;
- }
- }
-
- @Override
- @Nullable
- public PsiClass[] getUnThrownExceptions() {
- if (myUnThrownExceptions == null) return null;
- JavaPsiFacade facade = JavaPsiFacade.getInstance(myManager.getProject());
- List<PsiClass> result = new ArrayList<PsiClass>(myUnThrownExceptions.size());
- for (String exception : myUnThrownExceptions) {
- PsiClass element = facade.findClass(exception, GlobalSearchScope.allScope(myManager.getProject()));
- if (element != null) result.add(element);
- }
- return result.toArray(new PsiClass[result.size()]);
- }
-
-
- public void setLibraryOverride(boolean libraryOverride) {
- setFlag(libraryOverride, IS_LIBRARY_OVERRIDE_MASK);
- }
-
- private void setAppMain(boolean appMain) {
- setFlag(appMain, IS_APPMAIN_MASK);
- }
-
- private void setAbstract(boolean anAbstract) {
- setFlag(anAbstract, IS_ABSTRACT_MASK);
- }
-
- public void setBodyEmpty(boolean bodyEmpty) {
- setFlag(bodyEmpty, IS_BODY_EMPTY_MASK);
- }
-
- private void setOnlyCallsSuper(boolean onlyCallsSuper) {
- setFlag(onlyCallsSuper, IS_ONLY_CALLS_SUPER_MASK);
- }
-
-
-
- private void setConstructor(boolean constructor) {
- setFlag(constructor, IS_CONSTRUCTOR_MASK);
- }
-
- @Override
- public boolean isTestMethod() {
- return checkFlag(IS_TEST_METHOD_MASK);
- }
-
- private void setTestMethod(boolean testMethod){
- setFlag(testMethod, IS_TEST_METHOD_MASK);
- }
-
- @Override
- public PsiModifierListOwner getElement() {
- return (PsiModifierListOwner)super.getElement();
- }
-
- @Override
- public boolean isCalledOnSubClass() {
- return checkFlag(IS_CALLED_ON_SUBCLASS);
- }
-
- public void setCalledOnSubClass(boolean isCalledOnSubClass){
- setFlag(isCalledOnSubClass, IS_CALLED_ON_SUBCLASS);
- }
-
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefPackageImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefPackageImpl.java
deleted file mode 100644
index 32649b924a25..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefPackageImpl.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Nov 15, 2001
- * Time: 5:17:38 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.util.PlatformIcons;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-
-
-public class RefPackageImpl extends RefEntityImpl implements RefPackage {
- private final String myQualifiedName;
-
- public RefPackageImpl(@NotNull String name, @NotNull RefManager refManager) {
- super(getPackageSuffix(name), refManager);
- myQualifiedName = name;
- }
-
- @NotNull
- @Override
- public String getQualifiedName() {
- return myQualifiedName;
- }
-
- private static String getPackageSuffix(@NotNull String fullName) {
- int dotIndex = fullName.lastIndexOf('.');
- return (dotIndex >= 0) ? fullName.substring(dotIndex + 1) : fullName;
- }
-
-
- @Override
- public void accept(@NotNull final RefVisitor visitor) {
- if (visitor instanceof RefJavaVisitor) {
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- @Override
- public void run() {
- ((RefJavaVisitor)visitor).visitPackage(RefPackageImpl.this);
- }
- });
- } else {
- super.accept(visitor);
- }
- }
-
- @Override
- public String getExternalName() {
- return getQualifiedName();
- }
-
- public static RefEntity packageFromFQName(final RefManager manager, final String name) {
- return manager.getExtension(RefJavaManager.MANAGER).getPackage(name);
- }
-
- @Override
- public boolean isValid() {
- return true;
- }
-
- @Override
- public Icon getIcon(final boolean expanded) {
- return PlatformIcons.PACKAGE_ICON;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefParameterImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefParameterImpl.java
deleted file mode 100644
index f33145fa070e..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefParameterImpl.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Oct 21, 2001
- * Time: 4:35:07 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.reference;
-
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiFormatUtil;
-import com.intellij.psi.util.PsiTreeUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public class RefParameterImpl extends RefJavaElementImpl implements RefParameter {
- private static final int USED_FOR_READING_MASK = 0x10000;
- private static final int USED_FOR_WRITING_MASK = 0x20000;
- private static final String VALUE_UNDEFINED = "#";
-
- private final short myIndex;
- private String myActualValueTemplate;
-
- RefParameterImpl(PsiParameter parameter, int index, RefManager manager) {
- super(parameter, manager);
-
- myIndex = (short)index;
- myActualValueTemplate = VALUE_UNDEFINED;
- final RefElementImpl owner = (RefElementImpl)manager.getReference(PsiTreeUtil.getParentOfType(parameter, PsiMethod.class));
- if (owner != null) {
- owner.add(this);
- }
- }
-
- @Override
- public void parameterReferenced(boolean forWriting) {
- if (forWriting) {
- setUsedForWriting();
- } else {
- setUsedForReading();
- }
- }
-
- @Override
- public boolean isUsedForReading() {
- return checkFlag(USED_FOR_READING_MASK);
- }
-
- private void setUsedForReading() {
- setFlag(true, USED_FOR_READING_MASK);
- }
-
- @Override
- public PsiParameter getElement() {
- return (PsiParameter)super.getElement();
- }
-
- @Override
- public boolean isUsedForWriting() {
- return checkFlag(USED_FOR_WRITING_MASK);
- }
-
- private void setUsedForWriting() {
- setFlag(true, USED_FOR_WRITING_MASK);
- }
-
- @Override
- public void accept(@NotNull final RefVisitor visitor) {
- if (visitor instanceof RefJavaVisitor) {
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- @Override
- public void run() {
- ((RefJavaVisitor)visitor).visitParameter(RefParameterImpl.this);
- }
- });
- } else {
- super.accept(visitor);
- }
- }
-
- @Override
- public int getIndex() {
- return myIndex;
- }
-
- public void updateTemplateValue(PsiExpression expression) {
- if (myActualValueTemplate == null) return;
-
- String newTemplate = null;
- if (expression instanceof PsiLiteralExpression) {
- PsiLiteralExpression psiLiteralExpression = (PsiLiteralExpression) expression;
- newTemplate = psiLiteralExpression.getText();
- } else if (expression instanceof PsiReferenceExpression) {
- PsiReferenceExpression referenceExpression = (PsiReferenceExpression) expression;
- PsiElement resolved = referenceExpression.resolve();
- if (resolved instanceof PsiField) {
- PsiField psiField = (PsiField) resolved;
- if (psiField.hasModifierProperty(PsiModifier.STATIC) &&
- psiField.hasModifierProperty(PsiModifier.FINAL) &&
- psiField.getContainingClass().getQualifiedName() != null) {
- newTemplate = PsiFormatUtil.formatVariable(psiField, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_CONTAINING_CLASS | PsiFormatUtil.SHOW_FQ_NAME, PsiSubstitutor.EMPTY);
- }
- }
- }
-
- if (myActualValueTemplate == VALUE_UNDEFINED) {
- myActualValueTemplate = newTemplate;
- } else if (!Comparing.equal(myActualValueTemplate, newTemplate)) {
- myActualValueTemplate = null;
- }
- }
-
- @Override
- public String getActualValueIfSame() {
- if (myActualValueTemplate == VALUE_UNDEFINED) return null;
- return myActualValueTemplate;
- }
-
- @Override
- protected void initialize() {
- }
-
- @Override
- public String getExternalName() {
- final String[] result = new String[1];
- final Runnable runnable = new Runnable() {
- @Override
- public void run() {
- PsiParameter parameter = getElement();
- LOG.assertTrue(parameter != null);
- result[0] = PsiFormatUtil.getExternalName(parameter);
- }
- };
-
- ApplicationManager.getApplication().runReadAction(runnable);
-
- return result[0];
- }
-
- @Nullable
- public static RefElement parameterFromExternalName(final RefManager manager, final String fqName) {
- final int idx = fqName.lastIndexOf(' ');
- if (idx > 0) {
- final String paramName = fqName.substring(idx + 1);
- final String method = fqName.substring(0, idx);
- final RefMethod refMethod = RefMethodImpl.methodFromExternalName(manager, method);
- if (refMethod != null) {
- final PsiMethod element = (PsiMethod)refMethod.getElement();
- final PsiParameterList list = element.getParameterList();
- final PsiParameter[] parameters = list.getParameters();
- int paramIdx = 0;
- for (PsiParameter parameter : parameters) {
- final String name = parameter.getName();
- if (name != null && name.equals(paramName)) {
- return manager.getExtension(RefJavaManager.MANAGER).getParameterReference(parameter, paramIdx);
- }
- paramIdx++;
- }
- }
- }
- return null;
- }
-
- @Nullable
- public static PsiParameter findPsiParameter(String fqName, final PsiManager manager) {
- final int idx = fqName.lastIndexOf(' ');
- if (idx > 0) {
- final String paramName = fqName.substring(idx + 1);
- final String method = fqName.substring(0, idx);
- final PsiMethod psiMethod = RefMethodImpl.findPsiMethod(manager, method);
- if (psiMethod != null) {
- final PsiParameterList list = psiMethod.getParameterList();
- final PsiParameter[] parameters = list.getParameters();
- for (PsiParameter parameter : parameters) {
- final String name = parameter.getName();
- if (name != null && name.equals(paramName)) {
- return parameter;
- }
- }
- }
- }
- return null;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java b/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
index 0f756686403c..12e26f8bd673 100644
--- a/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
@@ -41,7 +41,7 @@ import java.util.List;
/**
* @author max
*/
-public class SameParameterValueInspection extends GlobalJavaInspectionTool {
+public class SameParameterValueInspection extends GlobalJavaBatchInspectionTool {
private static final Logger LOG = Logger.getInstance("#" + SameParameterValueInspection.class.getName());
@Override
diff --git a/java/java-impl/src/com/intellij/codeInspection/sameReturnValue/SameReturnValueInspection.java b/java/java-impl/src/com/intellij/codeInspection/sameReturnValue/SameReturnValueInspection.java
deleted file mode 100644
index 7d4c3536b139..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/sameReturnValue/SameReturnValueInspection.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2000-2009 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.sameReturnValue;
-
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.psi.PsiMethod;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author max
- */
-public class SameReturnValueInspection extends GlobalJavaInspectionTool {
- @Override
- @Nullable
- public CommonProblemDescriptor[] checkElement(@NotNull RefEntity refEntity, @NotNull AnalysisScope scope, @NotNull InspectionManager manager, @NotNull GlobalInspectionContext globalContext,
- @NotNull ProblemDescriptionsProcessor processor) {
- if (refEntity instanceof RefMethod) {
- final RefMethod refMethod = (RefMethod)refEntity;
-
- if (refMethod.isConstructor()) return null;
- if (refMethod.hasSuperMethods()) return null;
-
- String returnValue = refMethod.getReturnValueIfSame();
- if (returnValue != null) {
- final String message;
- if (refMethod.getDerivedMethods().isEmpty()) {
- message = InspectionsBundle.message("inspection.same.return.value.problem.descriptor", "<code>" + returnValue + "</code>");
- } else if (refMethod.hasBody()) {
- message = InspectionsBundle.message("inspection.same.return.value.problem.descriptor1", "<code>" + returnValue + "</code>");
- } else {
- message = InspectionsBundle.message("inspection.same.return.value.problem.descriptor2", "<code>" + returnValue + "</code>");
- }
-
- return new ProblemDescriptor[] {manager.createProblemDescriptor(refMethod.getElement().getNavigationElement(), message, false, null, ProblemHighlightType.GENERIC_ERROR_OR_WARNING)};
- }
- }
-
- return null;
- }
-
-
- @Override
- protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager, @NotNull final GlobalJavaInspectionContext globalContext,
- @NotNull final ProblemDescriptionsProcessor processor) {
- manager.iterate(new RefJavaVisitor() {
- @Override public void visitElement(@NotNull RefEntity refEntity) {
- if (refEntity instanceof RefElement && processor.getDescriptions(refEntity) != null) {
- refEntity.accept(new RefJavaVisitor() {
- @Override public void visitMethod(@NotNull final RefMethod refMethod) {
- globalContext.enqueueDerivedMethodsProcessor(refMethod, new GlobalJavaInspectionContext.DerivedMethodsProcessor() {
- @Override
- public boolean process(PsiMethod derivedMethod) {
- processor.ignoreElement(refMethod);
- return false;
- }
- });
- }
- });
- }
- }
- });
-
- return false;
- }
-
- @Override
- @NotNull
- public String getDisplayName() {
- return InspectionsBundle.message("inspection.same.return.value.display.name");
- }
-
- @Override
- @NotNull
- public String getGroupDisplayName() {
- return GroupNames.DECLARATION_REDUNDANCY;
- }
-
- @Override
- @NotNull
- public String getShortName() {
- return "SameReturnValue";
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java b/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java
index 7363d43c104b..b02ce22527bf 100644
--- a/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java
+++ b/java/java-impl/src/com/intellij/codeInspection/ui/EntryPointsNode.java
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInspection.ui;
-import com.intellij.codeInspection.deadCode.DummyEntryPointsTool;
+import com.intellij.codeInspection.deadCode.DummyEntryPointsEP;
import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
import com.intellij.codeInspection.ex.GlobalInspectionToolWrapper;
import com.intellij.codeInspection.ex.InspectionToolWrapper;
@@ -33,7 +33,7 @@ public class EntryPointsNode extends InspectionNode {
}
private static InspectionToolWrapper createDummyWrapper(@NotNull GlobalInspectionContextImpl context) {
- InspectionToolWrapper toolWrapper = new GlobalInspectionToolWrapper(new DummyEntryPointsTool());
+ InspectionToolWrapper toolWrapper = new GlobalInspectionToolWrapper(new DummyEntryPointsEP());
toolWrapper.initialize(context);
return toolWrapper;
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java
index 24cc9d181fd2..b740fcf9e7f6 100644
--- a/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspection.java
@@ -24,14 +24,12 @@ import com.intellij.codeInsight.daemon.impl.quickfix.VariableArrayTypeFix;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.codeInsight.quickfix.ChangeVariableTypeQuickFixProvider;
-import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
-import com.intellij.codeInspection.InspectionsBundle;
-import com.intellij.codeInspection.LocalQuickFix;
-import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.codeInspection.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.Pass;
import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.util.*;
import org.intellij.lang.annotations.Pattern;
@@ -168,8 +166,13 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool
@NotNull
@Override
- public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
- return new UncheckedWarningsVisitor(isOnTheFly){
+ public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder,
+ boolean isOnTheFly,
+ @NotNull LocalInspectionToolSession session) {
+ LanguageLevel languageLevel = PsiUtil.getLanguageLevel(session.getFile());
+ if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_5)) return super.buildVisitor(holder, isOnTheFly, session);
+
+ return new UncheckedWarningsVisitor(isOnTheFly, languageLevel){
@Override
protected void registerProblem(@NotNull String message, @NotNull PsiElement psiElement, @NotNull LocalQuickFix[] quickFixes) {
holder.registerProblem(psiElement, message, quickFixes);
@@ -179,10 +182,12 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool
private abstract class UncheckedWarningsVisitor extends JavaElementVisitor {
private final boolean myOnTheFly;
+ @NotNull private final LanguageLevel myLanguageLevel;
private final LocalQuickFix[] myGenerifyFixes;
- public UncheckedWarningsVisitor(boolean onTheFly) {
+ public UncheckedWarningsVisitor(boolean onTheFly, @NotNull LanguageLevel level) {
myOnTheFly = onTheFly;
+ myLanguageLevel = level;
myGenerifyFixes = onTheFly ? new LocalQuickFix[]{new GenerifyFileFix()} : LocalQuickFix.EMPTY_ARRAY;
}
@@ -192,9 +197,8 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
if (IGNORE_UNCHECKED_GENERICS_ARRAY_CREATION) return;
- if (!PsiUtil.isLanguageLevel5OrHigher(expression)) return;
final JavaResolveResult result = expression.advancedResolve(false);
- if (JavaGenericsUtil.isUncheckedWarning(expression, result)) {
+ if (JavaGenericsUtil.isUncheckedWarning(expression, result, myLanguageLevel)) {
registerProblem("Unchecked generics array creation for varargs parameter", expression, LocalQuickFix.EMPTY_ARRAY);
}
}
@@ -203,9 +207,8 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool
public void visitNewExpression(PsiNewExpression expression) {
super.visitNewExpression(expression);
if (IGNORE_UNCHECKED_GENERICS_ARRAY_CREATION) return;
- if (!PsiUtil.isLanguageLevel5OrHigher(expression)) return;
final PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
- if (JavaGenericsUtil.isUncheckedWarning(classReference, expression.resolveMethodGenerics())) {
+ if (classReference != null && JavaGenericsUtil.isUncheckedWarning(classReference, expression.resolveMethodGenerics(), myLanguageLevel)) {
registerProblem("Unchecked generics array creation for varargs parameter", classReference, LocalQuickFix.EMPTY_ARRAY);
}
}
@@ -214,7 +217,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool
public void visitTypeCastExpression(PsiTypeCastExpression expression) {
super.visitTypeCastExpression(expression);
if (IGNORE_UNCHECKED_CAST) return;
- if (!PsiUtil.isLanguageLevel5OrHigher(expression)) return;
final PsiTypeElement typeElement = expression.getCastType();
if (typeElement == null) return;
final PsiType castType = typeElement.getType();
@@ -234,7 +236,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool
@Override
public void visitCallExpression(PsiCallExpression callExpression) {
super.visitCallExpression(callExpression);
- if (!PsiUtil.isLanguageLevel5OrHigher(callExpression)) return;
final JavaResolveResult result = callExpression.resolveMethodGenerics();
final String description = getUncheckedCallDescription(result);
if (description != null) {
@@ -273,7 +274,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool
public void visitVariable(PsiVariable variable) {
super.visitVariable(variable);
if (IGNORE_UNCHECKED_ASSIGNMENT) return;
- if (!PsiUtil.isLanguageLevel5OrHigher(variable)) return;
PsiExpression initializer = variable.getInitializer();
if (initializer == null || initializer instanceof PsiArrayInitializerExpression) return;
final PsiType initializerType = initializer.getType();
@@ -285,13 +285,11 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool
public void visitForeachStatement(PsiForeachStatement statement) {
super.visitForeachStatement(statement);
if (IGNORE_UNCHECKED_ASSIGNMENT) return;
- if (!PsiUtil.isLanguageLevel5OrHigher(statement)) return;
final PsiParameter parameter = statement.getIterationParameter();
final PsiType parameterType = parameter.getType();
final PsiExpression iteratedValue = statement.getIteratedValue();
if (iteratedValue == null) return;
final PsiType itemType = JavaGenericsUtil.getCollectionItemType(iteratedValue);
- if (!PsiUtil.isLanguageLevel5OrHigher(statement)) return;
checkRawToGenericsAssignment(parameter, parameterType, itemType, true, myOnTheFly ? getChangeVariableTypeFixes(parameter, itemType) : LocalQuickFix.EMPTY_ARRAY);
}
@@ -299,7 +297,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool
public void visitAssignmentExpression(PsiAssignmentExpression expression) {
super.visitAssignmentExpression(expression);
if (IGNORE_UNCHECKED_ASSIGNMENT) return;
- if (!PsiUtil.isLanguageLevel5OrHigher(expression)) return;
if (!"=".equals(expression.getOperationSign().getText())) return;
PsiExpression lExpr = expression.getLExpression();
PsiExpression rExpr = expression.getRExpression();
@@ -321,7 +318,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool
public void visitArrayInitializerExpression(PsiArrayInitializerExpression arrayInitializer) {
super.visitArrayInitializerExpression(arrayInitializer);
if (IGNORE_UNCHECKED_ASSIGNMENT) return;
- if (!PsiUtil.isLanguageLevel5OrHigher(arrayInitializer)) return;
final PsiType type = arrayInitializer.getType();
if (!(type instanceof PsiArrayType)) return;
final PsiType componentType = ((PsiArrayType)type).getComponentType();
@@ -372,7 +368,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool
public void visitMethod(PsiMethod method) {
super.visitMethod(method);
if (IGNORE_UNCHECKED_OVERRIDING) return;
- if (!PsiUtil.isLanguageLevel5OrHigher(method)) return;
if (!method.isConstructor()) {
List<HierarchicalMethodSignature> superMethodSignatures = method.getHierarchicalMethodSignature().getSuperSignatures();
if (!superMethodSignatures.isEmpty() && !method.hasModifierProperty(PsiModifier.STATIC)) {
@@ -403,7 +398,6 @@ public class UncheckedWarningLocalInspection extends BaseJavaLocalInspectionTool
public void visitReturnStatement(PsiReturnStatement statement) {
super.visitReturnStatement(statement);
if (IGNORE_UNCHECKED_ASSIGNMENT) return;
- if (!PsiUtil.isLanguageLevel5OrHigher(statement)) return;
final PsiMethod method = PsiTreeUtil.getParentOfType(statement, PsiMethod.class);
if (method != null) {
final PsiType returnType = method.getReturnType();
diff --git a/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyAnnotator.java b/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyAnnotator.java
deleted file mode 100644
index 0ee3c679beb5..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyAnnotator.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.intellij.codeInspection.unnecessaryModuleDependency;
-
-import com.intellij.codeInspection.reference.RefElement;
-import com.intellij.codeInspection.reference.RefGraphAnnotator;
-import com.intellij.codeInspection.reference.RefManager;
-import com.intellij.codeInspection.reference.RefModule;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
-import com.intellij.openapi.util.Key;
-import com.intellij.psi.PsiElement;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * User: anna
- * Date: 09-Jan-2006
- */
-public class UnnecessaryModuleDependencyAnnotator extends RefGraphAnnotator {
- public static final Key<Set<Module>> DEPENDENCIES = Key.create("inspection.dependencies");
-
- private final RefManager myManager;
-
- public UnnecessaryModuleDependencyAnnotator(final RefManager manager) {
- myManager = manager;
- }
-
-
-
- @Override
- public void onMarkReferenced(RefElement refWhat, RefElement refFrom, boolean referencedFromClassInitializer) {
- final PsiElement onElement = refWhat.getElement();
- final PsiElement fromElement = refFrom.getElement();
- if (onElement != null && fromElement!= null){
- final Module onModule = ModuleUtil.findModuleForPsiElement(onElement);
- final Module fromModule = ModuleUtil.findModuleForPsiElement(fromElement);
- if (onModule != null && fromModule != null && onModule != fromModule){
- final RefModule refModule = myManager.getRefModule(fromModule);
- if (refModule != null) {
- Set<Module> modules = refModule.getUserData(DEPENDENCIES);
- if (modules == null){
- modules = new HashSet<Module>();
- refModule.putUserData(DEPENDENCIES, modules);
- }
- modules.add(onModule);
- }
- }
- }
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyInspection.java b/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyInspection.java
deleted file mode 100644
index 87e99c553b36..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/unnecessaryModuleDependency/UnnecessaryModuleDependencyInspection.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package com.intellij.codeInspection.unnecessaryModuleDependency;
-
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.reference.RefEntity;
-import com.intellij.codeInspection.reference.RefGraphAnnotator;
-import com.intellij.codeInspection.reference.RefManager;
-import com.intellij.codeInspection.reference.RefModule;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ModifiableRootModel;
-import com.intellij.openapi.roots.ModuleOrderEntry;
-import com.intellij.openapi.roots.ModuleRootManager;
-import com.intellij.openapi.roots.OrderEntry;
-import com.intellij.openapi.util.Comparing;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * User: anna
- * Date: 09-Jan-2006
- */
-public class UnnecessaryModuleDependencyInspection extends GlobalInspectionTool {
-
- @Override
- public RefGraphAnnotator getAnnotator(@NotNull final RefManager refManager) {
- return new UnnecessaryModuleDependencyAnnotator(refManager);
- }
-
- @Override
- public CommonProblemDescriptor[] checkElement(@NotNull RefEntity refEntity, @NotNull AnalysisScope scope, @NotNull InspectionManager manager, @NotNull final GlobalInspectionContext globalContext) {
- if (refEntity instanceof RefModule){
- final RefModule refModule = (RefModule)refEntity;
- final Module module = refModule.getModule();
- final Module[] declaredDependencies = ModuleRootManager.getInstance(module).getDependencies();
- List<CommonProblemDescriptor> descriptors = new ArrayList<CommonProblemDescriptor>();
- final Set<Module> modules = refModule.getUserData(UnnecessaryModuleDependencyAnnotator.DEPENDENCIES);
- for (final Module dependency : declaredDependencies) {
- if (modules == null || !modules.contains(dependency)) {
- final CommonProblemDescriptor problemDescriptor;
- if (scope.containsModule(dependency)) { //external references are rejected -> annotator doesn't provide any information on them -> false positives
- problemDescriptor = manager.createProblemDescriptor(
- InspectionsBundle.message("unnecessary.module.dependency.problem.descriptor", module.getName(), dependency.getName()),
- new RemoveModuleDependencyFix(module, dependency));
- } else {
- String message = InspectionsBundle
- .message("suspected.module.dependency.problem.descriptor", module.getName(), dependency.getName(), scope.getDisplayName(),
- dependency.getName());
- problemDescriptor = manager.createProblemDescriptor(message);
- }
- descriptors.add(problemDescriptor);
- }
- }
- return descriptors.isEmpty() ? null : descriptors.toArray(new CommonProblemDescriptor[descriptors.size()]);
- }
- 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() {
- return "UnnecessaryModuleDependencyInspection";
- }
-
- public static class RemoveModuleDependencyFix implements QuickFix {
- private final Module myModule;
- private final Module myDependency;
-
- public RemoveModuleDependencyFix(Module module, Module dependency) {
- myModule = module;
- 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()) {
- if (entry instanceof ModuleOrderEntry) {
- final Module mDependency = ((ModuleOrderEntry)entry).getModule();
- if (Comparing.equal(mDependency, myDependency)) {
- model.removeOrderEntry(entry);
- break;
- }
- }
- }
- model.commit();
- }
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java b/java/java-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java
deleted file mode 100644
index 8810af9e6bea..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Copyright 2000-2009 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.unneededThrows;
-
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.ExceptionUtil;
-import com.intellij.codeInsight.FileModificationService;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Pair;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.searches.AllOverridingMethodsSearch;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.Processor;
-import com.intellij.util.Query;
-import com.intellij.util.containers.BidirectionalMap;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author max
- */
-public class RedundantThrows extends GlobalJavaInspectionTool {
- private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.unneededThrows.RedundantThrows");
- private static final String DISPLAY_NAME = InspectionsBundle.message("inspection.redundant.throws.display.name");
- private final BidirectionalMap<String, QuickFix> myQuickFixes = new BidirectionalMap<String, QuickFix>();
- @NonNls private static final String SHORT_NAME = "RedundantThrows";
-
- @Override
- @Nullable
- public CommonProblemDescriptor[] checkElement(@NotNull RefEntity refEntity,
- @NotNull AnalysisScope scope,
- @NotNull InspectionManager manager,
- @NotNull GlobalInspectionContext globalContext,
- @NotNull ProblemDescriptionsProcessor processor) {
- if (refEntity instanceof RefMethod) {
- final RefMethod refMethod = (RefMethod)refEntity;
- if (refMethod.isSyntheticJSP()) return null;
-
- if (refMethod.hasSuperMethods()) return null;
-
- if (refMethod.isEntry()) return null;
-
- PsiClass[] unThrown = refMethod.getUnThrownExceptions();
- if (unThrown == null) return null;
-
- PsiMethod psiMethod = (PsiMethod)refMethod.getElement();
- PsiClassType[] throwsList = psiMethod.getThrowsList().getReferencedTypes();
- PsiJavaCodeReferenceElement[] throwsRefs = psiMethod.getThrowsList().getReferenceElements();
- List<ProblemDescriptor> problems = null;
-
- final PsiManager psiManager = psiMethod.getManager();
- for (int i = 0; i < throwsList.length; i++) {
- final PsiClassType throwsType = throwsList[i];
- final String throwsClassName = throwsType.getClassName();
- final PsiJavaCodeReferenceElement throwsRef = throwsRefs[i];
- if (ExceptionUtil.isUncheckedException(throwsType)) continue;
- if (declaredInRemotableMethod(psiMethod, throwsType)) continue;
-
- for (PsiClass s : unThrown) {
- final PsiClass throwsResolvedType = throwsType.resolve();
- if (psiManager.areElementsEquivalent(s, throwsResolvedType)) {
- if (problems == null) problems = new ArrayList<ProblemDescriptor>(1);
-
- if (refMethod.isAbstract() || refMethod.getOwnerClass().isInterface()) {
- problems.add(manager.createProblemDescriptor(throwsRef, InspectionsBundle.message(
- "inspection.redundant.throws.problem.descriptor", "<code>#ref</code>"), getFix(processor, throwsClassName), ProblemHighlightType.LIKE_UNUSED_SYMBOL,
- false));
- }
- else if (!refMethod.getDerivedMethods().isEmpty()) {
- problems.add(manager.createProblemDescriptor(throwsRef, InspectionsBundle.message(
- "inspection.redundant.throws.problem.descriptor1", "<code>#ref</code>"), getFix(processor, throwsClassName), ProblemHighlightType.LIKE_UNUSED_SYMBOL,
- false));
- }
- else {
- problems.add(manager.createProblemDescriptor(throwsRef, InspectionsBundle.message(
- "inspection.redundant.throws.problem.descriptor2", "<code>#ref</code>"), getFix(processor, throwsClassName), ProblemHighlightType.LIKE_UNUSED_SYMBOL,
- false));
- }
- }
- }
- }
-
- if (problems != null) {
- return problems.toArray(new CommonProblemDescriptor[problems.size()]);
- }
- }
-
- return null;
- }
-
- private static boolean declaredInRemotableMethod(final PsiMethod psiMethod, final PsiClassType throwsType) {
- if (!throwsType.equalsToText("java.rmi.RemoteException")) return false;
- PsiClass aClass = psiMethod.getContainingClass();
- if (aClass == null) return false;
- PsiClass remote =
- JavaPsiFacade.getInstance(aClass.getProject()).findClass("java.rmi.Remote", GlobalSearchScope.allScope(aClass.getProject()));
- return remote != null && aClass.isInheritor(remote, true);
- }
-
-
- @Override
- protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager, @NotNull final GlobalJavaInspectionContext globalContext,
- @NotNull final ProblemDescriptionsProcessor processor) {
- manager.iterate(new RefJavaVisitor() {
- @Override public void visitElement(@NotNull RefEntity refEntity) {
- if (processor.getDescriptions(refEntity) != null) {
- refEntity.accept(new RefJavaVisitor() {
- @Override public void visitMethod(@NotNull final RefMethod refMethod) {
- globalContext.enqueueDerivedMethodsProcessor(refMethod, new GlobalJavaInspectionContext.DerivedMethodsProcessor() {
- @Override
- public boolean process(PsiMethod derivedMethod) {
- processor.ignoreElement(refMethod);
- return true;
- }
- });
- }
- });
- }
- }
- });
-
- return false;
- }
-
- @Override
- @NotNull
- public String getDisplayName() {
- return DISPLAY_NAME;
- }
-
- @Override
- @NotNull
- public String getGroupDisplayName() {
- return GroupNames.DECLARATION_REDUNDANCY;
- }
-
- @Override
- @NotNull
- public String getShortName() {
- return SHORT_NAME;
- }
-
- private LocalQuickFix getFix(final ProblemDescriptionsProcessor processor, final String hint) {
- QuickFix fix = myQuickFixes.get(hint);
- if (fix == null) {
- fix = new MyQuickFix(processor, hint);
- if (hint != null) {
- myQuickFixes.put(hint, fix);
- }
- }
- return (LocalQuickFix)fix;
- }
-
-
- @Override
- @Nullable
- public QuickFix getQuickFix(String hint) {
- return getFix(null, hint);
- }
-
- @Override
- @Nullable
- public String getHint(@NotNull final QuickFix fix) {
- final List<String> hints = myQuickFixes.getKeysByValue(fix);
- LOG.assertTrue(hints != null && hints.size() == 1);
- return hints.get(0);
- }
-
- private static class MyQuickFix implements LocalQuickFix {
- private final ProblemDescriptionsProcessor myProcessor;
- private final String myHint;
-
- public MyQuickFix(final ProblemDescriptionsProcessor processor, final String hint) {
- myProcessor = processor;
- myHint = hint;
- }
-
- @Override
- @NotNull
- public String getName() {
- return InspectionsBundle.message("inspection.redundant.throws.remove.quickfix");
- }
-
- @Override
- public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
- if (myProcessor != null) {
- RefElement refElement = (RefElement)myProcessor.getElement(descriptor);
- if (refElement instanceof RefMethod && refElement.isValid()) {
- RefMethod refMethod = (RefMethod)refElement;
- final CommonProblemDescriptor[] problems = myProcessor.getDescriptions(refMethod);
- if (problems != null) {
- removeExcessiveThrows(refMethod, null, problems);
- }
- }
- }
- else {
- final PsiMethod psiMethod = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiMethod.class);
- if (psiMethod != null) {
- removeExcessiveThrows(null, psiMethod, new CommonProblemDescriptor[]{descriptor});
- }
- }
- }
-
- @Override
- @NotNull
- public String getFamilyName() {
- return getName();
- }
-
- private void removeExcessiveThrows(@Nullable RefMethod refMethod, @Nullable final PsiModifierListOwner element, final CommonProblemDescriptor[] problems) {
- try {
- @Nullable final PsiMethod psiMethod;
- if (element == null) {
- LOG.assertTrue(refMethod != null);
- psiMethod = (PsiMethod)refMethod.getElement();
- }
- else {
- psiMethod = (PsiMethod)element;
- }
- if (psiMethod == null) return; //invalid refMethod
- final Project project = psiMethod.getProject();
- final PsiManager psiManager = PsiManager.getInstance(project);
- final List<PsiJavaCodeReferenceElement> refsToDelete = new ArrayList<PsiJavaCodeReferenceElement>();
- for (CommonProblemDescriptor problem : problems) {
- final PsiElement psiElement = ((ProblemDescriptor)problem).getPsiElement();
- if (psiElement instanceof PsiJavaCodeReferenceElement) {
- final PsiJavaCodeReferenceElement classRef = (PsiJavaCodeReferenceElement)psiElement;
- final PsiType psiType = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory().createType(classRef);
- removeException(refMethod, psiType, refsToDelete, psiMethod);
- } else {
- final PsiReferenceList throwsList = psiMethod.getThrowsList();
- final PsiClassType[] classTypes = throwsList.getReferencedTypes();
- for (PsiClassType classType : classTypes) {
- final String text = classType.getClassName();
- if (Comparing.strEqual(myHint, text)) {
- removeException(refMethod, classType, refsToDelete, psiMethod);
- break;
- }
- }
- }
- }
-
- //check read-only status for derived methods
- if (!FileModificationService.getInstance().preparePsiElementsForWrite(refsToDelete)) return;
-
- for (final PsiJavaCodeReferenceElement aRefsToDelete : refsToDelete) {
- aRefsToDelete.delete();
- }
- }
- catch (IncorrectOperationException e) {
- LOG.error(e);
- }
- }
-
- private static void removeException(final RefMethod refMethod,
- final PsiType exceptionType,
- final List<PsiJavaCodeReferenceElement> refsToDelete,
- final PsiMethod psiMethod) {
- PsiManager psiManager = psiMethod.getManager();
-
- PsiJavaCodeReferenceElement[] refs = psiMethod.getThrowsList().getReferenceElements();
- for (PsiJavaCodeReferenceElement ref : refs) {
- PsiType refType = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory().createType(ref);
- if (exceptionType.isAssignableFrom(refType)) {
- refsToDelete.add(ref);
- }
- }
-
- if (refMethod != null) {
- for (RefMethod refDerived : refMethod.getDerivedMethods()) {
- removeException(refDerived, exceptionType, refsToDelete, (PsiMethod)refDerived.getElement());
- }
- } else {
- final Query<Pair<PsiMethod,PsiMethod>> query = AllOverridingMethodsSearch.search(psiMethod.getContainingClass());
- query.forEach(new Processor<Pair<PsiMethod, PsiMethod>>(){
- @Override
- public boolean process(final Pair<PsiMethod, PsiMethod> pair) {
- if (pair.first == psiMethod) {
- removeException(null, exceptionType, refsToDelete, pair.second);
- }
- return true;
- }
- });
- }
- }
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedImport/UnusedImportLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedImport/UnusedImportLocalInspection.java
index 807cf4bc8308..a8feaf9c148e 100644
--- a/java/java-impl/src/com/intellij/codeInspection/unusedImport/UnusedImportLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedImport/UnusedImportLocalInspection.java
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ex.PairedUnfairLocalInspectionTool;
+import com.siyeh.ig.imports.UnusedImportInspection;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -55,8 +56,9 @@ public class UnusedImportLocalInspection extends BaseJavaLocalInspectionTool imp
return true;
}
+ @NotNull
@Override
public String getInspectionForBatchShortName() {
- return "UnusedImport";
+ return new UnusedImportInspection().getShortName();
}
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedLibraries/UnusedLibrariesInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedLibraries/UnusedLibrariesInspection.java
deleted file mode 100644
index a8a6be97c268..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/unusedLibraries/UnusedLibrariesInspection.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * User: anna
- * Date: 18-Apr-2007
- */
-package com.intellij.codeInspection.unusedLibraries;
-
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
-import com.intellij.codeInspection.ex.JobDescriptor;
-import com.intellij.codeInspection.reference.RefManager;
-import com.intellij.codeInspection.reference.RefModule;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.progress.impl.ProgressManagerImpl;
-import com.intellij.openapi.progress.util.ProgressIndicatorBase;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.*;
-import com.intellij.openapi.roots.libraries.Library;
-import com.intellij.openapi.roots.libraries.LibraryUtil;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.VfsUtil;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.packageDependencies.BackwardDependenciesBuilder;
-import com.intellij.psi.PsiCompiledElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiRecursiveElementVisitor;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.GlobalSearchScopes;
-import com.intellij.psi.search.scope.packageSet.NamedScope;
-import com.intellij.psi.search.scope.packageSet.PackageSetFactory;
-import com.intellij.psi.search.scope.packageSet.ParsingException;
-import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.*;
-
-public class UnusedLibrariesInspection extends GlobalInspectionTool {
- private static final Logger LOG = Logger.getInstance("#" + UnusedLibrariesInspection.class.getName());
- private final JobDescriptor BACKWARD_ANALYSIS = new JobDescriptor(InspectionsBundle.message("unused.library.backward.analysis.job.description"));
-
- @Override
- public void runInspection(@NotNull AnalysisScope scope,
- @NotNull InspectionManager manager,
- @NotNull final GlobalInspectionContext globalContext,
- @NotNull ProblemDescriptionsProcessor problemProcessor) {
- ((GlobalInspectionContextImpl)globalContext).appendJobDescriptor(BACKWARD_ANALYSIS);
- final Project project = manager.getProject();
- final ArrayList<VirtualFile> libraryRoots = new ArrayList<VirtualFile>();
- if (scope.getScopeType() == AnalysisScope.PROJECT) {
- ContainerUtil.addAll(libraryRoots, LibraryUtil.getLibraryRoots(project, false, false));
- }
- else {
- final Set<Module> modules = new HashSet<Module>();
- scope.accept(new PsiRecursiveElementVisitor() {
- @Override
- public void visitFile(PsiFile file) {
- if (!(file instanceof PsiCompiledElement)) {
- final VirtualFile virtualFile = file.getVirtualFile();
- if (virtualFile != null) {
- final Module module = ModuleUtil.findModuleForFile(virtualFile, project);
- if (module != null) {
- modules.add(module);
- }
- }
- }
- }
- });
- ContainerUtil.addAll(libraryRoots, LibraryUtil.getLibraryRoots(modules.toArray(new Module[modules.size()]), false, false));
- }
- if (libraryRoots.isEmpty()) {
- return;
- }
-
- GlobalSearchScope searchScope;
- try {
- @NonNls final String libsName = "libs";
- NamedScope libScope = new NamedScope(libsName, PackageSetFactory.getInstance().compile("lib:*..*"));
- searchScope = GlobalSearchScopes.filterScope(project, libScope);
- }
- catch (ParsingException e) {
- //can't be
- LOG.error(e);
- return;
- }
- final AnalysisScope analysisScope = new AnalysisScope(searchScope, project);
- analysisScope.setSearchInLibraries(true);
- final BackwardDependenciesBuilder builder = new BackwardDependenciesBuilder(project, analysisScope);
-
- final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
-
- BACKWARD_ANALYSIS.setTotalAmount(builder.getTotalFileCount());
- ((ProgressManagerImpl)ProgressManager.getInstance()).executeProcessUnderProgress(new Runnable(){
- @Override
- public void run() {
- builder.analyze();
- }
- }, new ProgressIndicatorBase() {
- @Override
- public void setFraction(final double fraction) {
- super.setFraction(fraction);
- int nextAmount = (int)(fraction * BACKWARD_ANALYSIS.getTotalAmount());
- if (nextAmount > BACKWARD_ANALYSIS.getDoneAmount() && nextAmount < BACKWARD_ANALYSIS.getTotalAmount()) {
- BACKWARD_ANALYSIS.setDoneAmount(nextAmount);
- globalContext.incrementJobDoneAmount(BACKWARD_ANALYSIS, getText2());
- }
- }
-
- @Override
- public boolean isCanceled() {
- return progressIndicator != null && progressIndicator.isCanceled() || super.isCanceled();
- }
- });
- BACKWARD_ANALYSIS.setDoneAmount(BACKWARD_ANALYSIS.getTotalAmount());
- final Map<PsiFile, Set<PsiFile>> dependencies = builder.getDependencies();
- for (PsiFile file : dependencies.keySet()) {
- final VirtualFile virtualFile = file.getVirtualFile();
- LOG.assertTrue(virtualFile != null);
- for (Iterator<VirtualFile> i = libraryRoots.iterator(); i.hasNext();) {
- if (VfsUtil.isAncestor(i.next(), virtualFile, false)) {
- i.remove();
- }
- }
- }
- if (libraryRoots.isEmpty()) {
- return;
- }
- ProjectFileIndex projectIndex = ProjectRootManager.getInstance(project).getFileIndex();
- Map<OrderEntry, Set<VirtualFile>> unusedLibs = new HashMap<OrderEntry, Set<VirtualFile>>();
- for (VirtualFile libraryRoot : libraryRoots) {
- final List<OrderEntry> orderEntries = projectIndex.getOrderEntriesForFile(libraryRoot);
- for (OrderEntry orderEntry : orderEntries) {
- Set<VirtualFile> files = unusedLibs.get(orderEntry);
- if (files == null) {
- files = new HashSet<VirtualFile>();
- unusedLibs.put(orderEntry, files);
- }
- files.add(libraryRoot);
- }
- }
- final RefManager refManager = globalContext.getRefManager();
- for (OrderEntry orderEntry : unusedLibs.keySet()) {
- if (!(orderEntry instanceof LibraryOrderEntry)) continue;
- final RefModule refModule = refManager.getRefModule(orderEntry.getOwnerModule());
- final Set<VirtualFile> files = unusedLibs.get(orderEntry);
- final VirtualFile[] roots = ((LibraryOrderEntry)orderEntry).getRootFiles(OrderRootType.CLASSES);
- if (files.size() < roots.length) {
- final String unusedLibraryRoots = StringUtil.join(files, new Function<VirtualFile, String>() {
- @Override
- public String fun(final VirtualFile file) {
- return file.getPresentableName();
- }
- }, ",");
- String message =
- InspectionsBundle.message("unused.library.roots.problem.descriptor", unusedLibraryRoots, orderEntry.getPresentableName());
- problemProcessor.addProblemElement(refModule,
- manager.createProblemDescriptor(message, new RemoveUnusedLibrary(refModule, orderEntry, files)));
- }
- else {
- String message = InspectionsBundle.message("unused.library.problem.descriptor", orderEntry.getPresentableName());
- problemProcessor.addProblemElement(refModule,
- manager.createProblemDescriptor(message, new RemoveUnusedLibrary(refModule, orderEntry, null)));
- }
- }
- }
-
- @Override
- public boolean isEnabledByDefault() {
- return false;
- }
-
- @Override
- @Nls
- @NotNull
- public String getGroupDisplayName() {
- return GroupNames.DECLARATION_REDUNDANCY;
- }
-
- @Override
- @NotNull
- public String getDisplayName() {
- return InspectionsBundle.message("unused.library.display.name");
- }
-
- @Override
- @NonNls
- @NotNull
- public String getShortName() {
- return "UnusedLibrary";
- }
-
- private static class RemoveUnusedLibrary implements QuickFix {
- private final RefModule myRefModule;
- private final OrderEntry myOrderEntry;
- private final Set<VirtualFile> myFiles;
-
- public RemoveUnusedLibrary(final RefModule refModule, final OrderEntry orderEntry, final Set<VirtualFile> files) {
- myRefModule = refModule;
- myOrderEntry = orderEntry;
- myFiles = files;
- }
-
- @Override
- @NotNull
- public String getName() {
- return myFiles == null ? InspectionsBundle.message("detach.library.quickfix.name") : InspectionsBundle.message("detach.library.roots.quickfix.name");
- }
-
- @Override
- @NotNull
- public String getFamilyName() {
- return getName();
- }
-
- @Override
- public void applyFix(@NotNull final Project project, @NotNull final CommonProblemDescriptor descriptor) {
- final Module module = myRefModule.getModule();
-
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
- final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
- for (OrderEntry entry : model.getOrderEntries()) {
- if (entry instanceof LibraryOrderEntry && Comparing.strEqual(entry.getPresentableName(), myOrderEntry.getPresentableName())) {
- if (myFiles == null) {
- model.removeOrderEntry(entry);
- }
- else {
- final Library library = ((LibraryOrderEntry)entry).getLibrary();
- if (library != null) {
- final Library.ModifiableModel modifiableModel = library.getModifiableModel();
- for (VirtualFile file : myFiles) {
- modifiableModel.removeRoot(file.getUrl(), OrderRootType.CLASSES);
- }
- modifiableModel.commit();
- }
- }
- }
- }
- model.commit();
- }
- });
- }
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java
index 5d576bbbd27e..9750838e9c0c 100644
--- a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java
@@ -28,9 +28,10 @@ import com.intellij.analysis.AnalysisScope;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.ex.EntryPointsManagerImpl;
+import com.intellij.codeInspection.ex.EntryPointsManager;
import com.intellij.codeInspection.reference.*;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.search.PsiReferenceProcessor;
@@ -52,8 +53,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-public class UnusedParametersInspection extends GlobalJavaInspectionTool {
-
+public class UnusedParametersInspection extends GlobalJavaBatchInspectionTool {
@NonNls public static final String SHORT_NAME = "UnusedParameters";
@Override
@@ -83,7 +83,7 @@ public class UnusedParametersInspection extends GlobalJavaInspectionTool {
if (refMethod.isEntry()) return null;
final PsiModifierListOwner element = refMethod.getElement();
- if (element != null && EntryPointsManagerImpl.getInstance(manager.getProject()).isEntryPoint(element)) return null;
+ if (element != null && EntryPointsManager.getInstance(manager.getProject()).isEntryPoint(element)) return null;
final List<ProblemDescriptor> result = new ArrayList<ProblemDescriptor>();
for (RefParameter refParameter : unusedParameters) {
@@ -235,7 +235,8 @@ public class UnusedParametersInspection extends GlobalJavaInspectionTool {
@Override
public JComponent createOptionsPanel() {
final JPanel panel = new JPanel(new GridBagLayout());
- panel.add(EntryPointsManagerImpl.createConfigureAnnotationsBtn(panel),
+ Project project = ProjectUtil.guessCurrentProject(panel);
+ panel.add(EntryPointsManager.getInstance(project).createConfigureAnnotationsBtn(),
new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
new Insets(0, 0, 0, 0), 0, 0));
return panel;
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedReturnValue/UnusedReturnValue.java b/java/java-impl/src/com/intellij/codeInspection/unusedReturnValue/UnusedReturnValue.java
index 2bfbdf833c93..1ca2c0e8bdbd 100644
--- a/java/java-impl/src/com/intellij/codeInspection/unusedReturnValue/UnusedReturnValue.java
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedReturnValue/UnusedReturnValue.java
@@ -41,7 +41,7 @@ import java.util.List;
/**
* @author max
*/
-public class UnusedReturnValue extends GlobalJavaInspectionTool{
+public class UnusedReturnValue extends GlobalJavaBatchInspectionTool{
private MakeVoidQuickFix myQuickFix;
public boolean IGNORE_BUILDER_PATTERN = false;
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java
index f88e7517f7c9..1f7434ee85d8 100644
--- a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java
@@ -22,10 +22,12 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
-import com.intellij.codeInspection.ex.EntryPointsManagerImpl;
+import com.intellij.codeInspection.ex.EntryPointsManager;
+import com.intellij.codeInspection.ex.EntryPointsManagerBase;
import com.intellij.codeInspection.ex.PairedUnfairLocalInspectionTool;
import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectUtil;
import com.intellij.psi.PsiModifierListOwner;
import org.intellij.lang.annotations.Pattern;
import org.jetbrains.annotations.Nls;
@@ -92,6 +94,7 @@ public class UnusedSymbolLocalInspection extends BaseJavaLocalInspectionTool imp
return true;
}
+ @NotNull
@Override
public String getInspectionForBatchShortName() {
return UnusedDeclarationInspection.SHORT_NAME;
@@ -136,7 +139,8 @@ public class UnusedSymbolLocalInspection extends BaseJavaLocalInspectionTool imp
myCheckClassesCheckBox.addActionListener(listener);
myCheckParametersCheckBox.addActionListener(listener);
myReportUnusedParametersInPublics.addActionListener(listener);
- myAnnos.add(EntryPointsManagerImpl.createConfigureAnnotationsBtn(myPanel),
+ Project project = ProjectUtil.guessCurrentProject(myPanel);
+ myAnnos.add(EntryPointsManager.getInstance(project).createConfigureAnnotationsBtn(),
new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
new Insets(10, 0, 0, 0), 0, 0));
}
@@ -153,7 +157,7 @@ public class UnusedSymbolLocalInspection extends BaseJavaLocalInspectionTool imp
}
public static IntentionAction createQuickFix(@NonNls String qualifiedName, @Nls String element, Project project) {
- final EntryPointsManagerImpl entryPointsManager = EntryPointsManagerImpl.getInstance(project);
+ final EntryPointsManagerBase entryPointsManager = EntryPointsManagerBase.getInstance(project);
return SpecialAnnotationsUtil.createAddToSpecialAnnotationsListIntentionAction(
QuickFixBundle.message("fix.unused.symbol.injection.text", element, qualifiedName),
QuickFixBundle.message("fix.unused.symbol.injection.family"),
@@ -161,6 +165,6 @@ public class UnusedSymbolLocalInspection extends BaseJavaLocalInspectionTool imp
}
public static boolean isInjected(final PsiModifierListOwner modifierListOwner) {
- return EntryPointsManagerImpl.getInstance(modifierListOwner.getProject()).isEntryPoint(modifierListOwner);
+ return EntryPointsManagerBase.getInstance(modifierListOwner.getProject()).isEntryPoint(modifierListOwner);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/util/RefFilter.java b/java/java-impl/src/com/intellij/codeInspection/util/RefFilter.java
deleted file mode 100644
index 4e9f11a531f3..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/util/RefFilter.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Dec 1, 2001
- * Time: 11:42:56 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.util;
-
-import com.intellij.codeInspection.reference.RefEntity;
-import com.intellij.codeInspection.reference.RefJavaElement;
-import com.intellij.codeInspection.reference.RefParameter;
-
-public abstract class RefFilter {
- // Default accepts implementation accepts element if one under unaccepted one. Thus it will accept all and only upper level classes.
- public int getElementProblemCount(RefJavaElement refElement) {
- if (refElement instanceof RefParameter) return 0;
- RefEntity refOwner = refElement.getOwner();
- if (refOwner == null || !(refOwner instanceof RefJavaElement)) return 1;
-
- return 1 - getElementProblemCount((RefJavaElement)refOwner);
- }
-
- public final boolean accepts(RefJavaElement refElement) {
- return getElementProblemCount(refElement) > 0;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityExtension.java b/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityExtension.java
deleted file mode 100644
index ab0a63ebdff5..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityExtension.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2000-2009 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.visibility;
-
-import com.intellij.codeInspection.ProblemDescriptionsProcessor;
-import com.intellij.codeInspection.reference.RefManager;
-import org.jetbrains.annotations.NotNull;
-
-public interface VisibilityExtension {
- void fillIgnoreList(@NotNull RefManager refManager, @NotNull ProblemDescriptionsProcessor processor);
-} \ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java b/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
deleted file mode 100644
index 88ff09b295a6..000000000000
--- a/java/java-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- */
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Dec 21, 2001
- * Time: 8:46:41 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
-package com.intellij.codeInspection.visibility;
-
-import com.intellij.ExtensionPoints;
-import com.intellij.analysis.AnalysisScope;
-import com.intellij.codeInsight.FileModificationService;
-import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInsight.highlighting.HighlightUsagesHandler;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.ex.EntryPointsManager;
-import com.intellij.codeInspection.reference.*;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.extensions.ExtensionPoint;
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.PsiNonJavaFileReferenceProcessor;
-import com.intellij.psi.search.PsiSearchHelper;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import java.awt.*;
-import java.util.List;
-
-public class VisibilityInspection extends GlobalJavaInspectionTool {
- private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.visibility.VisibilityInspection");
- public boolean SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS = true;
- public boolean SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES = true;
- public boolean SUGGEST_PRIVATE_FOR_INNERS = false;
- private static final String DISPLAY_NAME = InspectionsBundle.message("inspection.visibility.display.name");
- @NonNls private static final String SHORT_NAME = "WeakerAccess";
- private static final String CAN_BE_PRIVATE = InspectionsBundle.message("inspection.visibility.compose.suggestion", "private");
- private static final String CAN_BE_PACKAGE_LOCAL = InspectionsBundle.message("inspection.visibility.compose.suggestion", "package local");
- private static final String CAN_BE_PROTECTED = InspectionsBundle.message("inspection.visibility.compose.suggestion", "protected");
-
- private class OptionsPanel extends JPanel {
- private final JCheckBox myPackageLocalForMembersCheckbox;
- private final JCheckBox myPrivateForInnersCheckbox;
- private final JCheckBox myPackageLocalForTopClassesCheckbox;
-
- private OptionsPanel() {
- super(new GridBagLayout());
-
- GridBagConstraints gc = new GridBagConstraints();
- gc.fill = GridBagConstraints.HORIZONTAL;
- gc.weightx = 1;
- gc.weighty = 0;
- gc.anchor = GridBagConstraints.NORTHWEST;
-
- myPackageLocalForMembersCheckbox = new JCheckBox(InspectionsBundle.message("inspection.visibility.option"));
- myPackageLocalForMembersCheckbox.setSelected(SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS);
- myPackageLocalForMembersCheckbox.getModel().addChangeListener(new ChangeListener() {
- @Override
- public void stateChanged(ChangeEvent e) {
- SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS = myPackageLocalForMembersCheckbox.isSelected();
- }
- });
-
- gc.gridy = 0;
- add(myPackageLocalForMembersCheckbox, gc);
-
- myPackageLocalForTopClassesCheckbox = new JCheckBox(InspectionsBundle.message("inspection.visibility.option1"));
- myPackageLocalForTopClassesCheckbox.setSelected(SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES);
- myPackageLocalForTopClassesCheckbox.getModel().addChangeListener(new ChangeListener() {
- @Override
- public void stateChanged(ChangeEvent e) {
- SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES = myPackageLocalForTopClassesCheckbox.isSelected();
- }
- });
-
- gc.gridy = 1;
- add(myPackageLocalForTopClassesCheckbox, gc);
-
-
- myPrivateForInnersCheckbox = new JCheckBox(InspectionsBundle.message("inspection.visibility.option2"));
- myPrivateForInnersCheckbox.setSelected(SUGGEST_PRIVATE_FOR_INNERS);
- myPrivateForInnersCheckbox.getModel().addChangeListener(new ChangeListener() {
- @Override
- public void stateChanged(ChangeEvent e) {
- SUGGEST_PRIVATE_FOR_INNERS = myPrivateForInnersCheckbox.isSelected();
- }
- });
-
- gc.gridy = 2;
- gc.weighty = 1;
- add(myPrivateForInnersCheckbox, gc);
- }
- }
-
- @Override
- public JComponent createOptionsPanel() {
- return new OptionsPanel();
- }
-
- @Override
- @NotNull
- public String getDisplayName() {
- return DISPLAY_NAME;
- }
-
- @Override
- @NotNull
- public String getGroupDisplayName() {
- return GroupNames.DECLARATION_REDUNDANCY;
- }
-
- @Override
- @NotNull
- public String getShortName() {
- return SHORT_NAME;
- }
-
- @Override
- @Nullable
- public CommonProblemDescriptor[] checkElement(@NotNull final RefEntity refEntity,
- @NotNull final AnalysisScope scope,
- @NotNull final InspectionManager manager,
- @NotNull final GlobalInspectionContext globalContext,
- @NotNull final ProblemDescriptionsProcessor processor) {
- if (refEntity instanceof RefJavaElement) {
- final RefJavaElement refElement = (RefJavaElement)refEntity;
-
- if (refElement instanceof RefParameter) return null;
- if (refElement.isSyntheticJSP()) return null;
-
- //ignore entry points.
- if (refElement.isEntry()) return null;
-
- //ignore implicit constructors. User should not be able to see them.
- if (refElement instanceof RefImplicitConstructor) return null;
-
- if (refElement instanceof RefField && ((RefField)refElement).getElement() instanceof PsiEnumConstant) return null;
-
- //ignore library override methods.
- if (refElement instanceof RefMethod) {
- RefMethod refMethod = (RefMethod) refElement;
- if (refMethod.isExternalOverride()) return null;
- if (refMethod.isEntry()) return null;
- }
-
- //ignore anonymous classes. They do not have access modifiers.
- if (refElement instanceof RefClass) {
- RefClass refClass = (RefClass) refElement;
- if (refClass.isAnonymous() || refClass.isEntry() || refClass.isTestCase() || refClass.isServlet() || refClass.isApplet() || refClass.isLocalClass()) return null;
- if (isTopLevelClass(refClass) && !SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES) return null;
- }
-
- //ignore unreferenced code. They could be a potential entry points.
- if (refElement.getInReferences().isEmpty()) return null;
-
- //ignore interface members. They always have public access modifier.
- if (refElement.getOwner() instanceof RefClass) {
- RefClass refClass = (RefClass) refElement.getOwner();
- if (refClass.isInterface()) return null;
- }
- String access = getPossibleAccess(refElement);
- if (access != refElement.getAccessModifier() && access != null) {
- final PsiElement element = refElement.getElement();
- final PsiElement nameIdentifier = element != null ? HighlightUsagesHandler.getNameIdentifier(element) : null;
- if (nameIdentifier != null) {
- return new ProblemDescriptor[]{manager.createProblemDescriptor(nameIdentifier,
- access.equals(PsiModifier.PRIVATE)
- ? CAN_BE_PRIVATE
- : access.equals(PsiModifier.PACKAGE_LOCAL)
- ? CAN_BE_PACKAGE_LOCAL
- : CAN_BE_PROTECTED,
- new AcceptSuggestedAccess(globalContext.getRefManager(), access),
- ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false)};
- }
- }
- }
- return null;
- }
-
- @Nullable
- @PsiModifier.ModifierConstant
- public String getPossibleAccess(@Nullable RefJavaElement refElement) {
- if (refElement == null) return null;
- String curAccess = refElement.getAccessModifier();
- String weakestAccess = PsiModifier.PRIVATE;
-
- if (isTopLevelClass(refElement) || isCalledOnSubClasses(refElement)) {
- weakestAccess = PsiModifier.PACKAGE_LOCAL;
- }
-
- if (isAbstractMethod(refElement)) {
- weakestAccess = PsiModifier.PROTECTED;
- }
-
- if (curAccess == weakestAccess) return curAccess;
-
- while (true) {
- String weakerAccess = getWeakerAccess(curAccess, refElement);
- if (weakerAccess == null || RefJavaUtil.getInstance().compareAccess(weakerAccess, weakestAccess) < 0) break;
- if (isAccessible(refElement, weakerAccess)) {
- curAccess = weakerAccess;
- }
- else {
- break;
- }
- }
-
- return curAccess;
- }
-
- private static boolean isCalledOnSubClasses(RefElement refElement) {
- return refElement instanceof RefMethod && ((RefMethod)refElement).isCalledOnSubClass();
- }
-
- private static boolean isAbstractMethod(RefElement refElement) {
- return refElement instanceof RefMethod && ((RefMethod) refElement).isAbstract();
- }
-
- private static boolean isTopLevelClass(RefElement refElement) {
- return refElement instanceof RefClass && RefJavaUtil.getInstance().getTopLevelClass(refElement) == refElement;
- }
-
- @Nullable
- @PsiModifier.ModifierConstant
- private String getWeakerAccess(@PsiModifier.ModifierConstant String curAccess, RefElement refElement) {
- if (curAccess == PsiModifier.PUBLIC) {
- return isTopLevelClass(refElement) ? PsiModifier.PACKAGE_LOCAL : PsiModifier.PROTECTED;
- }
- if (curAccess == PsiModifier.PROTECTED) {
- return SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS ? PsiModifier.PACKAGE_LOCAL : PsiModifier.PRIVATE;
- }
- if (curAccess == PsiModifier.PACKAGE_LOCAL) {
- return PsiModifier.PRIVATE;
- }
-
- return null;
- }
-
- private boolean isAccessible(RefJavaElement to, @PsiModifier.ModifierConstant String accessModifier) {
-
- for (RefElement refElement : to.getInReferences()) {
- if (!isAccessibleFrom(refElement, to, accessModifier)) return false;
- }
-
- if (to instanceof RefMethod) {
- RefMethod refMethod = (RefMethod) to;
-
- if (refMethod.isAbstract() && (refMethod.getDerivedMethods().isEmpty() || refMethod.getAccessModifier() == PsiModifier.PRIVATE)) return false;
-
- for (RefMethod refOverride : refMethod.getDerivedMethods()) {
- if (!isAccessibleFrom(refOverride, to, accessModifier)) return false;
- }
-
- for (RefMethod refSuper : refMethod.getSuperMethods()) {
- if (RefJavaUtil.getInstance().compareAccess(refSuper.getAccessModifier(), accessModifier) > 0) return false;
- }
- }
-
- if (to instanceof RefClass) {
- RefClass refClass = (RefClass) to;
- for (RefClass subClass : refClass.getSubClasses()) {
- if (!isAccessibleFrom(subClass, to, accessModifier)) return false;
- }
-
- List children = refClass.getChildren();
- if (children != null) {
- for (Object refElement : children) {
- if (!isAccessible((RefJavaElement)refElement, accessModifier)) return false;
- }
- }
-
- for (final RefElement refElement : refClass.getInTypeReferences()) {
- if (!isAccessibleFrom(refElement, refClass, accessModifier)) return false;
- }
-
- List<RefJavaElement> classExporters = ((RefClassImpl)refClass).getClassExporters();
- if (classExporters != null) {
- for (RefJavaElement refExporter : classExporters) {
- if (getAccessLevel(accessModifier) < getAccessLevel(refExporter.getAccessModifier())) return false;
- }
- }
- }
-
- return true;
- }
-
- private static int getAccessLevel(@PsiModifier.ModifierConstant String access) {
- if (access == PsiModifier.PRIVATE) return 1;
- if (access == PsiModifier.PACKAGE_LOCAL) return 2;
- if (access == PsiModifier.PROTECTED) return 3;
- return 4;
- }
-
- private boolean isAccessibleFrom(RefElement from, RefJavaElement to, String accessModifier) {
- if (accessModifier == PsiModifier.PUBLIC) return true;
-
- final RefJavaUtil refUtil = RefJavaUtil.getInstance();
- if (accessModifier == PsiModifier.PACKAGE_LOCAL) {
- return RefJavaUtil.getPackage(from) == RefJavaUtil.getPackage(to);
- }
-
- RefClass fromTopLevel = refUtil.getTopLevelClass(from);
- RefClass toTopLevel = refUtil.getTopLevelClass(to);
- RefClass fromOwner = refUtil.getOwnerClass(from);
- RefClass toOwner = refUtil.getOwnerClass(to);
-
- if (accessModifier == PsiModifier.PROTECTED) {
- if (SUGGEST_PRIVATE_FOR_INNERS) {
- return refUtil.isInheritor(fromTopLevel, toOwner)
- || fromOwner != null && refUtil.isInheritor(fromOwner, toTopLevel)
- || toOwner != null && refUtil.getOwnerClass(toOwner) == from;
- }
-
- return refUtil.isInheritor(fromTopLevel, toOwner);
- }
-
- if (accessModifier == PsiModifier.PRIVATE) {
- if (SUGGEST_PRIVATE_FOR_INNERS) {
- if (isInExtendsList(to, fromTopLevel.getElement().getExtendsList())) return false;
- if (isInExtendsList(to, fromTopLevel.getElement().getImplementsList())) return false;
- if (isInAnnotations(to, fromTopLevel)) return false;
- return fromTopLevel == toOwner || fromOwner == toTopLevel || toOwner != null && refUtil.getOwnerClass(toOwner) == from;
- }
-
- if (fromOwner != null && fromOwner.isStatic() && !to.isStatic() && refUtil.isInheritor(fromOwner, toOwner)) return false;
-
- if (fromTopLevel == toOwner) {
- if (from instanceof RefClass && to instanceof RefClass) {
- final PsiClass fromClass = ((RefClass)from).getElement();
- LOG.assertTrue(fromClass != null);
- if (isInExtendsList(to, fromClass.getExtendsList())) return false;
- if (isInExtendsList(to, fromClass.getImplementsList())) return false;
- }
-
- return true;
- }
- }
-
- return false;
- }
-
- private static boolean isInAnnotations(final RefJavaElement to, final RefClass fromTopLevel) {
- final PsiModifierList modifierList = fromTopLevel.getElement().getModifierList();
- if (modifierList == null) return false;
- final PsiElement toElement = to.getElement();
-
- final boolean [] resolved = new boolean[] {false};
- modifierList.accept(new JavaRecursiveElementWalkingVisitor() {
- @Override
- public void visitReferenceExpression(PsiReferenceExpression expression) {
- if (resolved[0]) return;
- super.visitReferenceExpression(expression);
- if (expression.resolve() == toElement) {
- resolved[0] = true;
- }
- }
- });
- return resolved[0];
- }
-
- private static boolean isInExtendsList(final RefJavaElement to, final PsiReferenceList extendsList) {
- if (extendsList != null) {
- final PsiJavaCodeReferenceElement[] referenceElements = extendsList.getReferenceElements();
- for (PsiJavaCodeReferenceElement referenceElement : referenceElements) {
- final PsiReferenceParameterList parameterList = referenceElement.getParameterList();
- if (parameterList != null) {
- for (PsiType type : parameterList.getTypeArguments()) {
- if (extendsList.getManager().areElementsEquivalent(PsiUtil.resolveClassInType(type), to.getElement())) {
- return true;
- }
- }
- }
- }
- }
- return false;
- }
-
-
- @Override
- protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager,
- @NotNull final GlobalJavaInspectionContext globalContext,
- @NotNull final ProblemDescriptionsProcessor processor) {
- final EntryPointsManager entryPointsManager = globalContext.getEntryPointsManager(manager);
- for (RefElement entryPoint : entryPointsManager.getEntryPoints()) {
- ignoreElement(processor, entryPoint);
- }
-
- ExtensionPoint<VisibilityExtension> point = Extensions.getRootArea().getExtensionPoint(ExtensionPoints.VISIBLITY_TOOL);
- for (VisibilityExtension addin : point.getExtensions()) {
- addin.fillIgnoreList(manager, processor);
- }
- manager.iterate(new RefJavaVisitor() {
- @Override public void visitElement(@NotNull final RefEntity refEntity) {
- if (!(refEntity instanceof RefElement)) return;
- if (processor.getDescriptions(refEntity) == null) return;
- refEntity.accept(new RefJavaVisitor() {
- @Override public void visitField(@NotNull final RefField refField) {
- if (refField.getAccessModifier() != PsiModifier.PRIVATE) {
- globalContext.enqueueFieldUsagesProcessor(refField, new GlobalJavaInspectionContext.UsagesProcessor() {
- @Override
- public boolean process(PsiReference psiReference) {
- ignoreElement(processor, refField);
- return false;
- }
- });
- }
- }
-
- @Override public void visitMethod(@NotNull final RefMethod refMethod) {
- if (!refMethod.isExternalOverride() && refMethod.getAccessModifier() != PsiModifier.PRIVATE &&
- !(refMethod instanceof RefImplicitConstructor)) {
- globalContext.enqueueDerivedMethodsProcessor(refMethod, new GlobalJavaInspectionContext.DerivedMethodsProcessor() {
- @Override
- public boolean process(PsiMethod derivedMethod) {
- ignoreElement(processor, refMethod);
- return false;
- }
- });
-
- globalContext.enqueueMethodUsagesProcessor(refMethod, new GlobalJavaInspectionContext.UsagesProcessor() {
- @Override
- public boolean process(PsiReference psiReference) {
- ignoreElement(processor, refMethod);
- return false;
- }
- });
-
- if (entryPointsManager.isAddNonJavaEntries()) {
- final RefClass ownerClass = refMethod.getOwnerClass();
- if (refMethod.isConstructor() && ownerClass.getDefaultConstructor() != null) {
- String qualifiedName = ownerClass.getElement().getQualifiedName();
- if (qualifiedName != null) {
- final Project project = manager.getProject();
- PsiSearchHelper.SERVICE.getInstance(project)
- .processUsagesInNonJavaFiles(qualifiedName, new PsiNonJavaFileReferenceProcessor() {
- @Override
- public boolean process(PsiFile file, int startOffset, int endOffset) {
- entryPointsManager.addEntryPoint(refMethod, false);
- ignoreElement(processor, refMethod);
- return false;
- }
- }, GlobalSearchScope.projectScope(project));
- }
- }
- }
- }
- }
-
- @Override public void visitClass(@NotNull final RefClass refClass) {
- if (!refClass.isAnonymous()) {
- globalContext.enqueueDerivedClassesProcessor(refClass, new GlobalJavaInspectionContext.DerivedClassesProcessor() {
- @Override
- public boolean process(PsiClass inheritor) {
- ignoreElement(processor, refClass);
- return false;
- }
- });
-
- globalContext.enqueueClassUsagesProcessor(refClass, new GlobalJavaInspectionContext.UsagesProcessor() {
- @Override
- public boolean process(PsiReference psiReference) {
- ignoreElement(processor, refClass);
- return false;
- }
- });
- }
- }
- });
-
- }
- });
- return false;
- }
-
- private static void ignoreElement(@NotNull ProblemDescriptionsProcessor processor, @NotNull RefEntity refElement){
- processor.ignoreElement(refElement);
-
- if (refElement instanceof RefClass) {
- RefClass refClass = (RefClass) refElement;
- RefMethod defaultConstructor = refClass.getDefaultConstructor();
- if (defaultConstructor != null) {
- processor.ignoreElement(defaultConstructor);
- return;
- }
- }
-
- RefEntity owner = refElement.getOwner();
- if (owner instanceof RefElement) {
- processor.ignoreElement(owner);
- }
- }
-
- @Override
- public void compose(@NotNull final StringBuffer buf, @NotNull final RefEntity refEntity, @NotNull final HTMLComposer composer) {
- composer.appendElementInReferences(buf, (RefElement)refEntity);
- }
-
- @Override
- @Nullable
- public QuickFix getQuickFix(final String hint) {
- return new AcceptSuggestedAccess(null, hint);
- }
-
- @Override
- @Nullable
- public String getHint(@NotNull final QuickFix fix) {
- return ((AcceptSuggestedAccess)fix).getHint();
- }
-
- private static class AcceptSuggestedAccess implements LocalQuickFix{
- private final RefManager myManager;
- @PsiModifier.ModifierConstant private final String myHint;
-
- private AcceptSuggestedAccess(final RefManager manager, @PsiModifier.ModifierConstant String hint) {
- myManager = manager;
- myHint = hint;
- }
-
- @Override
- @NotNull
- public String getName() {
- return InspectionsBundle.message("inspection.visibility.accept.quickfix");
- }
-
- @Override
- @NotNull
- public String getFamilyName() {
- return getName();
- }
-
- @Override
- public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
- if (!FileModificationService.getInstance().preparePsiElementForWrite(descriptor.getPsiElement())) return;
- final PsiModifierListOwner element = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiModifierListOwner.class);
- if (element != null) {
- RefElement refElement = null;
- if (myManager != null) {
- refElement = myManager.getReference(element);
- }
- try {
- if (element instanceof PsiVariable) {
- ((PsiVariable)element).normalizeDeclaration();
- }
-
- PsiModifierList list = element.getModifierList();
-
- LOG.assertTrue(list != null);
-
- if (element instanceof PsiMethod) {
- PsiMethod psiMethod = (PsiMethod)element;
- PsiClass containingClass = psiMethod.getContainingClass();
- if (containingClass != null && containingClass.getParent() instanceof PsiFile &&
- myHint == PsiModifier.PRIVATE &&
- list.hasModifierProperty(PsiModifier.FINAL)) {
- list.setModifierProperty(PsiModifier.FINAL, false);
- }
- }
-
- list.setModifierProperty(myHint, true);
- if (refElement instanceof RefJavaElement) {
- RefJavaUtil.getInstance().setAccessModifier((RefJavaElement)refElement, myHint);
- }
- }
- catch (IncorrectOperationException e) {
- LOG.error(e);
- }
- }
- }
-
- public String getHint() {
- return myHint;
- }
- }
-}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/ArrayListKeyDescriptor.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/ArrayListKeyDescriptor.java
new file mode 100644
index 000000000000..0f2d3de6e0a0
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/ArrayListKeyDescriptor.java
@@ -0,0 +1,50 @@
+package com.intellij.compilerOutputIndex.api.descriptor;
+
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class ArrayListKeyDescriptor<E> implements KeyDescriptor<List<E>> {
+
+ private final DataExternalizer<E> myDataExternalizer;
+
+ public ArrayListKeyDescriptor(final DataExternalizer<E> dataExternalizer) {
+ myDataExternalizer = dataExternalizer;
+ }
+
+ @Override
+ public void save(final DataOutput out, final List<E> list) throws IOException {
+ out.writeInt(list.size());
+ for (final E element : list) {
+ myDataExternalizer.save(out, element);
+ }
+ }
+
+ @Override
+ public ArrayList<E> read(final DataInput in) throws IOException {
+ final int size = in.readInt();
+ final ArrayList<E> list = new ArrayList<E>(size);
+ for (int i = 0; i < size; i++) {
+ list.add(myDataExternalizer.read(in));
+ }
+ return list;
+ }
+
+ @Override
+ public int getHashCode(final List<E> value) {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean isEqual(final List<E> val1, final List<E> val2) {
+ return val1.equals(val2);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashMapKeyDescriptor.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashMapKeyDescriptor.java
new file mode 100644
index 000000000000..1f012dd68a44
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashMapKeyDescriptor.java
@@ -0,0 +1,54 @@
+package com.intellij.compilerOutputIndex.api.descriptor;
+
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class HashMapKeyDescriptor<K, V> implements KeyDescriptor<Map<K, V>> {
+
+ private final DataExternalizer<K> myKeyDataExternalizer;
+ private final DataExternalizer<V> myValueDataExternalizer;
+
+ public HashMapKeyDescriptor(final DataExternalizer<K> keyDataExternalizer, final DataExternalizer<V> valueDataExternalizer) {
+ myKeyDataExternalizer = keyDataExternalizer;
+ myValueDataExternalizer = valueDataExternalizer;
+ }
+
+ @Override
+ public void save(final DataOutput out, final Map<K, V> map) throws IOException {
+ final int size = map.size();
+ out.writeInt(size);
+ for (final Map.Entry<K, V> e : map.entrySet()) {
+ myKeyDataExternalizer.save(out, e.getKey());
+ myValueDataExternalizer.save(out, e.getValue());
+ }
+ }
+
+ @Override
+ public Map<K, V> read(final DataInput in) throws IOException {
+ final int size = in.readInt();
+ final HashMap<K, V> map = new HashMap<K, V>(size);
+ for (int i = 0; i < size; i++) {
+ map.put(myKeyDataExternalizer.read(in), myValueDataExternalizer.read(in));
+ }
+ return map;
+ }
+
+ @Override
+ public int getHashCode(final Map<K, V> map) {
+ return map.hashCode();
+ }
+
+ @Override
+ public boolean isEqual(final Map<K, V> val1, final Map<K, V> val2) {
+ return val1.equals(val2);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashSetKeyDescriptor.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashSetKeyDescriptor.java
new file mode 100644
index 000000000000..1201ccf98446
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashSetKeyDescriptor.java
@@ -0,0 +1,54 @@
+package com.intellij.compilerOutputIndex.api.descriptor;
+
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class HashSetKeyDescriptor<K> implements KeyDescriptor<Set<K>> {
+
+ private final DataExternalizer<K> keyDataExternalizer;
+
+ public HashSetKeyDescriptor(final DataExternalizer<K> keyDataExternalizer) {
+ this.keyDataExternalizer = keyDataExternalizer;
+ }
+
+ @Override
+ public void save(final DataOutput out, final Set<K> set) throws IOException {
+ out.writeInt(set.size());
+ for (final K k : set) {
+ keyDataExternalizer.save(out, k);
+ }
+ }
+
+ @Override
+ public HashSet<K> read(final DataInput in) throws IOException {
+ final int size = in.readInt();
+ final HashSet<K> set = new HashSet<K>(size);
+ for (int i = 0; i < size; i++) {
+ set.add(keyDataExternalizer.read(in));
+ }
+ return set;
+ }
+
+ public static <K> HashSetKeyDescriptor<K> of(final DataExternalizer<K> keyDataExternalizer) {
+ return new HashSetKeyDescriptor<K>(keyDataExternalizer);
+ }
+
+ @Override
+ public int getHashCode(final Set<K> value) {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean isEqual(final Set<K> val1, final Set<K> val2) {
+ return val1.equals(val2);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/AsmUtil.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/AsmUtil.java
new file mode 100644
index 000000000000..45f761e3203f
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/AsmUtil.java
@@ -0,0 +1,129 @@
+package com.intellij.compilerOutputIndex.api.fs;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.Opcodes;
+import org.jetbrains.asm4.Type;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public final class AsmUtil implements Opcodes {
+
+ private AsmUtil() {}
+
+ public static boolean isStaticMethodDeclaration(final int access) {
+ return (access & Opcodes.ACC_STATIC) != 0;
+ }
+
+ public static boolean isStaticMethodInvocation(final int opcode) {
+ return opcode == Opcodes.INVOKESTATIC;
+ }
+
+ public static String getQualifiedClassName(final String name) {
+ return asJavaInnerClassQName(Type.getObjectType(name).getClassName());
+ }
+
+ public static String getReturnType(final String desc) {
+ return asJavaInnerClassQName(Type.getReturnType(desc).getClassName());
+ }
+
+ public static String[] getQualifiedClassNames(final String[] classNames, final String... yetAnotherClassNames) {
+ final List<String> qualifiedClassNames = new ArrayList<String>(classNames.length + yetAnotherClassNames.length);
+ for (final String className : classNames) {
+ qualifiedClassNames.add(getQualifiedClassName(className));
+ }
+ for (final String className : yetAnotherClassNames) {
+ if (className != null) {
+ qualifiedClassNames.add(getQualifiedClassName(className));
+ }
+ }
+ return ArrayUtil.toStringArray(qualifiedClassNames);
+ }
+
+ public static String[] getParamsTypes(final String desc) {
+ final Type[] types = Type.getArgumentTypes(desc);
+ final String[] typesAsString = new String[types.length];
+ for (int i = 0; i < types.length; i++) {
+ typesAsString[i] = types[i].getClassName();
+ }
+ return typesAsString;
+ }
+
+ @Nullable
+ public static String getSignature(final PsiMethod psiMethod) {
+ final PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
+ final StringBuilder sb = new StringBuilder();
+ sb.append("(");
+ for (final PsiParameter p : parameters) {
+ final String desc = getDescriptor(p);
+ if (desc == null) {
+ return null;
+ }
+ sb.append(desc);
+ }
+ sb.append(")");
+ final String desc = getDescriptor(psiMethod.getReturnType());
+ if (desc == null) {
+ return null;
+ }
+ sb.append(desc);
+ return sb.toString();
+ }
+
+ @Nullable
+ private static String getDescriptor(final PsiParameter parameter) {
+ return getDescriptor(parameter.getType());
+ }
+
+ @Nullable
+ private static String getDescriptor(@Nullable final PsiType type) {
+ if (type == null) {
+ return null;
+ }
+ if (type instanceof PsiPrimitiveType) {
+ final PsiPrimitiveType primitiveType = (PsiPrimitiveType) type;
+ if (PsiType.INT.equals(primitiveType)) {
+ return "I";
+ } else if (primitiveType.equals(PsiType.VOID)) {
+ return "V";
+ } else if (primitiveType.equals(PsiType.BOOLEAN)) {
+ return "Z";
+ } else if (primitiveType.equals(PsiType.BYTE)) {
+ return "B";
+ } else if (primitiveType.equals(PsiType.CHAR)) {
+ return "C";
+ } else if (primitiveType.equals(PsiType.SHORT)) {
+ return "S";
+ } else if (primitiveType.equals(PsiType.DOUBLE)) {
+ return "D";
+ } else if (primitiveType.equals(PsiType.FLOAT)) {
+ return "F";
+ } else /* if (primitiveType.equals(PsiType.LONG)) */ {
+ return "J";
+ }
+ } else if (type instanceof PsiArrayType) {
+ return "[" + getDescriptor(((PsiArrayType) type).getComponentType());
+ } else {
+ final PsiClassType classType = (PsiClassType) type;
+ final PsiClass aClass = classType.resolve();
+ if (aClass == null) {
+ return null;
+ }
+ final String qName = aClass.getQualifiedName();
+ if (qName == null) {
+ return null;
+ }
+ return "L" + StringUtil.replace(qName, ".", "/") + ";";
+ }
+ }
+
+ private static String asJavaInnerClassQName(final String byteCodeClassQName) {
+ return StringUtil.replaceChar(byteCodeClassQName, '$', '.');
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/CompilerOutputFilesUtil.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/CompilerOutputFilesUtil.java
new file mode 100644
index 000000000000..ef4137079f95
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/CompilerOutputFilesUtil.java
@@ -0,0 +1,64 @@
+package com.intellij.compilerOutputIndex.api.fs;
+
+import com.intellij.openapi.compiler.CompilerPaths;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Consumer;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public final class CompilerOutputFilesUtil {
+
+ private CompilerOutputFilesUtil() {}
+
+ public final static String CLASS_FILES_SUFFIX = ".class";
+
+ public static void iterateProjectClassFiles(@NotNull final Project project, @NotNull final Consumer<File> fileConsumer) {
+ for (final Module module : ModuleManager.getInstance(project).getModules()) {
+ iterateModuleClassFiles(module, fileConsumer);
+ }
+ }
+
+ public static void iterateModuleClassFiles(@NotNull final Module module, @NotNull final Consumer<File> fileConsumer) {
+ final VirtualFile moduleOutputDirectory = CompilerPaths.getModuleOutputDirectory(module, false);
+ if (moduleOutputDirectory == null) {
+ return;
+ }
+ final String canonicalPath = moduleOutputDirectory.getCanonicalPath();
+ if (canonicalPath == null) {
+ return;
+ }
+ final File root = new File(canonicalPath);
+ iterateClassFilesOverRoot(root, fileConsumer);
+ }
+
+ public static void iterateClassFilesOverRoot(@NotNull final File file, final Consumer<File> fileConsumer) {
+ iterateClassFilesOverRoot(file, fileConsumer, new HashSet<File>());
+ }
+
+ private static void iterateClassFilesOverRoot(@NotNull final File file, final Consumer<File> fileConsumer, final Set<File> visited) {
+ if (file.isDirectory()) {
+ final File[] files = file.listFiles();
+ if (files != null) {
+ for (final File childFile : files) {
+ if (visited.add(childFile)) {
+ iterateClassFilesOverRoot(childFile.getAbsoluteFile(), fileConsumer, visited);
+ }
+ }
+ }
+ }
+ else {
+ if (file.getName().endsWith(CLASS_FILES_SUFFIX)) {
+ fileConsumer.consume(file);
+ }
+ }
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/FileVisitorService.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/FileVisitorService.java
new file mode 100644
index 000000000000..9a7f00be3dc3
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/FileVisitorService.java
@@ -0,0 +1,53 @@
+package com.intellij.compilerOutputIndex.api.fs;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.util.Consumer;
+
+import java.io.File;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public interface FileVisitorService {
+
+ interface Visitor {
+ void visit(File file);
+ }
+
+ void visit(final Consumer<File> visitor);
+
+ class ProjectClassFiles implements FileVisitorService {
+ private final Project myProject;
+
+ public ProjectClassFiles(final Project project) {
+ myProject = project;
+ }
+
+ @Override
+ public void visit(final Consumer<File> visitor) {
+ CompilerOutputFilesUtil.iterateProjectClassFiles(myProject, visitor);
+ }
+ }
+
+ class DirectoryClassFiles implements FileVisitorService {
+ private final File myDir;
+
+ public DirectoryClassFiles(final File dir) {
+ if (!dir.isDirectory()) {
+ throw new IllegalArgumentException();
+ }
+ myDir = dir;
+ }
+
+ @Override
+ public void visit(final Consumer<File> visitor) {
+ //noinspection ConstantConditions
+ for (final File file : myDir.listFiles()) {
+ if (file.getName().endsWith(CompilerOutputFilesUtil.CLASS_FILES_SUFFIX)) {
+ visitor.consume(file);
+ }
+ }
+ }
+ }
+}
+
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java
new file mode 100644
index 000000000000..a37368b03d86
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java
@@ -0,0 +1,141 @@
+package com.intellij.compilerOutputIndex.api.indexer;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Factory;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.indexing.*;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+import com.intellij.util.io.PersistentHashMap;
+import org.jetbrains.asm4.ClassReader;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+
+import static com.intellij.util.indexing.IndexInfrastructure.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public abstract class CompilerOutputBaseIndex<K, V> {
+ public final static ExtensionPointName<CompilerOutputBaseIndex> EXTENSION_POINT_NAME =
+ ExtensionPointName.create("com.intellij.java.compilerOutputIndex");
+
+ private final static Logger LOG = Logger.getInstance(CompilerOutputBaseIndex.class);
+ private final KeyDescriptor<K> myKeyDescriptor;
+ private final DataExternalizer<V> myValueExternalizer;
+
+ protected volatile MapReduceIndex<K, V, ClassReader> myIndex;
+
+ private volatile Project myProject;
+
+ public CompilerOutputBaseIndex(final KeyDescriptor<K> keyDescriptor, final DataExternalizer<V> valueExternalizer) {
+ myKeyDescriptor = keyDescriptor;
+ myValueExternalizer = valueExternalizer;
+ }
+
+ public final boolean init(final Project project) {
+ myProject = project;
+ final MapReduceIndex<K, V, ClassReader> index;
+ final Ref<Boolean> rewriteIndex = new Ref<Boolean>(false);
+ try {
+ final ID<K, V> indexId = getIndexId();
+ if (!IndexInfrastructure.getIndexRootDir(indexId).exists()) {
+ rewriteIndex.set(true);
+ }
+ final File storageFile = IndexInfrastructure.getStorageFile(indexId);
+ final MapIndexStorage<K, V> indexStorage = new MapIndexStorage<K, V>(storageFile, myKeyDescriptor, myValueExternalizer, 1024);
+ index = new MapReduceIndex<K, V, ClassReader>(indexId, getIndexer(), indexStorage);
+ index.setInputIdToDataKeysIndex(new Factory<PersistentHashMap<Integer, Collection<K>>>() {
+ @Override
+ public PersistentHashMap<Integer, Collection<K>> create() {
+ Exception failCause = null;
+ for (int attempts = 0; attempts < 2; attempts++) {
+ try {
+ return FileBasedIndexImpl.createIdToDataKeysIndex(indexId, myKeyDescriptor, new MemoryIndexStorage<K, V>(indexStorage));
+ }
+ catch (IOException e) {
+ failCause = e;
+ FileUtil.delete(IndexInfrastructure.getInputIndexStorageFile(getIndexId()));
+ rewriteIndex.set(true);
+ }
+ }
+ throw new RuntimeException("couldn't create index", failCause);
+ }
+ });
+ final File versionFile = getVersionFile(indexId);
+ if (versionFile.exists()) {
+ if (versionDiffers(versionFile, getVersion())) {
+ rewriteVersion(versionFile, getVersion());
+ rewriteIndex.set(true);
+ try {
+ LOG.info("clearing index for updating index version");
+ index.clear();
+ }
+ catch (StorageException e) {
+ LOG.error("couldn't clear index for reinitializing");
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ else if (versionFile.createNewFile()) {
+ rewriteVersion(versionFile, getVersion());
+ rewriteIndex.set(true);
+ }
+ else {
+ LOG.error(String.format("problems while access to index version file to index %s ", indexId));
+ }
+ }
+ catch (IOException e) {
+ LOG.error("couldn't initialize index");
+ throw new RuntimeException(e);
+ }
+ myIndex = index;
+ return rewriteIndex.get();
+ }
+
+ protected abstract ID<K, V> getIndexId();
+
+ protected abstract int getVersion();
+
+ protected abstract DataIndexer<K, V, ClassReader> getIndexer();
+
+ public final void projectClosed() {
+ if (myIndex != null) {
+ try {
+ myIndex.flush();
+ }
+ catch (StorageException ignored) {
+ }
+ myIndex.dispose();
+ }
+ }
+
+ public void update(final int id, final ClassReader classReader) {
+ Boolean result = myIndex.update(id, classReader).compute();
+ if (result == Boolean.FALSE) throw new RuntimeException();
+ }
+
+ public void clear() {
+ try {
+ myIndex.clear();
+ }
+ catch (StorageException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected final ID<K, V> generateIndexId(final String indexName) {
+ return CompilerOutputIndexUtil.generateIndexId(indexName, myProject);
+ }
+
+ protected final ID<K, V> generateIndexId(final Class aClass) {
+ final String className = StringUtil.getShortName(aClass);
+ return generateIndexId(StringUtil.trimEnd(className, "Index"));
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexUtil.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexUtil.java
new file mode 100644
index 000000000000..c096cc81a364
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexUtil.java
@@ -0,0 +1,21 @@
+package com.intellij.compilerOutputIndex.api.indexer;
+
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.indexing.ID;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class CompilerOutputIndexUtil {
+ private CompilerOutputIndexUtil() {}
+
+ public static <K, V> ID<K, V> generateIndexId(final String indexName, final Project project) {
+ return ID.create(String.format("compilerOutputIndex.%s.%d", indexName, Math.abs(project.getBasePath().hashCode())));
+ }
+
+ public static boolean isSetterOrConstructorMethodName(final String methodName) {
+ return MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(methodName) || methodName.startsWith("set");
+
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java
new file mode 100644
index 000000000000..83da82862c22
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java
@@ -0,0 +1,360 @@
+package com.intellij.compilerOutputIndex.api.indexer;
+
+import com.intellij.compilerOutputIndex.api.fs.CompilerOutputFilesUtil;
+import com.intellij.compilerOutputIndex.api.fs.FileVisitorService;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompileTask;
+import com.intellij.openapi.compiler.CompilerManager;
+import com.intellij.openapi.components.AbstractProjectComponent;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.registry.RegistryValue;
+import com.intellij.openapi.util.registry.RegistryValueListener;
+import com.intellij.util.Consumer;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.indexing.IndexInfrastructure;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.PersistentEnumeratorDelegate;
+import com.intellij.util.io.PersistentHashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
+import org.jetbrains.asm4.ClassReader;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class CompilerOutputIndexer extends AbstractProjectComponent {
+ private final static Logger LOG = Logger.getInstance(CompilerOutputIndexer.class);
+
+ public final static String REGISTRY_KEY = "completion.enable.relevant.method.chain.suggestions";
+ public final static String TITLE = "Compiler output indexer in progress...";
+
+ private volatile CompilerOutputBaseIndex[] myIndexes;
+ private volatile Map<String, CompilerOutputBaseIndex> myIndexTypeQNameToIndex;
+ private volatile PersistentHashMap<String, Long> myFileTimestampsIndex;
+ private volatile PersistentEnumeratorDelegate<String> myFileEnumerator;
+ private volatile boolean myInitialized = false;
+
+ private final Lock myLock = new ReentrantLock();
+ private final AtomicBoolean myInProgress = new AtomicBoolean(false);
+ private AtomicBoolean myEnabled = new AtomicBoolean(false);
+
+ public static CompilerOutputIndexer getInstance(final Project project) {
+ return project.getComponent(CompilerOutputIndexer.class);
+ }
+
+ protected CompilerOutputIndexer(final Project project) {
+ super(project);
+ }
+
+ public boolean isEnabled() {
+ return myEnabled.get();
+ }
+
+ private ID<String, Long> getFileTimestampsIndexId() {
+ return CompilerOutputIndexUtil.generateIndexId("ProjectCompilerOutputClassFilesTimestamps", myProject);
+ }
+
+ @Override
+ public final void projectOpened() {
+ Registry.get(REGISTRY_KEY).addListener(new RegistryValueListener.Adapter() {
+ @Override
+ public void afterValueChanged(final RegistryValue value) {
+ myEnabled.set(value.asBoolean());
+ if (myEnabled.get()) {
+ doEnable();
+ }
+ }
+ }, myProject);
+
+ myEnabled = new AtomicBoolean(Registry.is(REGISTRY_KEY) || ApplicationManager.getApplication().isUnitTestMode());
+ if (myEnabled.get()) {
+ doEnable();
+ }
+ }
+
+ private void doEnable() {
+ if (!myInitialized) {
+ myIndexes = Extensions.getExtensions(CompilerOutputBaseIndex.EXTENSION_POINT_NAME, myProject);
+ myIndexTypeQNameToIndex = new HashMap<String, CompilerOutputBaseIndex>();
+ boolean needReindex = false;
+ for (final CompilerOutputBaseIndex index : myIndexes) {
+ if (index.init(myProject)) {
+ needReindex = true;
+ }
+ myIndexTypeQNameToIndex.put(index.getClass().getCanonicalName(), index);
+ }
+ initTimestampIndex(needReindex);
+ try {
+ myFileEnumerator = new PersistentEnumeratorDelegate<String>(
+ IndexInfrastructure.getStorageFile(CompilerOutputIndexUtil.generateIndexId("compilerOutputIndexFileId.enum", myProject)),
+ new EnumeratorStringDescriptor(), 2048);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ CompilerManager.getInstance(myProject).addAfterTask(new CompileTask() {
+ @Override
+ public boolean execute(final CompileContext context) {
+ if (myEnabled.get() && myInProgress.compareAndSet(false, true)) {
+ myLock.lock();
+ try {
+ context.getProgressIndicator().setText("Compiler output indexing in progress");
+ final Consumer<File> fileConsumer = new Consumer<File>() {
+ @Override
+ public void consume(final File file) {
+ try {
+ doIndexing(file, context.getProgressIndicator());
+ }
+ catch (ProcessCanceledException e0) {
+ throw e0;
+ }
+ catch (RuntimeException e) {
+ LOG.error(e);
+ }
+ }
+ };
+ for (final Module module : context.getCompileScope().getAffectedModules()) {
+ CompilerOutputFilesUtil.iterateModuleClassFiles(module, fileConsumer);
+ }
+ }
+ finally {
+ myLock.unlock();
+ myInProgress.set(false);
+ }
+ }
+ return true;
+ }
+ });
+ if (needReindex) {
+ reindexAllProjectInBackground();
+ }
+ myInitialized = true;
+ }
+ }
+
+ private void initTimestampIndex(final boolean needReindex) {
+ if (needReindex) {
+ FileUtil.delete(IndexInfrastructure.getIndexRootDir(getFileTimestampsIndexId()));
+ }
+ for (int attempts = 0; attempts < 2; attempts++) {
+ try {
+ myFileTimestampsIndex = new PersistentHashMap<String, Long>(IndexInfrastructure.getStorageFile(getFileTimestampsIndexId()),
+ new EnumeratorStringDescriptor(), new DataExternalizer<Long>() {
+ @Override
+ public void save(final DataOutput out, final Long value) throws IOException {
+ out.writeLong(value);
+ }
+
+ @Override
+ public Long read(final DataInput in) throws IOException {
+ return in.readLong();
+ }
+ });
+ }
+ catch (IOException e) {
+ FileUtil.delete(IndexInfrastructure.getIndexRootDir(getFileTimestampsIndexId()));
+ }
+ if (myFileTimestampsIndex != null) {
+ return;
+ }
+ }
+ throw new RuntimeException("Timestamps index not initialized");
+ }
+
+
+ public void reindex(final FileVisitorService visitorService, @NotNull final ProgressIndicator indicator) {
+ myLock.lock();
+ try {
+ indicator.setText(TITLE);
+ visitorService.visit(new Consumer<File>() {
+ @Override
+ public void consume(final File file) {
+ try {
+ doIndexing(file, indicator);
+ }
+ catch (ProcessCanceledException e0) {
+ throw e0;
+ }
+ catch (RuntimeException e) {
+ LOG.error(e);
+ }
+ }
+ });
+ }
+ finally {
+ myLock.unlock();
+ }
+ }
+
+ public void reindexAllProjectInBackground() {
+ if (myInProgress.compareAndSet(false, true)) {
+ ProgressManager.getInstance().run(new Task.Backgroundable(myProject, TITLE) {
+
+ @Override
+ public void onCancel() {
+ myIndexTypeQNameToIndex.clear();
+ myInProgress.set(false);
+ }
+
+ @Override
+ public void onSuccess() {
+ myInProgress.set(false);
+ }
+
+ @Override
+ public void run(@NotNull final ProgressIndicator indicator) {
+ reindexAllProject(indicator);
+ }
+ });
+ }
+ }
+
+ public void reindexAllProject(@NotNull final ProgressIndicator indicator) {
+ reindex(new FileVisitorService.ProjectClassFiles(myProject), indicator);
+ }
+
+ @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
+ private void doIndexing(@NotNull final File file, @NotNull final ProgressIndicator indicator) {
+ final String filePath;
+ try {
+ filePath = file.getCanonicalPath();
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ return;
+ }
+ final Long timestamp = getTimestamp(filePath);
+ ProgressManager.checkCanceled();
+ final long currentTimeStamp = file.lastModified();
+ if (timestamp == null || timestamp != currentTimeStamp) {
+ putTimestamp(filePath, currentTimeStamp);
+ final ClassReader reader;
+ InputStream is = null;
+ try {
+ is = new FileInputStream(file);
+ reader = new ClassReader(is);
+ }
+ catch (IOException e) {
+ removeTimestamp(filePath);
+ return;
+ }
+ finally {
+ if (is != null) {
+ try {
+ is.close();
+ }
+ catch (IOException ignored) {
+ }
+ }
+ }
+ try {
+ indicator.setText2(filePath);
+ final int id = myFileEnumerator.enumerate(filePath);
+ for (final CompilerOutputBaseIndex index : myIndexes) {
+ index.update(id, reader);
+ }
+ }
+ catch (RuntimeException e) {
+ LOG.error(String.format("can't index file: %s", file.getAbsolutePath()), e);
+ }
+ catch (IOException e) {
+ LOG.error(String.format("can't index file: %s", file.getAbsolutePath()), e);
+ }
+ }
+ }
+
+ public void clear() {
+ try {
+ myFileTimestampsIndex.close();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ initTimestampIndex(true);
+ for (final CompilerOutputBaseIndex index : myIndexes) {
+ index.clear();
+ }
+ }
+
+ private void removeTimestamp(final String fileId) {
+ try {
+ myFileTimestampsIndex.remove(fileId);
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ }
+
+ @Nullable
+ private Long getTimestamp(final String fileName) {
+ try {
+ return myFileTimestampsIndex.get(fileName);
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ return 0L;
+ }
+ }
+
+ private void putTimestamp(final String fileName, final long timestamp) {
+ try {
+ myFileTimestampsIndex.put(fileName, timestamp);
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ }
+
+
+ @Override
+ public void projectClosed() {
+ if (myInitialized) {
+ for (final CompilerOutputBaseIndex index : myIndexes) {
+ index.projectClosed();
+ }
+ try {
+ myFileTimestampsIndex.close();
+ myFileEnumerator.close();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @TestOnly
+ public void removeIndexes() {
+ for (final CompilerOutputBaseIndex index : myIndexes) {
+ FileUtil.delete(IndexInfrastructure.getIndexRootDir(index.getIndexId()));
+ }
+ FileUtil.delete(IndexInfrastructure.getIndexRootDir(getFileTimestampsIndexId()));
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T extends CompilerOutputBaseIndex> T getIndex(final Class<T> tClass) {
+ final CompilerOutputBaseIndex index = myIndexTypeQNameToIndex.get(tClass.getCanonicalName());
+ if (index == null) {
+ throw new RuntimeException(String.format("index class with name %s not found", tClass.getName()));
+ }
+ return (T)index;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/ClassFileData.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/ClassFileData.java
new file mode 100644
index 000000000000..f0a7c27d0be6
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/ClassFileData.java
@@ -0,0 +1,116 @@
+package com.intellij.compilerOutputIndex.impl;
+
+import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.ClassVisitor;
+import org.jetbrains.asm4.MethodVisitor;
+import org.jetbrains.asm4.Opcodes;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class ClassFileData {
+ private final List<MethodData> myMethodDatas;
+
+ public ClassFileData(final ClassReader classReader) {
+ this(classReader, true);
+ }
+
+ public ClassFileData(final ClassReader classReader, final boolean checkForPrimitiveReturn) {
+ myMethodDatas = new ArrayList<MethodData>();
+ classReader.accept(new ClassVisitor(Opcodes.ASM4) {
+ @Override
+ public MethodVisitor visitMethod(final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions) {
+ final MethodDataAccumulator methodDataAccumulator = new MethodDataAccumulator(checkForPrimitiveReturn);
+ myMethodDatas.add(methodDataAccumulator.getMethodData());
+ return methodDataAccumulator;
+ }
+ }, Opcodes.ASM4);
+ }
+
+ public List<MethodData> getMethodDatas() {
+ return myMethodDatas;
+ }
+
+ public static class MethodData {
+ private final List<MethodInsnSignature> myMethodInsnSignatures = new ArrayList<MethodInsnSignature>();
+
+ private void addSign(final MethodInsnSignature signature) {
+ myMethodInsnSignatures.add(signature);
+ }
+
+ public List<MethodInsnSignature> getMethodInsnSignatures() {
+ return myMethodInsnSignatures;
+ }
+ }
+
+ private static class MethodDataAccumulator extends MethodVisitor {
+ private final MethodData myMethodData = new MethodData();
+ private final boolean myCheckForPrimitiveReturn;
+
+ public MethodDataAccumulator(final boolean checkForPrimitiveReturn) {
+ super(Opcodes.ASM4);
+ myCheckForPrimitiveReturn = checkForPrimitiveReturn;
+ }
+
+ private MethodData getMethodData() {
+ return myMethodData;
+ }
+
+ @Override
+ public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
+ if (MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(name)) {
+ return;
+ }
+ final String ownerClassName = AsmUtil.getQualifiedClassName(owner);
+ if (ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(ownerClassName)) {
+ return;
+ }
+ if (myCheckForPrimitiveReturn) {
+ final String returnType = AsmUtil.getReturnType(desc);
+ if (ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(returnType)) {
+ return;
+ }
+ }
+ myMethodData.addSign(new MethodInsnSignature(opcode, owner, name, desc));
+ }
+ }
+
+ public static class MethodInsnSignature {
+ private final int myOpcode;
+ private final String myOwner;
+ private final String myName;
+ private final String myDesc;
+
+ private MethodInsnSignature(final int opcode, final String owner, final String name, final String desc) {
+ myOpcode = opcode;
+ myOwner = owner;
+ myName = name;
+ myDesc = desc;
+ }
+
+ public int getOpcode() {
+ return myOpcode;
+ }
+
+ public String getOwner() {
+ return myOwner;
+ }
+
+ public String getName() {
+ return myName;
+ }
+
+ public String getDesc() {
+ return myDesc;
+ }
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/CompilerOutputBaseGramsIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/CompilerOutputBaseGramsIndex.java
new file mode 100644
index 000000000000..b1afc8395951
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/CompilerOutputBaseGramsIndex.java
@@ -0,0 +1,47 @@
+package com.intellij.compilerOutputIndex.impl;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
+import com.intellij.util.indexing.StorageException;
+import com.intellij.util.indexing.ValueContainer;
+import com.intellij.util.io.KeyDescriptor;
+
+import java.util.TreeSet;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public abstract class CompilerOutputBaseGramsIndex<K> extends CompilerOutputBaseIndex<K, Multiset<MethodIncompleteSignature>> {
+
+ protected CompilerOutputBaseGramsIndex(final KeyDescriptor<K> keyDescriptor) {
+ super(keyDescriptor, new GuavaHashMultiSetExternalizer<MethodIncompleteSignature>(MethodIncompleteSignature.createKeyDescriptor()));
+ }
+
+ public TreeSet<UsageIndexValue> getValues(final K key) {
+ try {
+ final ValueContainer<Multiset<MethodIncompleteSignature>> valueContainer = myIndex.getData(key);
+ final Multiset<MethodIncompleteSignature> rawValues = HashMultiset.create();
+ valueContainer.forEach(new ValueContainer.ContainerAction<Multiset<MethodIncompleteSignature>>() {
+ @Override
+ public boolean perform(final int id, final Multiset<MethodIncompleteSignature> values) {
+ for (final Multiset.Entry<MethodIncompleteSignature> entry : values.entrySet()) {
+ rawValues.add(entry.getElement(), entry.getCount());
+ }
+ return true;
+ }
+ });
+ return rawValuesToValues(rawValues);
+ } catch (StorageException e) {
+ throw new RuntimeException();
+ }
+ }
+
+ private static TreeSet<UsageIndexValue> rawValuesToValues(final Multiset<MethodIncompleteSignature> rawValues) {
+ final TreeSet<UsageIndexValue> values = new TreeSet<UsageIndexValue>();
+ for (final Multiset.Entry<MethodIncompleteSignature> entry : rawValues.entrySet()) {
+ values.add(new UsageIndexValue(entry.getElement(), entry.getCount()));
+ }
+ return values;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/GuavaHashMultiSetExternalizer.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/GuavaHashMultiSetExternalizer.java
new file mode 100644
index 000000000000..fe36071af30a
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/GuavaHashMultiSetExternalizer.java
@@ -0,0 +1,56 @@
+/*
+ * 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.compilerOutputIndex.impl;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.intellij.util.io.DataExternalizer;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class GuavaHashMultiSetExternalizer<K> implements DataExternalizer<Multiset<K>> {
+ private final DataExternalizer<K> myKeyDataExternalizer;
+
+ public GuavaHashMultiSetExternalizer(final DataExternalizer<K> keyDataExternalizer) {
+ myKeyDataExternalizer = keyDataExternalizer;
+ }
+
+ @Override
+ public void save(final DataOutput out, final Multiset<K> multiset) throws IOException {
+ final Set<Multiset.Entry<K>> entries = multiset.entrySet();
+ out.writeInt(entries.size());
+ for (final Multiset.Entry<K> entry : entries) {
+ myKeyDataExternalizer.save(out, entry.getElement());
+ out.writeInt(entry.getCount());
+ }
+ }
+
+ @Override
+ public Multiset<K> read(final DataInput in) throws IOException {
+ final int size = in.readInt();
+ final Multiset<K> multiset = HashMultiset.create(size);
+ for (int i = 0; i < size; i++) {
+ multiset.add(myKeyDataExternalizer.read(in), in.readInt());
+ }
+ return multiset;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignature.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignature.java
new file mode 100644
index 000000000000..ad85322f3f6a
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignature.java
@@ -0,0 +1,183 @@
+package com.intellij.compilerOutputIndex.impl;
+
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class MethodIncompleteSignature {
+
+ public static final String CONSTRUCTOR_METHOD_NAME = "<init>";
+
+ @NotNull
+ private final String myOwner;
+ @NotNull
+ private final String myReturnType;
+ @NotNull
+ private final String myName;
+ private final boolean myStatic;
+
+ public MethodIncompleteSignature(@NotNull final String owner,
+ @NotNull final String returnType,
+ @NotNull final String name,
+ final boolean aStatic) {
+ myOwner = owner;
+ myReturnType = returnType;
+ myName = name;
+ myStatic = aStatic;
+ }
+
+ public static MethodIncompleteSignature constructor(@NotNull final String className) {
+ return new MethodIncompleteSignature(className, className, CONSTRUCTOR_METHOD_NAME, true);
+ }
+
+ @NotNull
+ public String getOwner() {
+ return myOwner;
+ }
+
+ @NotNull
+ public String getReturnType() {
+ return myReturnType;
+ }
+
+ @NotNull
+ public String getName() {
+ return myName;
+ }
+
+ public boolean isStatic() {
+ return myStatic;
+ }
+
+ @NotNull
+ public PsiMethod[] resolveNotDeprecated(final JavaPsiFacade javaPsiFacade, final GlobalSearchScope scope) {
+ return notDeprecated(resolve(javaPsiFacade, scope));
+ }
+
+ @NotNull
+ public PsiMethod[] resolve(final JavaPsiFacade javaPsiFacade, final GlobalSearchScope scope) {
+ if (CONSTRUCTOR_METHOD_NAME.equals(getName())) {
+ return PsiMethod.EMPTY_ARRAY;
+ }
+ final PsiClass aClass = javaPsiFacade.findClass(getOwner(), scope);
+ if (aClass == null) {
+ return PsiMethod.EMPTY_ARRAY;
+ }
+ final PsiMethod[] methods = aClass.findMethodsByName(getName(), true);
+ final List<PsiMethod> filtered = new ArrayList<PsiMethod>(methods.length);
+ for (final PsiMethod method : methods) {
+ if (method.hasModifierProperty(PsiModifier.STATIC) == isStatic()) {
+ final PsiType returnType = method.getReturnType();
+ if (returnType != null && returnType.equalsToText(getReturnType())) {
+ filtered.add(method);
+ }
+ }
+ }
+ return filtered.toArray(new PsiMethod[filtered.size()]);
+ }
+
+ public static KeyDescriptor<MethodIncompleteSignature> createKeyDescriptor() {
+ final EnumeratorStringDescriptor stringDescriptor = new EnumeratorStringDescriptor();
+ return new KeyDescriptor<MethodIncompleteSignature>() {
+ @Override
+ public void save(final DataOutput out, final MethodIncompleteSignature value) throws IOException {
+ stringDescriptor.save(out, value.getOwner());
+ stringDescriptor.save(out, value.getReturnType());
+ stringDescriptor.save(out, value.getName());
+ out.writeBoolean(value.isStatic());
+ }
+
+ @Override
+ public MethodIncompleteSignature read(final DataInput in) throws IOException {
+ return new MethodIncompleteSignature(stringDescriptor.read(in), stringDescriptor.read(in), stringDescriptor.read(in),
+ in.readBoolean());
+ }
+
+ @Override
+ public int getHashCode(final MethodIncompleteSignature value) {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean isEqual(final MethodIncompleteSignature val1, final MethodIncompleteSignature val2) {
+ return val1.equals(val2);
+ }
+ };
+ }
+
+ @NotNull
+ private static PsiMethod[] notDeprecated(@NotNull final PsiMethod[] methods) {
+ final List<PsiMethod> filtered = ContainerUtil.filter(methods, NOT_DEPRECATED_CONDITION);
+ return filtered.toArray(new PsiMethod[filtered.size()]);
+ }
+
+ private final static Condition<PsiMethod> NOT_DEPRECATED_CONDITION = new Condition<PsiMethod>() {
+ @Override
+ public boolean value(final PsiMethod method) {
+ return !method.isDeprecated();
+ }
+ };
+
+ public final static Comparator<MethodIncompleteSignature> COMPARATOR = new Comparator<MethodIncompleteSignature>() {
+ @Override
+ public int compare(final MethodIncompleteSignature o1, final MethodIncompleteSignature o2) {
+ int sub = o1.getOwner().compareTo(o2.getOwner());
+ if (sub != 0) {
+ return sub;
+ }
+ sub = o1.getName().compareTo(o2.getName());
+ if (sub != 0) {
+ return sub;
+ }
+ sub = o1.getReturnType().compareTo(o2.getReturnType());
+ if (sub != 0) {
+ return sub;
+ }
+ if (o1.isStatic() && !o2.isStatic()) {
+ return 1;
+ }
+ if (o2.isStatic() && !o1.isStatic()) {
+ return -1;
+ }
+ return 0;
+ }
+ };
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final MethodIncompleteSignature that = (MethodIncompleteSignature)o;
+
+ if (myStatic != that.myStatic) return false;
+ if (!myName.equals(that.myName)) return false;
+ if (!myOwner.equals(that.myOwner)) return false;
+ if (!myReturnType.equals(that.myReturnType)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myOwner.hashCode();
+ result = 31 * result + myReturnType.hashCode();
+ result = 31 * result + myName.hashCode();
+ result = 31 * result + (myStatic ? 1 : 0);
+ return result;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignatureChain.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignatureChain.java
new file mode 100644
index 000000000000..a11e731f3d34
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignatureChain.java
@@ -0,0 +1,44 @@
+package com.intellij.compilerOutputIndex.impl;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class MethodIncompleteSignatureChain {
+ private final List<MethodIncompleteSignature> myMethodIncompleteSignatures;
+
+ public MethodIncompleteSignatureChain(final List<MethodIncompleteSignature> methodIncompleteSignatures) {
+ myMethodIncompleteSignatures = methodIncompleteSignatures;
+ }
+
+ public List<MethodIncompleteSignature> list() {
+ return myMethodIncompleteSignatures;
+ }
+
+ public boolean isEmpty() {
+ return myMethodIncompleteSignatures.isEmpty();
+ }
+
+ @Nullable
+ public MethodIncompleteSignature getFirstInvocation() {
+ final int size = myMethodIncompleteSignatures.size();
+ return size == 0 ? null : myMethodIncompleteSignatures.get(0);
+ }
+
+ @Nullable
+ public MethodIncompleteSignature getLastInvocation() {
+ final int size = myMethodIncompleteSignatures.size();
+ return size == 0 ? null : myMethodIncompleteSignatures.get(size -1);
+ }
+
+ public int size() {
+ return myMethodIncompleteSignatures.size();
+ }
+
+ public MethodIncompleteSignature get(final int index) {
+ return myMethodIncompleteSignatures.get(index);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodsUsageIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodsUsageIndex.java
new file mode 100644
index 000000000000..e07c0380ad9e
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodsUsageIndex.java
@@ -0,0 +1,91 @@
+package com.intellij.compilerOutputIndex.impl;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.indexing.StorageException;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.Opcodes;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class MethodsUsageIndex extends CompilerOutputBaseGramsIndex<String> {
+
+ public static MethodsUsageIndex getInstance(final Project project) {
+ return CompilerOutputIndexer.getInstance(project).getIndex(MethodsUsageIndex.class);
+ }
+
+ public MethodsUsageIndex() {
+ super(new EnumeratorStringDescriptor());
+ }
+
+ @Override
+ protected DataIndexer<String, Multiset<MethodIncompleteSignature>, ClassReader> getIndexer() {
+ return new DataIndexer<String, Multiset<MethodIncompleteSignature>, ClassReader>() {
+ @NotNull
+ @Override
+ public Map<String, Multiset<MethodIncompleteSignature>> map(final ClassReader inputData) {
+ final Map<String, Multiset<MethodIncompleteSignature>> map = new HashMap<String, Multiset<MethodIncompleteSignature>>();
+ for (final ClassFileData.MethodData data : new ClassFileData(inputData).getMethodDatas()) {
+ for (final ClassFileData.MethodInsnSignature ms : data.getMethodInsnSignatures()) {
+ final String ownerClassName = AsmUtil.getQualifiedClassName(ms.getOwner());
+ final String returnType = AsmUtil.getReturnType(ms.getDesc());
+ if (MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(ms.getName())) {
+ addToIndex(map, ownerClassName, MethodIncompleteSignature.constructor(ownerClassName));
+ }
+ else {
+ final boolean isStatic = ms.getOpcode() == Opcodes.INVOKESTATIC;
+ if (!ownerClassName.equals(returnType) || isStatic) {
+ addToIndex(map, returnType, new MethodIncompleteSignature(ownerClassName, returnType, ms.getName(), isStatic));
+ }
+ }
+ }
+ }
+ return map;
+ }
+
+
+ };
+ }
+
+ public void clear() {
+ try {
+ myIndex.clear();
+ }
+ catch (StorageException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected ID<String, Multiset<MethodIncompleteSignature>> getIndexId() {
+ return generateIndexId(MethodsUsageIndex.class);
+ }
+
+ @Override
+ protected int getVersion() {
+ return 0;
+ }
+
+ private static void addToIndex(final Map<String, Multiset<MethodIncompleteSignature>> map,
+ final String key,
+ final MethodIncompleteSignature mi) {
+ Multiset<MethodIncompleteSignature> occurrences = map.get(key);
+ if (occurrences == null) {
+ occurrences = HashMultiset.create();
+ map.put(key, occurrences);
+ }
+ occurrences.add(mi);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/UsageIndexValue.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/UsageIndexValue.java
new file mode 100644
index 000000000000..f99a0dea18c6
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/UsageIndexValue.java
@@ -0,0 +1,69 @@
+package com.intellij.compilerOutputIndex.impl;
+
+import com.intellij.util.io.DataExternalizer;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class UsageIndexValue implements Comparable<UsageIndexValue> {
+ private final int myOccurrences;
+ private final MethodIncompleteSignature myMethodIncompleteSignature;
+
+ public UsageIndexValue(final MethodIncompleteSignature signature, final int occurrences) {
+ myOccurrences = occurrences;
+ myMethodIncompleteSignature = signature;
+ }
+
+ public int getOccurrences() {
+ return myOccurrences;
+ }
+
+ public MethodIncompleteSignature getMethodIncompleteSignature() {
+ return myMethodIncompleteSignature;
+ }
+
+ public static DataExternalizer<UsageIndexValue> createDataExternalizer() {
+ final DataExternalizer<MethodIncompleteSignature> methodInvocationDataExternalizer = MethodIncompleteSignature.createKeyDescriptor();
+ return new DataExternalizer<UsageIndexValue>() {
+ @Override
+ public void save(final DataOutput out, final UsageIndexValue value) throws IOException {
+ methodInvocationDataExternalizer.save(out, value.myMethodIncompleteSignature);
+ out.writeInt(value.myOccurrences);
+ }
+
+ @Override
+ public UsageIndexValue read(final DataInput in) throws IOException {
+ return new UsageIndexValue(methodInvocationDataExternalizer.read(in), in.readInt());
+ }
+ };
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final UsageIndexValue that = (UsageIndexValue)o;
+
+ return myOccurrences == that.myOccurrences && myMethodIncompleteSignature.equals(that.myMethodIncompleteSignature);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myOccurrences;
+ result = 31 * result + myMethodIncompleteSignature.hashCode();
+ return result;
+ }
+
+ @Override
+ public int compareTo(@NotNull final UsageIndexValue that) {
+ final int sub = -myOccurrences + that.myOccurrences;
+ if (sub != 0) return sub;
+ return MethodIncompleteSignature.COMPARATOR.compare(myMethodIncompleteSignature, that.myMethodIncompleteSignature);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/Bigram.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/Bigram.java
new file mode 100644
index 000000000000..f5f4ff87a095
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/Bigram.java
@@ -0,0 +1,22 @@
+package com.intellij.compilerOutputIndex.impl.bigram;
+
+import com.intellij.openapi.util.Pair;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class Bigram<E> extends Pair<E, E> {
+ public Bigram(@NotNull final E first, @NotNull final E second) {
+ super(first, second);
+ }
+
+ public Bigram<E> swap() {
+ return new Bigram<E>(second, first);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s - %s", first, second);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/BigramMethodsUsageIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/BigramMethodsUsageIndex.java
new file mode 100644
index 000000000000..1f4d7e2cf6e6
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/BigramMethodsUsageIndex.java
@@ -0,0 +1,86 @@
+package com.intellij.compilerOutputIndex.impl.bigram;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.compilerOutputIndex.impl.ClassFileData;
+import com.intellij.compilerOutputIndex.impl.CompilerOutputBaseGramsIndex;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignatureChain;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.SmartList;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.ID;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.Opcodes;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class BigramMethodsUsageIndex extends CompilerOutputBaseGramsIndex<MethodIncompleteSignature> {
+ public static BigramMethodsUsageIndex getInstance(final Project project) {
+ return CompilerOutputIndexer.getInstance(project).getIndex(BigramMethodsUsageIndex.class);
+ }
+
+ public BigramMethodsUsageIndex() {
+ super(MethodIncompleteSignature.createKeyDescriptor());
+ }
+
+ @Override
+ protected ID<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>> getIndexId() {
+ return generateIndexId(BigramMethodsUsageIndex.class);
+ }
+
+ @Override
+ protected int getVersion() {
+ return 0;
+ }
+
+ @Override
+ protected DataIndexer<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>, ClassReader> getIndexer() {
+ //
+ // not fair way, but works fast
+ //
+ return new DataIndexer<MethodIncompleteSignature,Multiset<MethodIncompleteSignature>,ClassReader>() {
+ @NotNull
+ @Override
+ public Map<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>> map(final ClassReader inputData) {
+ final Map<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>> map =
+ new HashMap<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>>();
+ for (final ClassFileData.MethodData data : new ClassFileData(inputData).getMethodDatas()) {
+ final SimpleBigramsExtractor extractor = new SimpleBigramsExtractor(new SimpleBigramsExtractor.BigramMethodIncompleteSignatureProcessor() {
+ @Override
+ public void process(final Bigram<MethodIncompleteSignature> bigram) {
+ final MethodIncompleteSignature secondGram = bigram.getSecond();
+ Multiset<MethodIncompleteSignature> occurrences = map.get(secondGram);
+ if (occurrences == null) {
+ occurrences = HashMultiset.create();
+ map.put(secondGram, occurrences);
+ }
+ occurrences.add(bigram.getFirst());
+ }
+ });
+ for (final ClassFileData.MethodInsnSignature ms : data.getMethodInsnSignatures()) {
+ final List<MethodIncompleteSignature> methodInvocations = new SmartList<MethodIncompleteSignature>();
+ final String ownerClassName = AsmUtil.getQualifiedClassName(ms.getOwner());
+ final String returnType = AsmUtil.getReturnType(ms.getDesc());
+
+ if (ms.getName().equals(MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME)) {
+ methodInvocations.add(MethodIncompleteSignature.constructor(ownerClassName));
+ }
+ else {
+ methodInvocations.add(new MethodIncompleteSignature(ownerClassName, returnType, ms.getName(), ms.getOpcode() == Opcodes.INVOKESTATIC));
+ }
+ extractor.addChain(new MethodIncompleteSignatureChain(methodInvocations));
+ }
+ }
+ return map;
+ }
+ };
+ }
+
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/SimpleBigramsExtractor.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/SimpleBigramsExtractor.java
new file mode 100644
index 000000000000..d231a07e0f18
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/bigram/SimpleBigramsExtractor.java
@@ -0,0 +1,55 @@
+package com.intellij.compilerOutputIndex.impl.bigram;
+
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignatureChain;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+* @author Dmitry Batkovich
+*/
+class SimpleBigramsExtractor {
+ private final Map<String, MethodIncompleteSignature> myHolder = new HashMap<String, MethodIncompleteSignature>();
+ private final BigramMethodIncompleteSignatureProcessor myProcessor;
+
+ public SimpleBigramsExtractor(final BigramMethodIncompleteSignatureProcessor processor) {
+ myProcessor = processor;
+ }
+
+ public void addChain(final MethodIncompleteSignatureChain chain) {
+ if (chain.isEmpty()) {
+ return;
+ }
+ final MethodIncompleteSignature firstInvocation = chain.getFirstInvocation();
+ assert firstInvocation != null;
+ final MethodIncompleteSignature head = firstInvocation.isStatic() ? null : myHolder.get(firstInvocation.getOwner());
+ for (final Bigram<MethodIncompleteSignature> bigram : toBigrams(head, chain)) {
+ myProcessor.process(bigram);
+ }
+ final MethodIncompleteSignature lastInvocation = chain.getLastInvocation();
+ assert lastInvocation != null;
+ myHolder.put(lastInvocation.getReturnType(), lastInvocation);
+ }
+
+ private static Collection<Bigram<MethodIncompleteSignature>> toBigrams(final @Nullable MethodIncompleteSignature head,
+ final @NotNull MethodIncompleteSignatureChain chain) {
+ MethodIncompleteSignature currentLast = null;
+ if (head != null) {
+ currentLast = head;
+ }
+ final List<Bigram<MethodIncompleteSignature>> bigrams = new ArrayList<Bigram<MethodIncompleteSignature>>(chain.size());
+ for (final MethodIncompleteSignature current : chain.list()) {
+ if (currentLast != null) {
+ bigrams.add(new Bigram<MethodIncompleteSignature>(currentLast, current));
+ }
+ currentLast = current;
+ }
+ return bigrams;
+ }
+
+ public interface BigramMethodIncompleteSignatureProcessor {
+ void process(Bigram<MethodIncompleteSignature> bigram);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/CallingLocation.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/CallingLocation.java
new file mode 100644
index 000000000000..b2a154121737
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/CallingLocation.java
@@ -0,0 +1,71 @@
+package com.intellij.compilerOutputIndex.impl.callingLocation;
+
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class CallingLocation {
+ @NotNull
+ private final MethodIncompleteSignature myMethodIncompleteSignature;
+ @NotNull
+ private final VariableType myVariableType;
+
+ public CallingLocation(@NotNull final MethodIncompleteSignature methodIncompleteSignature, @NotNull final VariableType variableType) {
+ myMethodIncompleteSignature = methodIncompleteSignature;
+ myVariableType = variableType;
+ }
+
+ @NotNull
+ public MethodIncompleteSignature getMethodIncompleteSignature() {
+ return myMethodIncompleteSignature;
+ }
+
+ @NotNull
+ public VariableType getVariableType() {
+ return myVariableType;
+ }
+
+ public static DataExternalizer<CallingLocation> createDataExternalizer() {
+ final KeyDescriptor<MethodIncompleteSignature> methodIncompleteSignatureKeyDescriptor = MethodIncompleteSignature.createKeyDescriptor();
+ return new DataExternalizer<CallingLocation>() {
+ @Override
+ public void save(final DataOutput out, final CallingLocation value) throws IOException {
+ methodIncompleteSignatureKeyDescriptor.save(out, value.getMethodIncompleteSignature());
+ VariableType.KEY_DESCRIPTOR.save(out, value.getVariableType());
+ }
+
+ @Override
+ public CallingLocation read(final DataInput in) throws IOException {
+ return new CallingLocation(methodIncompleteSignatureKeyDescriptor.read(in), VariableType.KEY_DESCRIPTOR.read(in));
+ }
+ };
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final CallingLocation that = (CallingLocation)o;
+
+ if (!myMethodIncompleteSignature.equals(that.myMethodIncompleteSignature)) return false;
+ if (myVariableType != that.myVariableType) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myMethodIncompleteSignature.hashCode();
+ result = 31 * result + myVariableType.hashCode();
+ return result;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodCallingLocationExtractor.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodCallingLocationExtractor.java
new file mode 100644
index 000000000000..f5cdadb6d170
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodCallingLocationExtractor.java
@@ -0,0 +1,157 @@
+package com.intellij.compilerOutputIndex.impl.callingLocation;
+
+import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.*;
+import org.jetbrains.asm4.commons.AnalyzerAdapter;
+import org.jetbrains.asm4.commons.JSRInlinerAdapter;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class MethodCallingLocationExtractor {
+ private MethodCallingLocationExtractor() {
+ }
+
+ public static Map<MethodNameAndQualifier, List<CallingLocation>> extract(final ClassReader classReader) {
+ final MyClassVisitor classVisitor = new MyClassVisitor();
+ classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES);
+ return classVisitor.getExtractedMethodsCallings();
+ }
+
+ private static class MyClassVisitor extends ClassVisitor {
+ public MyClassVisitor() {
+ super(Opcodes.ASM4);
+ }
+
+ private final Map<MethodNameAndQualifier, List<CallingLocation>> myExtractedMethodsCallings =
+ new HashMap<MethodNameAndQualifier, List<CallingLocation>>();
+
+ private String myClassName;
+ private String myRawClassName;
+
+ private Map<MethodNameAndQualifier, List<CallingLocation>> getExtractedMethodsCallings() {
+ return myExtractedMethodsCallings;
+ }
+
+ @Override
+ public void visit(final int version,
+ final int access,
+ final String className,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ myRawClassName = className;
+ myClassName = AsmUtil.getQualifiedClassName(className);
+ }
+
+ @Nullable
+ @Override
+ public FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public MethodVisitor visitMethod(final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions) {
+
+ if (name.charAt(0) == '<') {
+ return null;
+ }
+ final boolean isStaticMethod = AsmUtil.isStaticMethodDeclaration(access);
+ if (isStaticMethod) {
+ return null;
+ }
+ @SuppressWarnings("UnnecessaryLocalVariable") final String methodName = name;
+ final String[] methodParams = AsmUtil.getParamsTypes(desc);
+ final MethodIncompleteSignature currentMethodSignature =
+ new MethodIncompleteSignature(myClassName, AsmUtil.getReturnType(desc), methodName, isStaticMethod);
+ return new JSRInlinerAdapter(new AnalyzerAdapter(Opcodes.ASM4, myRawClassName, access, name, desc, null) {
+ private final Map<Integer, Variable> myFieldsAndParamsPositionInStack = new HashMap<Integer, Variable>();
+
+ @Override
+ public void visitInsn(final int opcode) {
+ super.visitInsn(opcode);
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) {
+ boolean onThis = false;
+ if (stack != null && opcode == Opcodes.GETFIELD && !ChainCompletionStringUtil.isPrimitiveOrArray(AsmUtil.getReturnType(desc))) {
+ final Object objectRef = stack.get(stack.size() - 1);
+ if (objectRef instanceof String && objectRef.equals(myRawClassName)) {
+ onThis = true;
+ }
+ }
+ super.visitFieldInsn(opcode, owner, name, desc);
+ if (onThis) {
+ final int index = stack.size() - 1;
+ final Object marker = stack.get(index);
+ myFieldsAndParamsPositionInStack.put(index, new Variable(marker, VariableType.FIELD));
+ }
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int varIndex) {
+ super.visitVarInsn(opcode, varIndex);
+ if (stack != null && opcode == Opcodes.ALOAD &&
+ varIndex > 0 &&
+ varIndex <= methodParams.length &&
+ !ChainCompletionStringUtil.isPrimitiveOrArray(methodParams[varIndex - 1])) {
+ final int stackPos = stack.size() - 1;
+ myFieldsAndParamsPositionInStack.put(stackPos, new Variable(stack.get(stackPos), VariableType.METHOD_PARAMETER));
+ }
+ }
+
+ @Override
+ public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
+ if (stack != null && opcode != Opcodes.INVOKESTATIC && !methodName.startsWith("<")) {
+ final int index = stack.size() - 1 - AsmUtil.getParamsTypes(desc).length;
+ final Object stackValue = stack.get(index);
+ final Variable variable = myFieldsAndParamsPositionInStack.get(index);
+ if (variable != null && variable.getMarker() == stackValue /*equality by reference is not mistake*/) {
+ final CallingLocation callingLocation = new CallingLocation(currentMethodSignature, variable.getVariableType());
+ final MethodNameAndQualifier invokedMethod = new MethodNameAndQualifier(name, AsmUtil.getQualifiedClassName(owner));
+ List<CallingLocation> callingLocations = myExtractedMethodsCallings.get(invokedMethod);
+ if (callingLocations == null) {
+ callingLocations = new ArrayList<CallingLocation>();
+ myExtractedMethodsCallings.put(invokedMethod, callingLocations);
+ }
+ callingLocations.add(callingLocation);
+ }
+ }
+ super.visitMethodInsn(opcode, owner, name, desc);
+ }
+ }, access, name, desc, signature, exceptions);
+ }
+ }
+
+ private static class Variable {
+ private final Object myMarker;
+ private final VariableType myVariableType;
+
+ private Variable(final Object marker, final VariableType variableType) {
+ myMarker = marker;
+ myVariableType = variableType;
+ }
+
+ private Object getMarker() {
+ return myMarker;
+ }
+
+ private VariableType getVariableType() {
+ return myVariableType;
+ }
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodCallingLocationIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodCallingLocationIndex.java
new file mode 100644
index 000000000000..c55273ab5254
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodCallingLocationIndex.java
@@ -0,0 +1,94 @@
+package com.intellij.compilerOutputIndex.impl.callingLocation;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.intellij.compilerOutputIndex.api.descriptor.ArrayListKeyDescriptor;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.indexing.StorageException;
+import com.intellij.util.indexing.ValueContainer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.asm4.ClassReader;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodCallingLocationIndex extends CompilerOutputBaseIndex<MethodNameAndQualifier, List<CallingLocation>> {
+
+ public static MethodCallingLocationIndex getInstance(final Project project) {
+ return CompilerOutputIndexer.getInstance(project).getIndex(MethodCallingLocationIndex.class);
+ }
+
+ public MethodCallingLocationIndex() {
+ super(MethodNameAndQualifier.createKeyDescriptor(),
+ new ArrayListKeyDescriptor<CallingLocation>(CallingLocation.createDataExternalizer()));
+ }
+
+ @Override
+ protected ID<MethodNameAndQualifier, List<CallingLocation>> getIndexId() {
+ return generateIndexId(MethodCallingLocationIndex.class);
+ }
+
+ @Override
+ protected int getVersion() {
+ return 0;
+ }
+
+ public List<CallingLocation> getAllLocations(final MethodNameAndQualifier methodNameAndQualifier) {
+ try {
+ final List<CallingLocation> result = new ArrayList<CallingLocation>();
+ myIndex.getData(methodNameAndQualifier).forEach(new ValueContainer.ContainerAction<List<CallingLocation>>() {
+ @Override
+ public boolean perform(final int id, final List<CallingLocation> values) {
+ result.addAll(values);
+ return true;
+ }
+ });
+ return result;
+ }
+ catch (StorageException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Multiset<MethodIncompleteSignature> getLocationsAsParam(final MethodNameAndQualifier methodNameAndQualifier) {
+ final Multiset<MethodIncompleteSignature> result = HashMultiset.create();
+ try {
+ myIndex.getData(methodNameAndQualifier).forEach(new ValueContainer.ContainerAction<List<CallingLocation>>() {
+ @Override
+ public boolean perform(final int id, final List<CallingLocation> values) {
+ for (final CallingLocation value : values) {
+ if (value.getVariableType().equals(VariableType.METHOD_PARAMETER)) {
+ result.add(value.getMethodIncompleteSignature());
+ }
+ }
+ return true;
+ }
+ });
+ }
+ catch (StorageException e) {
+ throw new RuntimeException(e);
+ }
+ return result;
+ }
+
+
+ @Override
+ protected DataIndexer<MethodNameAndQualifier, List<CallingLocation>, ClassReader> getIndexer() {
+ return new DataIndexer<MethodNameAndQualifier, List<CallingLocation>, ClassReader>() {
+ @NotNull
+ @Override
+ public Map<MethodNameAndQualifier, List<CallingLocation>> map(final ClassReader inputData) {
+ return MethodCallingLocationExtractor.extract(inputData);
+ }
+ };
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodNameAndQualifier.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodNameAndQualifier.java
new file mode 100644
index 000000000000..e69d4f322f9b
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/MethodNameAndQualifier.java
@@ -0,0 +1,81 @@
+package com.intellij.compilerOutputIndex.impl.callingLocation;
+
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodNameAndQualifier {
+ @NotNull
+ private final String myMethodName;
+ @NotNull
+ private final String myQualifierName;
+
+ public MethodNameAndQualifier(@NotNull final String methodName, @NotNull final String qualifierName) {
+ myMethodName = methodName;
+ myQualifierName = qualifierName;
+ }
+
+ @NotNull
+ public String getMethodName() {
+ return myMethodName;
+ }
+
+ @NotNull
+ public String getQualifierName() {
+ return myQualifierName;
+ }
+
+ public static KeyDescriptor<MethodNameAndQualifier> createKeyDescriptor() {
+ final DataExternalizer<String> stringDataExternalizer = new EnumeratorStringDescriptor();
+ return new KeyDescriptor<MethodNameAndQualifier>() {
+ @Override
+ public void save(final DataOutput out, final MethodNameAndQualifier value) throws IOException {
+ stringDataExternalizer.save(out, value.myMethodName);
+ stringDataExternalizer.save(out, value.myQualifierName);
+ }
+
+ @Override
+ public MethodNameAndQualifier read(final DataInput in) throws IOException {
+ return new MethodNameAndQualifier(stringDataExternalizer.read(in), stringDataExternalizer.read(in));
+ }
+
+ @Override
+ public int getHashCode(final MethodNameAndQualifier value) {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean isEqual(final MethodNameAndQualifier val1, final MethodNameAndQualifier val2) {
+ return val1.equals(val2);
+ }
+ };
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final MethodNameAndQualifier that = (MethodNameAndQualifier)o;
+
+ if (!myMethodName.equals(that.myMethodName)) return false;
+ if (!myQualifierName.equals(that.myQualifierName)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myMethodName.hashCode();
+ result = 31 * result + myQualifierName.hashCode();
+ return result;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/VariableType.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/VariableType.java
new file mode 100644
index 000000000000..6cf1ff232881
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/callingLocation/VariableType.java
@@ -0,0 +1,15 @@
+package com.intellij.compilerOutputIndex.impl.callingLocation;
+
+import com.intellij.util.io.EnumDataDescriptor;
+import com.intellij.util.io.KeyDescriptor;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public enum VariableType {
+ FIELD,
+ METHOD_PARAMETER,
+ OTHER;
+
+ public static final KeyDescriptor<VariableType> KEY_DESCRIPTOR = new EnumDataDescriptor<VariableType>(VariableType.class);
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickInheritanceIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickInheritanceIndex.java
new file mode 100644
index 000000000000..9a136f5f5084
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickInheritanceIndex.java
@@ -0,0 +1,96 @@
+package com.intellij.compilerOutputIndex.impl.quickInheritance;
+
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
+import com.intellij.psi.CommonClassNames;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.indexing.StorageException;
+import com.intellij.util.indexing.ValueContainer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.compilerOutputIndex.api.descriptor.HashSetKeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.ClassVisitor;
+import org.jetbrains.asm4.Opcodes;
+import org.jetbrains.asm4.Type;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class QuickInheritanceIndex extends CompilerOutputBaseIndex<String, Set<String>> {
+
+ public static QuickInheritanceIndex getInstance(final Project project) {
+ return CompilerOutputIndexer.getInstance(project).getIndex(QuickInheritanceIndex.class);
+ }
+
+ public QuickInheritanceIndex() {
+ super(new EnumeratorStringDescriptor(), new HashSetKeyDescriptor<String>(new EnumeratorStringDescriptor()));
+ }
+
+ @Override
+ protected ID<String, Set<String>> getIndexId() {
+ return generateIndexId(QuickInheritanceIndex.class);
+ }
+
+ protected Set<String> getSupers(final String classQName) {
+ try {
+ final ValueContainer<Set<String>> valueContainer = myIndex.getData(classQName);
+ final Ref<Set<String>> setRef = Ref.create();
+ valueContainer.forEach(new ValueContainer.ContainerAction<Set<String>>() {
+ @Override
+ public boolean perform(final int id, final Set<String> value) {
+ setRef.set(value);
+ return false;
+ }
+ });
+ final Set<String> supers = setRef.get();
+ if (supers == null) {
+ return Collections.emptySet();
+ }
+ return supers;
+ }
+ catch (StorageException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected int getVersion() {
+ return 0;
+ }
+
+ @Override
+ protected DataIndexer<String, Set<String>, ClassReader> getIndexer() {
+ return new DataIndexer<String, Set<String>, ClassReader>() {
+ @NotNull
+ @Override
+ public Map<String, Set<String>> map(final ClassReader inputData) {
+ final Map<String, Set<String>> map = new HashMap<String, Set<String>>();
+ inputData.accept(new ClassVisitor(Opcodes.ASM4) {
+ @Override
+ public void visit(final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces) {
+ final String className = Type.getObjectType(name).getClassName();
+ if (className != null) {
+ final HashSet<String> value = ContainerUtil.newHashSet(AsmUtil.getQualifiedClassNames(interfaces, superName));
+ value.remove(CommonClassNames.JAVA_LANG_OBJECT);
+ map.put(className, value);
+ }
+ }
+ }, Opcodes.ASM4);
+ return map;
+ }
+ };
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickMethodsIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickMethodsIndex.java
new file mode 100644
index 000000000000..d857706f58d8
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickMethodsIndex.java
@@ -0,0 +1,103 @@
+package com.intellij.compilerOutputIndex.impl.quickInheritance;
+
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.indexing.StorageException;
+import com.intellij.util.indexing.ValueContainer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.compilerOutputIndex.api.descriptor.HashSetKeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.ClassVisitor;
+import org.jetbrains.asm4.MethodVisitor;
+import org.jetbrains.asm4.Opcodes;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class QuickMethodsIndex extends CompilerOutputBaseIndex<String, Set<String>> {
+
+ public static QuickMethodsIndex getInstance(final Project project) {
+ return CompilerOutputIndexer.getInstance(project).getIndex(QuickMethodsIndex.class);
+ }
+
+ public QuickMethodsIndex() {
+ super(new EnumeratorStringDescriptor(), new HashSetKeyDescriptor<String>(new EnumeratorStringDescriptor()));
+ }
+
+ @Override
+ protected ID<String, Set<String>> getIndexId() {
+ return generateIndexId(QuickMethodsIndex.class);
+ }
+
+ @Override
+ protected int getVersion() {
+ return 0;
+ }
+
+ protected Set<String> getMethodsNames(final String classQName) {
+ final Ref<Set<String>> methodsRef = Ref.create();
+ try {
+ myIndex.getData(classQName).forEach(new ValueContainer.ContainerAction<Set<String>>() {
+ @Override
+ public boolean perform(final int id, final Set<String> value) {
+ methodsRef.set(value);
+ return true;
+ }
+ });
+ final Set<String> methods = methodsRef.get();
+ return methods == null ? Collections.<String>emptySet() : methods;
+ }
+ catch (StorageException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected DataIndexer<String, Set<String>, ClassReader> getIndexer() {
+ return new DataIndexer<String, Set<String>, ClassReader>() {
+ @NotNull
+ @Override
+ public Map<String, Set<String>> map(final ClassReader inputData) {
+ final Map<String, Set<String>> map = new HashMap<String, Set<String>>();
+ inputData.accept(new ClassVisitor(Opcodes.ASM4) {
+
+ private String myClassName;
+ private final HashSet<String> myMethodNames = new HashSet<String>();
+
+ @Override
+ public void visit(final int i, final int i2, final String name, final String s2, final String s3, final String[] strings) {
+ myClassName = AsmUtil.getQualifiedClassName(name);
+ }
+
+ @Override
+ public void visitEnd() {
+ map.put(myClassName, myMethodNames);
+ }
+
+ @Nullable
+ @Override
+ public MethodVisitor visitMethod(final int access,
+ final String name,
+ final String desc,
+ final String sign,
+ final String[] exceptions) {
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ myMethodNames.add(name);
+ }
+ return null;
+ }
+ }, Opcodes.ASM4);
+ return map;
+ }
+ };
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickOverrideUtil.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickOverrideUtil.java
new file mode 100644
index 000000000000..78583aa9446f
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/quickInheritance/QuickOverrideUtil.java
@@ -0,0 +1,23 @@
+package com.intellij.compilerOutputIndex.impl.quickInheritance;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class QuickOverrideUtil {
+
+ private QuickOverrideUtil() {}
+
+ public static boolean isMethodOverriden(final String classQName, final String methodName,
+ final QuickInheritanceIndex quickInheritanceIndex,
+ final QuickMethodsIndex quickMethodsIndex) {
+ for (final String aSuper : quickInheritanceIndex.getSupers(classQName)) {
+ if (quickMethodsIndex.getMethodsNames(aSuper).contains(methodName)) {
+ return true;
+ }
+ if (isMethodOverriden(aSuper, methodName, quickInheritanceIndex, quickMethodsIndex)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/MethodShortSignature.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/MethodShortSignature.java
new file mode 100644
index 000000000000..a1ef8129a19a
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/MethodShortSignature.java
@@ -0,0 +1,71 @@
+package com.intellij.compilerOutputIndex.impl.singleton;
+
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodShortSignature {
+ @NotNull
+ private final String myName;
+ @NotNull
+ private final String mySignature; //in raw asm type
+
+ public MethodShortSignature(final @NotNull String name, final @NotNull String signature) {
+ myName = name;
+ mySignature = signature;
+ }
+
+ @NotNull
+ public String getName() {
+ return myName;
+ }
+
+ @NotNull
+ public String getSignature() {
+ return mySignature;
+ }
+
+ public static DataExternalizer<MethodShortSignature> createDataExternalizer() {
+ final EnumeratorStringDescriptor stringDescriptor = new EnumeratorStringDescriptor();
+ return new DataExternalizer<MethodShortSignature>() {
+
+ @Override
+ public void save(final DataOutput out, final MethodShortSignature value) throws IOException {
+ stringDescriptor.save(out, value.getName());
+ stringDescriptor.save(out, value.getSignature());
+ }
+
+ @Override
+ public MethodShortSignature read(final DataInput in) throws IOException {
+ return new MethodShortSignature(stringDescriptor.read(in), stringDescriptor.read(in));
+ }
+ };
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final MethodShortSignature that = (MethodShortSignature) o;
+
+ if (!myName.equals(that.myName)) return false;
+ if (!mySignature.equals(that.mySignature)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myName.hashCode();
+ result = 31 * result + mySignature.hashCode();
+ return result;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/MethodShortSignatureWithWeight.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/MethodShortSignatureWithWeight.java
new file mode 100644
index 000000000000..a6381ec99c79
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/MethodShortSignatureWithWeight.java
@@ -0,0 +1,53 @@
+package com.intellij.compilerOutputIndex.impl.singleton;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Comparator;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodShortSignatureWithWeight {
+ private final MethodShortSignature myMethodShortSignature;
+ private final int myWeight;
+
+ public MethodShortSignatureWithWeight(final MethodShortSignature methodShortSignature, final int weight) {
+ myMethodShortSignature = methodShortSignature;
+ myWeight = weight;
+ }
+
+ public MethodShortSignature getMethodShortSignature() {
+ return myMethodShortSignature;
+ }
+
+ public int getWeight() {
+ return myWeight;
+ }
+
+ public static Comparator<MethodShortSignatureWithWeight> COMPARATOR = new Comparator<MethodShortSignatureWithWeight>() {
+ @Override
+ public int compare(final MethodShortSignatureWithWeight o1, final MethodShortSignatureWithWeight o2) {
+ return o1.getWeight() - o2.getWeight();
+ }
+ } ;
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final MethodShortSignatureWithWeight that = (MethodShortSignatureWithWeight) o;
+
+ if (myWeight != that.myWeight) return false;
+ if (!myMethodShortSignature.equals(that.myMethodShortSignature)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myMethodShortSignature.hashCode();
+ result = 31 * result + myWeight;
+ return result;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/ParamsInMethodOccurrencesIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/ParamsInMethodOccurrencesIndex.java
new file mode 100644
index 000000000000..dff423bd32d1
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/ParamsInMethodOccurrencesIndex.java
@@ -0,0 +1,116 @@
+package com.intellij.compilerOutputIndex.impl.singleton;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.compilerOutputIndex.impl.GuavaHashMultiSetExternalizer;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.indexing.StorageException;
+import com.intellij.util.indexing.ValueContainer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.*;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ParamsInMethodOccurrencesIndex extends CompilerOutputBaseIndex<String, Multiset<MethodShortSignature>> {
+
+ public static ParamsInMethodOccurrencesIndex getInstance(final Project project) {
+ return CompilerOutputIndexer.getInstance(project).getIndex(ParamsInMethodOccurrencesIndex.class);
+ }
+
+ public ParamsInMethodOccurrencesIndex() {
+ super(new EnumeratorStringDescriptor(), new GuavaHashMultiSetExternalizer<MethodShortSignature>(MethodShortSignature.createDataExternalizer()));
+ }
+
+ @Override
+ protected ID<String, Multiset<MethodShortSignature>> getIndexId() {
+ return generateIndexId(ParamsInMethodOccurrencesIndex.class);
+ }
+
+ @Override
+ protected int getVersion() {
+ return 0;
+ }
+
+ public Pair<List<MethodShortSignatureWithWeight>, Integer> getParameterOccurrences(final String parameterTypeName) {
+ try {
+ final Multiset<MethodShortSignature> resultAsMultiset = HashMultiset.create();
+ final ValueContainer<Multiset<MethodShortSignature>> valueContainer = myIndex.getData(parameterTypeName);
+ valueContainer.forEach(new ValueContainer.ContainerAction<Multiset<MethodShortSignature>>() {
+ @Override
+ public boolean perform(final int id, final Multiset<MethodShortSignature> localMap) {
+ for (final Multiset.Entry<MethodShortSignature> e : localMap.entrySet()) {
+ resultAsMultiset.add(e.getElement(), e.getCount());
+ }
+ return true;
+ }
+ });
+
+ final List<MethodShortSignatureWithWeight> result = new ArrayList<MethodShortSignatureWithWeight>(resultAsMultiset.elementSet().size());
+ int sumWeight = 0;
+ for (final Multiset.Entry<MethodShortSignature> e : resultAsMultiset.entrySet()) {
+ sumWeight += e.getCount();
+ result.add(new MethodShortSignatureWithWeight(e.getElement(), e.getCount()));
+ }
+ Collections.sort(result, MethodShortSignatureWithWeight.COMPARATOR);
+
+ return Pair.create(result, sumWeight);
+ } catch (StorageException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected DataIndexer<String, Multiset<MethodShortSignature>, ClassReader> getIndexer() {
+ return new DataIndexer<String, Multiset<MethodShortSignature>, ClassReader>() {
+ @NotNull
+ @Override
+ public Map<String, Multiset<MethodShortSignature>> map(final ClassReader inputData) {
+ final Map<String, Multiset<MethodShortSignature>> result = new HashMap<String, Multiset<MethodShortSignature>>();
+ inputData.accept(new ClassVisitor(Opcodes.ASM4) {
+ @Nullable
+ @Override
+ public MethodVisitor visitMethod(final int i, final String name, final String desc, final String signature, final String[] exception) {
+ if (CompilerOutputIndexUtil.isSetterOrConstructorMethodName(name)) {
+ return null;
+ }
+ final String[] parameters = AsmUtil.getParamsTypes(desc);
+ final MethodShortSignature thisMethodShortSignature = new MethodShortSignature(name, desc);
+ for (final String parameter : parameters) {
+ Multiset<MethodShortSignature> methods = result.get(parameter);
+ if (methods == null) {
+ methods = HashMultiset.create();
+ result.put(parameter, methods);
+ }
+ methods.add(thisMethodShortSignature);
+ }
+ return new MethodVisitor(Opcodes.ASM4) {
+ @Override
+ public void visitLocalVariable(final String s, final String desc, final String signature, final Label label, final Label label2, final int i) {
+ final String varType = AsmUtil.getQualifiedClassName(desc);
+ Multiset<MethodShortSignature> methods = result.get(varType);
+ if (methods == null) {
+ methods = HashMultiset.create();
+ result.put(varType, methods);
+ }
+ methods.add(thisMethodShortSignature);
+ }
+ };
+ }
+ }, Opcodes.ASM4);
+ return result;
+ }
+ };
+ }
+}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/TwinVariablesIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/TwinVariablesIndex.java
new file mode 100644
index 000000000000..8a04b72dca62
--- /dev/null
+++ b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/singleton/TwinVariablesIndex.java
@@ -0,0 +1,137 @@
+package com.intellij.compilerOutputIndex.impl.singleton;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
+import com.intellij.compilerOutputIndex.api.descriptor.ArrayListKeyDescriptor;
+import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexUtil;
+import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.ID;
+import com.intellij.util.indexing.StorageException;
+import com.intellij.util.indexing.ValueContainer;
+import com.intellij.util.io.EnumeratorIntegerDescriptor;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.*;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class TwinVariablesIndex extends CompilerOutputBaseIndex<String, List<Integer>> {
+ public static TwinVariablesIndex getInstance(final Project project) {
+ return CompilerOutputIndexer.getInstance(project).getIndex(TwinVariablesIndex.class);
+ }
+
+ public TwinVariablesIndex() {
+ super(new EnumeratorStringDescriptor(), new ArrayListKeyDescriptor<Integer>(EnumeratorIntegerDescriptor.INSTANCE));
+ }
+
+ @Override
+ protected ID<String, List<Integer>> getIndexId() {
+ return generateIndexId(TwinVariablesIndex.class);
+ }
+
+ @Override
+ protected int getVersion() {
+ return 0;
+ }
+
+ @NotNull
+ public List<Integer> getTwinInfo(final String typeQName) {
+ try {
+ final ValueContainer<List<Integer>> valueContainer = myIndex.getData(typeQName);
+ final List<Integer> result = new ArrayList<Integer>(valueContainer.size());
+ valueContainer.forEach(new ValueContainer.ContainerAction<List<Integer>>() {
+ @Override
+ public boolean perform(final int id, final List<Integer> value) {
+ result.addAll(value);
+ return true;
+ }
+ });
+ return result;
+ }
+ catch (StorageException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected DataIndexer<String, List<Integer>, ClassReader> getIndexer() {
+ return new DataIndexer<String, List<Integer>, ClassReader>() {
+ @NotNull
+ @Override
+ public Map<String, List<Integer>> map(final ClassReader inputData) {
+ final Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
+ inputData.accept(new ClassVisitor(Opcodes.ASM4) {
+
+ @Nullable
+ @Override
+ public MethodVisitor visitMethod(final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions) {
+ if (CompilerOutputIndexUtil.isSetterOrConstructorMethodName(name)) {
+ return null;
+ }
+ final Multiset<String> myTypesOccurrences = HashMultiset.create();
+ final String[] paramsTypes = AsmUtil.getParamsTypes(desc);
+ Collections.addAll(myTypesOccurrences, paramsTypes);
+ return new MethodVisitor(Opcodes.ASM4) {
+ private final Set<String> myLocalVarNames = new HashSet<String>();
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void visitEnd() {
+ for (final Multiset.Entry<String> e: myTypesOccurrences.entrySet()) {
+ final String key = e.getElement();
+ if (!ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(key)) {
+ List<Integer> values = map.get(key);
+ if (values == null) {
+ values = new ArrayList<Integer>();
+ map.put(key, values);
+ }
+ values.add(e.getCount());
+ }
+ }
+ }
+
+ private final Set<String> myUsedReadFieldsIndex = new HashSet<String>();
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) {
+ final String fieldTypeQName = AsmUtil.getReturnType(desc);
+ if ((opcode == Opcodes.GETSTATIC || opcode == Opcodes.GETFIELD)) {
+ if (myUsedReadFieldsIndex.add(owner + name)) {
+ myTypesOccurrences.add(fieldTypeQName);
+ }
+ }
+ }
+
+ @Override
+ public void visitLocalVariable(final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index) {
+ if (index > paramsTypes.length && myLocalVarNames.add(name)) {
+ final String type = AsmUtil.getReturnType(desc);
+ myTypesOccurrences.add(type);
+ }
+ }
+ };
+ }
+ }, Opcodes.ASM4);
+ return map;
+ }
+ };
+ }
+}
diff --git a/java/java-impl/src/com/intellij/externalSystem/JavaProjectData.java b/java/java-impl/src/com/intellij/externalSystem/JavaProjectData.java
index 9deea918441a..fb632cdd7123 100644
--- a/java/java-impl/src/com/intellij/externalSystem/JavaProjectData.java
+++ b/java/java-impl/src/com/intellij/externalSystem/JavaProjectData.java
@@ -43,7 +43,7 @@ public class JavaProjectData extends AbstractExternalEntityData {
private static final LanguageLevel DEFAULT_LANGUAGE_LEVEL = LanguageLevel.JDK_1_6;
private static final JavaSdkVersion DEFAULT_JDK_VERSION = JavaSdkVersion.JDK_1_6;
- private static final Pattern JDK_VERSION_PATTERN = Pattern.compile(".*1\\.(\\d+).*");
+ private static final Pattern JDK_VERSION_PATTERN = Pattern.compile(".*1.(\\d+).*");
@NotNull private JavaSdkVersion myJdkVersion = DEFAULT_JDK_VERSION;
@NotNull private LanguageLevel myLanguageLevel = DEFAULT_LANGUAGE_LEVEL;
@@ -128,6 +128,13 @@ public class JavaProjectData extends AbstractExternalEntityData {
public void setLanguageLevel(@Nullable String languageLevel) {
LanguageLevel level = LanguageLevel.parse(languageLevel);
+ if (level == null) {
+ Matcher matcher = JDK_VERSION_PATTERN.matcher(languageLevel);
+ if (matcher.matches()) {
+ String versionAsString = matcher.group(1);
+ level = LanguageLevel.parse("1." + versionAsString);
+ }
+ }
if (level != null) {
myLanguageLevel = level;
}
diff --git a/java/java-impl/src/com/intellij/ide/actions/JavaCreateTemplateInPackageAction.java b/java/java-impl/src/com/intellij/ide/actions/JavaCreateTemplateInPackageAction.java
index a6c302b3174b..e80c05e0acf1 100644
--- a/java/java-impl/src/com/intellij/ide/actions/JavaCreateTemplateInPackageAction.java
+++ b/java/java-impl/src/com/intellij/ide/actions/JavaCreateTemplateInPackageAction.java
@@ -15,12 +15,14 @@
*/
package com.intellij.ide.actions;
+import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import javax.swing.*;
-public abstract class JavaCreateTemplateInPackageAction<T extends PsiElement> extends CreateTemplateInPackageAction<T> {
+public abstract class JavaCreateTemplateInPackageAction<T extends PsiElement> extends CreateTemplateInPackageAction<T> implements
+ DumbAware {
protected JavaCreateTemplateInPackageAction(String text, String description, Icon icon, boolean inSourceOnly) {
super(text, description, icon, inSourceOnly);
diff --git a/java/java-impl/src/com/intellij/ide/actions/JavaQualifiedNameProvider.java b/java/java-impl/src/com/intellij/ide/actions/JavaQualifiedNameProvider.java
index de3446ecb4bb..13ac82b52dcb 100644
--- a/java/java-impl/src/com/intellij/ide/actions/JavaQualifiedNameProvider.java
+++ b/java/java-impl/src/com/intellij/ide/actions/JavaQualifiedNameProvider.java
@@ -72,6 +72,9 @@ public class JavaQualifiedNameProvider implements QualifiedNameProvider {
if (containingClass == null) return null;
String classFqn = containingClass.getQualifiedName();
if (classFqn == null) return member.getName(); // refer to member of anonymous class by simple name
+ if (member instanceof PsiMethod && containingClass.findMethodsByName(member.getName(), false).length > 1) {
+ return classFqn + "#" + member.getName() + getParameterString((PsiMethod)member);
+ }
return classFqn + "#" + member.getName();
}
return null;
@@ -89,17 +92,18 @@ public class JavaQualifiedNameProvider implements QualifiedNameProvider {
final int endIndex = fqn.indexOf('#');
if (endIndex != -1) {
String className = fqn.substring(0, endIndex);
- if (className != null) {
- aClass = JavaPsiFacade.getInstance(project).findClass(className, GlobalSearchScope.allScope(project));
- if (aClass != null) {
- String memberName = fqn.substring(endIndex + 1);
- PsiField field = aClass.findFieldByName(memberName, false);
- if (field != null) {
- return field;
- }
- PsiMethod[] methods = aClass.findMethodsByName(memberName, false);
- if (methods.length != 0) {
- return methods[0];
+ int paramIndex = fqn.indexOf('(', endIndex);
+ aClass = JavaPsiFacade.getInstance(project).findClass(className, GlobalSearchScope.allScope(project));
+ if (aClass != null) {
+ String memberName = fqn.substring(endIndex + 1, paramIndex < 0 ? fqn.length() : paramIndex);
+ PsiField field = aClass.findFieldByName(memberName, false);
+ if (field != null) {
+ return field;
+ }
+ String paramString = paramIndex < 0 ? "" : fqn.substring(paramIndex);
+ for (PsiMethod overload : aClass.findMethodsByName(memberName, false)) {
+ if (StringUtil.isEmpty(paramString) || paramString.equals(getParameterString(overload))) {
+ return overload;
}
}
}
@@ -161,14 +165,7 @@ public class JavaQualifiedNameProvider implements QualifiedNameProvider {
if (toInsert.length() != 0) toInsert += "#";
toInsert += member.getName();
if (member instanceof PsiMethod) {
- toInsert += "(";
- PsiParameter[] parameters = ((PsiMethod)member).getParameterList().getParameters();
- for (int i = 0; i < parameters.length; i++) {
- PsiParameter parameter = parameters[i];
- if (i != 0) toInsert += ", ";
- toInsert += parameter.getType().getCanonicalText();
- }
- toInsert += ")";
+ toInsert += getParameterString((PsiMethod)member);
}
}
else if (elementAtCaret == null ||
@@ -256,6 +253,18 @@ public class JavaQualifiedNameProvider implements QualifiedNameProvider {
editor.getCaretModel().moveToOffset(caretOffset);
}
+ private static String getParameterString(PsiMethod method) {
+ String toInsert = "(";
+ PsiParameter[] parameters = method.getParameterList().getParameters();
+ for (int i = 0; i < parameters.length; i++) {
+ PsiParameter parameter = parameters[i];
+ if (i != 0) toInsert += ", ";
+ toInsert += parameter.getType().getCanonicalText();
+ }
+ toInsert += ")";
+ return toInsert;
+ }
+
private static boolean isReferencedTo(PsiReferenceExpression referenceExpression, PsiMember targetElement) {
PsiElement resolved = referenceExpression.advancedResolve(true).getElement();
if (!(resolved instanceof PsiMember)) return false;
diff --git a/java/java-impl/src/com/intellij/ide/scopeView/ClassesScopeTreeStructureExpander.java b/java/java-impl/src/com/intellij/ide/scopeView/ClassesScopeTreeStructureExpander.java
index a025a1e7cdc6..3f81ae349c8a 100644
--- a/java/java-impl/src/com/intellij/ide/scopeView/ClassesScopeTreeStructureExpander.java
+++ b/java/java-impl/src/com/intellij/ide/scopeView/ClassesScopeTreeStructureExpander.java
@@ -119,7 +119,7 @@ public class ClassesScopeTreeStructureExpander implements ScopeTreeStructureExpa
public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {
final TreePath path = event.getPath();
if (path == null) return;
- final DefaultMutableTreeNode node = (PackageDependenciesNode)path.getLastPathComponent();
+ final DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
if (node instanceof DirectoryNode) {
Set<FileNode> fileNodes = null;
for (int i = node.getChildCount() - 1; i >= 0; i--) {
diff --git a/java/java-impl/src/com/intellij/jarFinder/FindJarFix.java b/java/java-impl/src/com/intellij/jarFinder/FindJarFix.java
new file mode 100644
index 000000000000..8fdf05c0a620
--- /dev/null
+++ b/java/java-impl/src/com/intellij/jarFinder/FindJarFix.java
@@ -0,0 +1,301 @@
+package com.intellij.jarFinder;
+
+import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
+import com.intellij.codeInsight.hint.HintManager;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.application.AccessToken;
+import com.intellij.openapi.application.WriteAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileChooser.FileChooser;
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.util.Iconable;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.CommonClassNames;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.NotNullFunction;
+import com.intellij.util.PlatformIcons;
+import com.intellij.util.download.DownloadableFileDescription;
+import com.intellij.util.download.DownloadableFileService;
+import org.apache.xerces.parsers.DOMParser;
+import org.jetbrains.annotations.NotNull;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.swing.*;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public abstract class FindJarFix<T extends PsiElement> implements IntentionAction, Iconable {
+ private static final String CLASS_ROOT_URL = "http://findjar.com/class/";
+ private static final String CLASS_PAGE_EXT = ".html";
+ private static final String SERVICE_URL = "http://findjar.com";
+ private static final String LINK_TAG_NAME = "a";
+ private static final String LINK_ATTR_NAME = "href";
+
+ protected final T myRef;
+ protected final Module myModule;
+ protected JComponent myEditorComponent;
+
+ public FindJarFix(T ref) {
+ myRef = ref;
+ myModule = ModuleUtil.findModuleForPsiElement(ref);
+ }
+
+ @NotNull
+ @Override
+ public String getText() {
+ return "Find jar on web";
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return "Family name";
+ }
+
+ @Override
+ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+ return myRef.isValid()
+ && JavaPsiFacade.getInstance(project).findClass(CommonClassNames.JAVA_LANG_OBJECT, file.getResolveScope()) != null
+ && myModule != null
+ && isFqnsOk(project, getPossibleFqns(myRef));
+ }
+
+ private static boolean isFqnsOk(Project project, List<String> fqns) {
+ if (fqns.isEmpty()) return false;
+ final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
+ final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
+ for (String fqn : fqns) {
+ if (facade.findClass(fqn, scope) != null) return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void invoke(@NotNull Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
+ final List<String> fqns = getPossibleFqns(myRef);
+ myEditorComponent = editor.getComponent();
+ if (fqns.size() > 1) {
+ final JBList listOfFqns = new JBList(fqns);
+ JBPopupFactory.getInstance()
+ .createListPopupBuilder(listOfFqns)
+ .setTitle("Select Qualified Name")
+ .setItemChoosenCallback(new Runnable() {
+ @Override
+ public void run() {
+ final Object value = listOfFqns.getSelectedValue();
+ if (value instanceof String) {
+ findJarsForFqn(((String)value), editor);
+ }
+ }
+ }).createPopup().showInBestPositionFor(editor);
+ }
+ else if (fqns.size() == 1) {
+ findJarsForFqn(fqns.get(0), editor);
+ }
+ }
+
+ private void findJarsForFqn(final String fqn, final Editor editor) {
+ final Map<String, String> libs = new HashMap<String, String>();
+
+ final Runnable runnable = new Runnable() {
+ public void run() {
+ try {
+ final DOMParser parser = new DOMParser();
+ parser.parse(CLASS_ROOT_URL + fqn.replace('.', '/') + CLASS_PAGE_EXT);
+ final Document doc = parser.getDocument();
+ if (doc != null) {
+ final NodeList links = doc.getElementsByTagName(LINK_TAG_NAME);
+ for (int i = 0; i < links.getLength(); i++) {
+ final Node link = links.item(i);
+ final String libName = link.getTextContent();
+ final NamedNodeMap attributes = link.getAttributes();
+ if (attributes != null) {
+ final Node href = attributes.getNamedItem(LINK_ATTR_NAME);
+ if (href != null) {
+ final String pathToJar = href.getTextContent();
+ if (pathToJar != null && (pathToJar.startsWith("/jar/") || pathToJar.startsWith("/class/../"))) {
+ libs.put(libName, SERVICE_URL + pathToJar);
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (IOException ignore) {//
+ }
+ catch (SAXException e) {//
+ }
+ }
+ };
+
+ final Task.Modal task = new Task.Modal(editor.getProject(), "Looking for libraries", true) {
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ indicator.setIndeterminate(true);
+ runnable.run();
+ }
+
+ @Override
+ public void onSuccess() {
+ super.onSuccess();
+ if (libs.isEmpty()) {
+ HintManager.getInstance().showInformationHint(editor, "No libraries found for '" + fqn + "'");
+ } else {
+ final ArrayList<String> variants = new ArrayList<String>(libs.keySet());
+ Collections.sort(variants, new Comparator<String>() {
+ @Override
+ public int compare(String o1, String o2) {
+ return o1.compareTo(o2);
+ }
+ });
+ final JBList libNames = new JBList(variants);
+ libNames.installCellRenderer(new NotNullFunction<Object, JComponent>() {
+ @NotNull
+ @Override
+ public JComponent fun(Object o) {
+ return new JLabel(o.toString(), PlatformIcons.JAR_ICON, SwingConstants.LEFT);
+ }
+ });
+ if (libs.size() == 1) {
+ final String jarName = libs.keySet().iterator().next();
+ final String url = libs.get(jarName);
+ initiateDownload(url, jarName);
+ } else {
+ JBPopupFactory.getInstance()
+ .createListPopupBuilder(libNames)
+ .setTitle("Select a jar file")
+ .setItemChoosenCallback(new Runnable() {
+ @Override
+ public void run() {
+ final Object value = libNames.getSelectedValue();
+ if (value instanceof String) {
+ final String jarName = (String)value;
+ final String url = libs.get(jarName);
+ if (url != null) {
+ initiateDownload(url, jarName);
+ }
+ }
+ }
+ })
+ .createPopup().showInBestPositionFor(editor);
+ }
+ }
+ }
+ };
+
+ ProgressManager.getInstance().run(task);
+ }
+
+ private void initiateDownload(String url, String jarName) {
+ DOMParser parser = new DOMParser();
+ try {
+ parser.parse(url);
+ final Document doc = parser.getDocument();
+ if (doc != null) {
+ final NodeList links = doc.getElementsByTagName(LINK_TAG_NAME);
+ if (links != null) {
+ for (int i = 0; i < links.getLength(); i++) {
+ final Node item = links.item(i);
+ if (item != null) {
+ final NamedNodeMap attributes = item.getAttributes();
+ if (attributes != null) {
+ final Node link = attributes.getNamedItem(LINK_ATTR_NAME);
+ if (link != null) {
+ final String jarUrl = link.getTextContent();
+ if (jarUrl != null && jarUrl.endsWith(jarName)) {
+ downloadJar(jarUrl, jarName);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (SAXException e) {//
+ }
+ catch (IOException e) {//
+ }
+ }
+
+ private void downloadJar(String jarUrl, String jarName) {
+ final Project project = myModule.getProject();
+ final String dirPath = PropertiesComponent.getInstance(project).getValue("findjar.last.used.dir");
+ VirtualFile toSelect = dirPath == null ? null : LocalFileSystem.getInstance().findFileByIoFile(new File(dirPath));
+ final VirtualFile file = FileChooser.chooseFile(FileChooserDescriptorFactory.createSingleFolderDescriptor(), project, toSelect);
+ if (file != null) {
+ PropertiesComponent.getInstance(project).setValue("findjar.last.used.dir", file.getPath());
+ final DownloadableFileService downloader = DownloadableFileService.getInstance();
+ final DownloadableFileDescription description = downloader.createFileDescription(jarUrl, jarName);
+ final VirtualFile[] jars = downloader.createDownloader(Arrays.asList(description), project, myEditorComponent, jarName)
+ .toDirectory(file.getPath()).download();
+ if (jars != null && jars.length == 1) {
+ AccessToken token = WriteAction.start();
+ try {
+ OrderEntryFix.addJarToRoots(jars[0].getPresentableUrl(), myModule, myRef);
+ }
+ finally {
+ token.finish();
+ }
+ }
+ }
+ }
+
+ protected abstract Collection<String> getFqns(@NotNull T ref);
+
+ protected List<String> getPossibleFqns(T ref) {
+ Collection<String> fqns = getFqns(ref);
+
+ List<String> res = new ArrayList<String>(fqns.size());
+
+ for (String fqn : fqns) {
+ if (fqn.startsWith("java.") || fqn.startsWith("javax.swing.")) {
+ continue;
+ }
+ final int index = fqn.lastIndexOf('.');
+ if (index == -1) {
+ continue;
+ }
+ final String className = fqn.substring(index + 1);
+ if (className.length() == 0 || Character.isLowerCase(className.charAt(0))) {
+ continue;
+ }
+
+ res.add(fqn);
+ }
+
+ return res;
+ }
+
+ @Override
+ public boolean startInWriteAction() {
+ return false;
+ }
+
+ @Override
+ public Icon getIcon(int flags) {
+ return PlatformIcons.WEB_ICON;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/jarFinder/FindJarQuickFixProvider.java b/java/java-impl/src/com/intellij/jarFinder/FindJarQuickFixProvider.java
new file mode 100644
index 000000000000..9cf66d3991fe
--- /dev/null
+++ b/java/java-impl/src/com/intellij/jarFinder/FindJarQuickFixProvider.java
@@ -0,0 +1,22 @@
+package com.intellij.jarFinder;
+
+import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
+import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
+import com.intellij.psi.PsiJavaCodeReferenceElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class FindJarQuickFixProvider extends UnresolvedReferenceQuickFixProvider<PsiJavaCodeReferenceElement> {
+ @Override
+ public void registerFixes(PsiJavaCodeReferenceElement ref, QuickFixActionRegistrar registrar) {
+ registrar.register(new JavaFindJarFix(ref));
+ }
+
+ @NotNull
+ @Override
+ public Class<PsiJavaCodeReferenceElement> getReferenceClass() {
+ return PsiJavaCodeReferenceElement.class;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/jarFinder/JavaFindJarFix.java b/java/java-impl/src/com/intellij/jarFinder/JavaFindJarFix.java
new file mode 100644
index 000000000000..98e5a6709a5c
--- /dev/null
+++ b/java/java-impl/src/com/intellij/jarFinder/JavaFindJarFix.java
@@ -0,0 +1,78 @@
+package com.intellij.jarFinder;
+
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.PsiImportStaticStatementImpl;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public class JavaFindJarFix extends FindJarFix<PsiQualifiedReferenceElement> {
+ public JavaFindJarFix(PsiQualifiedReferenceElement ref) {
+ super(ref);
+ }
+
+ @Override
+ protected Collection<String> getFqns(@NotNull PsiQualifiedReferenceElement ref) {
+ final PsiImportStatementBase importStatement = PsiTreeUtil.getParentOfType(ref.getElement(), PsiImportStatementBase.class);
+
+ //from static imports
+ if (importStatement != null) {
+ if (importStatement instanceof PsiImportStatement) {
+ final String importFQN = ((PsiImportStatement)importStatement).getQualifiedName();
+ if (importFQN != null && !importFQN.endsWith("*")) {
+ return Collections.singleton(importFQN);
+ }
+ }
+ else if (importStatement instanceof PsiImportStaticStatementImpl) {
+ final PsiJavaCodeReferenceElement classRef = ((PsiImportStaticStatementImpl)importStatement).getClassReference();
+ if (classRef != null) {
+ final String importFQN = classRef.getQualifiedName();
+ if (importFQN != null) {
+ return Collections.singleton(importFQN);
+ }
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ final PsiElement qualifier = ref.getQualifier();
+ if (qualifier instanceof PsiQualifiedReference) {
+ //PsiQualifiedReference r = (PsiQualifiedReference)qualifier;
+ //TODO[kb] get fqn from expressions like org.unresolvedPackage.MyClass.staticMethodCall(...);
+ return Collections.emptyList();
+ }
+ final String className = ref.getReferenceName();
+ PsiFile file = ref.getContainingFile().getOriginalFile();
+ if (className != null && file instanceof PsiJavaFile) {
+ final PsiImportList importList = ((PsiJavaFile)file).getImportList();
+ if (importList != null) {
+ final PsiImportStatementBase statement = importList.findSingleImportStatement(className);
+ if (statement instanceof PsiImportStatement) {
+ final String importFQN = ((PsiImportStatement)statement).getQualifiedName();
+ if (importFQN != null) {
+ return Collections.singleton(importFQN);
+ }
+ }
+ else {
+ List<String> res = new ArrayList<String>();
+ // iterate through *
+ for (PsiImportStatementBase imp : importList.getAllImportStatements()) {
+ if (imp.isOnDemand() && imp instanceof PsiImportStatement) {
+ res.add(((PsiImportStatement)imp).getQualifiedName() + "." + className);
+ }
+ }
+
+ return res;
+ }
+ }
+ }
+ return Collections.emptyList();
+ }
+}
diff --git a/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java
new file mode 100644
index 000000000000..deaed59885ec
--- /dev/null
+++ b/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java
@@ -0,0 +1,70 @@
+package com.intellij.jarFinder;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.xpath.XPath;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public class MavenCentralSourceSearcher extends SourceSearcher {
+
+ private static final Logger LOG = Logger.getInstance(MavenCentralSourceSearcher.class);
+
+ @Nullable
+ @Override
+ protected String findSourceJar(@NotNull ProgressIndicator indicator,
+ @NotNull String artifactId,
+ @NotNull String version) throws SourceSearchException {
+ try {
+ indicator.setIndeterminate(true);
+ indicator.setText("Connecting to http://search.maven.org");
+
+ indicator.checkCanceled();
+
+ String url = "http://search.maven.org/solrsearch/select?rows=3&wt=xml&q=a:%22" + artifactId + "%22%20AND%20v:%22" + version + "%22%20AND%20l:%22sources%22";
+ Document document = readDocumentCancelable(indicator, url);
+
+ indicator.checkCanceled();
+
+ List<Element> artifactList = (List<Element>)XPath.newInstance("/response/result/doc/str[@name='g']").selectNodes(document);
+ if (artifactList.isEmpty()) {
+ return null;
+ }
+
+ Element element;
+
+ if (artifactList.size() == 1) {
+ element = artifactList.get(0);
+ }
+ else {
+ // TODO handle
+ return null;
+ }
+
+ String groupId = element.getValue();
+
+ String downloadUrl = "http://search.maven.org/remotecontent?filepath=" + groupId.replace('.', '/') + '/' + artifactId + '/' + version + '/' + artifactId + '-' + version + "-sources.jar";
+
+ return downloadUrl;
+ }
+ catch (JDOMException e) {
+ LOG.warn(e);
+ throw new SourceSearchException("Failed to parse response from server. See log for more details.");
+ }
+ catch (IOException e) {
+ indicator.checkCanceled(); // Cause of IOException may be canceling of operation.
+
+ LOG.warn(e);
+ throw new SourceSearchException("Connection problem. See log for more details.");
+ }
+ }
+}
diff --git a/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java
new file mode 100644
index 000000000000..2a942cca8946
--- /dev/null
+++ b/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java
@@ -0,0 +1,87 @@
+package com.intellij.jarFinder;
+
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.util.Pair;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.xpath.XPath;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public class SonatypeSourceSearcher extends SourceSearcher {
+
+ private static final Logger LOG = Logger.getInstance(SonatypeSourceSearcher.class);
+
+ @Nullable
+ @Override
+ public String findSourceJar(@NotNull final ProgressIndicator indicator, @NotNull String artifactId, @NotNull String version)
+ throws SourceSearchException {
+ try {
+ indicator.setIndeterminate(true);
+ indicator.setText("Connecting to https://oss.sonatype.org");
+
+ indicator.checkCanceled();
+
+ String url = "https://oss.sonatype.org/service/local/lucene/search?collapseresults=true&c=sources&a=" + artifactId + "&v=" + version;
+ Document document = readDocumentCancelable(indicator, url);
+
+ indicator.checkCanceled();
+
+ List<Element> artifactList = (List<Element>)XPath.newInstance("/searchNGResponse/data/artifact").selectNodes(document);
+ if (artifactList.isEmpty()) {
+ return null;
+ }
+
+ Element element;
+
+ if (artifactList.size() == 1) {
+ element = artifactList.get(0);
+ }
+ else {
+ // TODO handle
+ return null;
+ }
+
+ List<Element> artifactHintList =
+ (List<Element>)XPath.newInstance("artifactHits/artifactHit/artifactLinks/artifactLink/classifier[text()='sources']/../../..")
+ .selectNodes(element);
+ if (artifactHintList.isEmpty()) {
+ return null;
+ }
+
+ String groupId = element.getChildTextTrim("groupId");
+ String repositoryId = artifactHintList.get(0).getChildTextTrim("repositoryId");
+
+ String downloadUrl = "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=" +
+ repositoryId +
+ "&g=" +
+ groupId +
+ "&a=" +
+ artifactId +
+ "&v=" +
+ version +
+ "&e=jar&c=sources";
+
+ return downloadUrl;
+ }
+ catch (JDOMException e) {
+ LOG.warn(e);
+ throw new SourceSearchException("Failed to parse response from server. See log for more details.");
+ }
+ catch (IOException e) {
+ indicator.checkCanceled(); // Cause of IOException may be canceling of operation.
+
+ LOG.warn(e);
+ throw new SourceSearchException("Connection problem. See log for more details.");
+ }
+ }
+}
diff --git a/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java
new file mode 100644
index 000000000000..b1d635af8525
--- /dev/null
+++ b/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java
@@ -0,0 +1,77 @@
+package com.intellij.jarFinder;
+
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.util.net.HttpConfigurable;
+import org.jdom.Document;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public abstract class SourceSearcher {
+
+ /**
+ * @param indicator
+ * @param artifactId
+ * @param version
+ * @return groupId of found artifact and url.
+ */
+ @Nullable
+ protected abstract String findSourceJar(@NotNull final ProgressIndicator indicator, @NotNull String artifactId, @NotNull String version) throws SourceSearchException;
+
+ protected static Document readDocumentCancelable(final ProgressIndicator indicator, String url) throws JDOMException, IOException {
+ final HttpURLConnection urlConnection = HttpConfigurable.getInstance().openHttpConnection(url);
+
+ Thread t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ //noinspection InfiniteLoopStatement
+ while (true) {
+ if (indicator.isCanceled()) {
+ urlConnection.disconnect();
+ }
+
+ //noinspection BusyWait
+ Thread.sleep(100);
+ }
+ }
+ catch (InterruptedException ignored) {
+
+ }
+ }
+ });
+
+ t.start();
+
+ try {
+ urlConnection.setRequestProperty("accept", "application/xml");
+
+ InputStream inputStream = urlConnection.getInputStream();
+ try {
+ return new SAXBuilder().build(inputStream);
+ }
+ finally {
+ inputStream.close();
+ }
+ }
+ finally {
+ t.interrupt();
+ }
+ }
+}
+
+class SourceSearchException extends Exception {
+
+ SourceSearchException(String message) {
+ super(message);
+ }
+
+} \ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java b/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java
index 5b7c3ef01ad2..08ecb6a716a4 100644
--- a/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java
+++ b/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java
@@ -21,8 +21,6 @@ import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.*;
import com.intellij.execution.filters.RegexpFilter;
-import com.intellij.execution.filters.TextConsoleBuilder;
-import com.intellij.execution.filters.TextConsoleBuilderFactory;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
@@ -138,10 +136,8 @@ public class JavadocConfiguration implements ModuleRunProfile, JDOMExternalizabl
super(null);
myGenerationOptions = generationOptions;
myProject = project;
- TextConsoleBuilder builder = TextConsoleBuilderFactory.getInstance().createBuilder(project);
- builder.addFilter(new RegexpFilter(project, "$FILE_PATH$:$LINE$:[^\\^]+\\^"));
- builder.addFilter(new RegexpFilter(project, "$FILE_PATH$:$LINE$: warning - .+$"));
- setConsoleBuilder(builder);
+ addConsoleFilters(new RegexpFilter(project, "$FILE_PATH$:$LINE$:[^\\^]+\\^"),
+ new RegexpFilter(project, "$FILE_PATH$:$LINE$: warning - .+$"));
}
protected GeneralCommandLine createCommandLine() throws ExecutionException {
diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java
index ecebc06f9555..e34cafbbb10c 100644
--- a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java
+++ b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java
@@ -18,6 +18,7 @@ package com.intellij.javadoc;
import com.intellij.CommonBundle;
import com.intellij.analysis.AnalysisScope;
import com.intellij.execution.ExecutionException;
+import com.intellij.execution.Executor;
import com.intellij.execution.RunnerRegistry;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.runners.ExecutionEnvironment;
@@ -83,7 +84,8 @@ public final class JavadocGenerationManager implements PersistentStateComponent<
try {
final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(DefaultRunExecutor.EXECUTOR_ID, myConfiguration);
assert runner != null;
- runner.execute(DefaultRunExecutor.getRunExecutorInstance(), new ExecutionEnvironment(myConfiguration, myProject, null, null, null));
+ Executor executor = DefaultRunExecutor.getRunExecutorInstance();
+ runner.execute(new ExecutionEnvironment(myConfiguration ,executor, myProject, null));
}
catch (ExecutionException e) {
ExecutionErrorDialog.show(e, CommonBundle.getErrorTitle(), myProject);
diff --git a/java/java-impl/src/com/intellij/lang/java/JavaLiteralEscaper.java b/java/java-impl/src/com/intellij/lang/java/JavaLiteralEscaper.java
deleted file mode 100644
index 4d3712d6ae08..000000000000
--- a/java/java-impl/src/com/intellij/lang/java/JavaLiteralEscaper.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2000-2009 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.lang.java;
-
-import com.intellij.lang.LiteralEscaper;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiJavaToken;
-import com.intellij.psi.JavaTokenType;
-import com.intellij.openapi.util.text.StringUtil;
-
-/**
- * @author yole
- */
-public class JavaLiteralEscaper implements LiteralEscaper {
- @Override
- public String getEscapedText(final PsiElement context, final String originalText) {
- if (context instanceof PsiJavaToken && ((PsiJavaToken)context).getTokenType() == JavaTokenType.STRING_LITERAL) {
- return StringUtil.escapeStringCharacters(originalText);
- }
- return originalText;
- }
-
- @Override
- public String escapeText(String originalText) {
- return StringUtil.escapeStringCharacters(originalText);
- }
-
- @Override
- public String unescapeText(String originalText) {
- return StringUtil.unescapeStringCharacters(originalText);
- }
-}
diff --git a/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java b/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java
index e8e66664f4d9..a86e3a6b7e7c 100644
--- a/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java
+++ b/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java
@@ -28,6 +28,7 @@ import com.intellij.psi.CommonClassNames;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -41,7 +42,7 @@ public class JavaModuleType extends ModuleType<JavaModuleBuilder> {
public static final String MODULE_NAME = ProjectBundle.message("module.type.java.name");
public static final String JAVA_GROUP = "Java";
- private static final String JAVA_MODULE = "JAVA_MODULE";
+ private static final String JAVA_MODULE = ModuleTypeId.JAVA_MODULE;
public JavaModuleType() {
this(JAVA_MODULE);
@@ -51,16 +52,19 @@ public class JavaModuleType extends ModuleType<JavaModuleBuilder> {
super(id);
}
+ @NotNull
@Override
public JavaModuleBuilder createModuleBuilder() {
return new JavaModuleBuilder();
}
+ @NotNull
@Override
public String getName() {
return MODULE_NAME;
}
+ @NotNull
@Override
public String getDescription() {
return ProjectBundle.message("module.type.java.description");
@@ -76,9 +80,10 @@ public class JavaModuleType extends ModuleType<JavaModuleBuilder> {
return getJavaModuleNodeIconClosed();
}
+ @NotNull
@Override
- public ModuleWizardStep[] createWizardSteps(final WizardContext wizardContext, final JavaModuleBuilder moduleBuilder,
- final ModulesProvider modulesProvider) {
+ public ModuleWizardStep[] createWizardSteps(@NotNull final WizardContext wizardContext, @NotNull final JavaModuleBuilder moduleBuilder,
+ @NotNull final ModulesProvider modulesProvider) {
final ProjectWizardStepFactory wizardFactory = ProjectWizardStepFactory.getInstance();
ArrayList<ModuleWizardStep> steps = new ArrayList<ModuleWizardStep>();
final ModuleWizardStep supportForFrameworksStep = wizardFactory.createSupportForFrameworksStep(wizardContext, moduleBuilder, modulesProvider);
@@ -91,7 +96,7 @@ public class JavaModuleType extends ModuleType<JavaModuleBuilder> {
@Nullable
@Override
- public ModuleWizardStep modifySettingsStep(SettingsStep settingsStep, final ModuleBuilder moduleBuilder) {
+ public ModuleWizardStep modifySettingsStep(@NotNull SettingsStep settingsStep, @NotNull final ModuleBuilder moduleBuilder) {
return ProjectWizardStepFactory.getInstance().createJavaSettingsStep(settingsStep, moduleBuilder, new Condition<SdkTypeId>() {
@Override
public boolean value(SdkTypeId sdkType) {
@@ -118,13 +123,13 @@ public class JavaModuleType extends ModuleType<JavaModuleBuilder> {
}
@Override
- public boolean isValidSdk(final Module module, final Sdk projectSdk) {
+ public boolean isValidSdk(@NotNull final Module module, final Sdk projectSdk) {
return isValidJavaSdk(module);
}
- public static boolean isValidJavaSdk(final Module module) {
+ public static boolean isValidJavaSdk(@NotNull Module module) {
if (ModuleRootManager.getInstance(module).getSourceRoots().length == 0) return true;
- return JavaPsiFacade.getInstance(module.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT,
+ return JavaPsiFacade.getInstance(module.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT,
module.getModuleWithLibrariesScope()) != null;
}
}
diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java
index 016e9f737156..76e9875e42c0 100644
--- a/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java
+++ b/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java
@@ -15,36 +15,16 @@
*/
package com.intellij.openapi.projectRoots;
-import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.util.Disposer;
import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
+import org.jetbrains.annotations.NotNull;
/**
* @author anna
* @since 3/28/12
*/
public class JavaVersionServiceImpl extends JavaVersionService {
- private JavaSdkVersion myTestVersion = JavaSdkVersion.JDK_1_7;
-
- @TestOnly
- public void setTestVersion(@Nullable JavaSdkVersion testVersion, Disposable parentDisposable) {
- myTestVersion = testVersion;
- Disposer.register(parentDisposable, new Disposable() {
- @Override
- public void dispose() {
- myTestVersion = JavaSdkVersion.JDK_1_7;
- }
- });
- }
-
@Override
- public boolean isAtLeast(PsiElement element, JavaSdkVersion version) {
- if (ApplicationManager.getApplication().isUnitTestMode()) {
- return myTestVersion != null && myTestVersion.isAtLeast(version);
- }
+ public boolean isAtLeast(@NotNull PsiElement element, @NotNull JavaSdkVersion version) {
return JavaSdkVersionUtil.isAtLeast(element, version);
}
}
diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java
index 248f5a7978d5..ad59dda1c471 100644
--- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java
+++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java
@@ -314,7 +314,7 @@ public class JavaSdkImpl extends JavaSdk {
@Override
@SuppressWarnings({"HardCodedStringLiteral"})
- public void setupSdkPaths(Sdk sdk) {
+ public void setupSdkPaths(@NotNull Sdk sdk) {
final File jdkHome = new File(sdk.getHomePath());
List<VirtualFile> classes = findClasses(jdkHome, false);
VirtualFile sources = findSources(jdkHome);
@@ -427,10 +427,6 @@ public class JavaSdkImpl extends JavaSdk {
@Override
public JavaSdkVersion getVersion(@NotNull Sdk sdk) {
- return getVersion1(sdk);
- }
-
- private static JavaSdkVersion getVersion1(Sdk sdk) {
String version = sdk.getVersionString();
if (version == null) return null;
return JdkVersionUtil.getVersion(version);
diff --git a/java/java-impl/src/com/intellij/openapi/roots/impl/JavaLanguageLevelPusher.java b/java/java-impl/src/com/intellij/openapi/roots/impl/JavaLanguageLevelPusher.java
index 8a12fac0e341..b177f9a9aa12 100644
--- a/java/java-impl/src/com/intellij/openapi/roots/impl/JavaLanguageLevelPusher.java
+++ b/java/java-impl/src/com/intellij/openapi/roots/impl/JavaLanguageLevelPusher.java
@@ -27,6 +27,7 @@ import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.util.io.DataInputOutputUtil;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -42,7 +43,7 @@ public class JavaLanguageLevelPusher implements FilePropertyPusher<LanguageLevel
}
@Override
- public void initExtra(Project project, MessageBus bus, Engine languageLevelUpdater) {
+ public void initExtra(@NotNull Project project, @NotNull MessageBus bus, @NotNull Engine languageLevelUpdater) {
// nothing
}
@@ -64,24 +65,24 @@ public class JavaLanguageLevelPusher implements FilePropertyPusher<LanguageLevel
}
@Override
- public LanguageLevel getImmediateValue(Project project, VirtualFile file) {
+ public LanguageLevel getImmediateValue(@NotNull Project project, @Nullable VirtualFile file) {
return null;
}
@Override
- public LanguageLevel getImmediateValue(Module module) {
+ public LanguageLevel getImmediateValue(@NotNull Module module) {
return LanguageLevelUtil.getEffectiveLanguageLevel(module);
}
@Override
- public boolean acceptsFile(VirtualFile file) {
+ public boolean acceptsFile(@NotNull VirtualFile file) {
return false;
}
private static final FileAttribute PERSISTENCE = new FileAttribute("language_level_persistence", 2, true);
@Override
- public void persistAttribute(VirtualFile fileOrDir, @NotNull LanguageLevel level) throws IOException {
+ public void persistAttribute(@NotNull VirtualFile fileOrDir, @NotNull LanguageLevel level) throws IOException {
final DataInputStream iStream = PERSISTENCE.readAttribute(fileOrDir);
if (iStream != null) {
try {
@@ -105,6 +106,6 @@ public class JavaLanguageLevelPusher implements FilePropertyPusher<LanguageLevel
}
@Override
- public void afterRootsChanged(Project project) {
+ public void afterRootsChanged(@NotNull Project project) {
}
}
diff --git a/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java b/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java
index 17d937611b17..af890621d62f 100644
--- a/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java
+++ b/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java
@@ -178,7 +178,8 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
@Override
public boolean processPackageDirectories(@NotNull PsiPackage psiPackage,
@NotNull GlobalSearchScope scope,
- @NotNull Processor<PsiDirectory> consumer) {
+ @NotNull Processor<PsiDirectory> consumer,
+ boolean includeLibrarySources) {
final List<VirtualFile> classRoots = getClassRoots();
if (classRoots.isEmpty()) {
return true;
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java
index d5b7e90b2fe6..b65393f3a4b3 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java
@@ -18,9 +18,9 @@ package com.intellij.psi.formatter.java;
import com.intellij.formatting.*;
import com.intellij.formatting.alignment.AlignmentStrategy;
import com.intellij.lang.ASTNode;
+import com.intellij.psi.JavaDocTokenType;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.formatter.FormatterUtil;
-import com.intellij.psi.impl.source.tree.ElementType;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -37,7 +37,7 @@ public class DocCommentBlock extends AbstractJavaBlock{
ASTNode child = myNode.getFirstChildNode();
while (child != null) {
- if (child.getElementType() == ElementType.DOC_COMMENT_START) {
+ if (child.getElementType() == JavaDocTokenType.DOC_COMMENT_START) {
result.add(createJavaBlock(child, mySettings, Indent.getNoneIndent(), null, AlignmentStrategy.getNullStrategy()));
} else if (!FormatterUtil.containsWhiteSpacesOnly(child) && child.getText().trim().length() > 0){
result.add(createJavaBlock(child, mySettings, Indent.getSpaceIndent(1), null, AlignmentStrategy.getNullStrategy()));
diff --git a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java
index 1594b3b3674e..0309800ad813 100644
--- a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java
+++ b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java
@@ -39,6 +39,7 @@ class AnchorElementInfo extends SelfElementInfo {
AnchorElementInfo(@NotNull PsiElement anchor, @NotNull PsiFile containingFile) {
super(containingFile.getProject(), ProperTextRange.create(anchor.getTextRange()), anchor.getClass(), containingFile,
containingFile.getLanguage());
+ assert !(anchor instanceof PsiFile) : "FileElementInfo must be used for file: "+anchor;
}
// will restore by stub index until file tree get loaded
AnchorElementInfo(@NotNull PsiElement anchor,
@@ -50,18 +51,19 @@ class AnchorElementInfo extends SelfElementInfo {
myStubElementType = stubElementType;
IElementType contentElementType = ((PsiFileImpl)containingFile).getContentElementType();
assert contentElementType instanceof IStubFileElementType : contentElementType;
+ assert !(anchor instanceof PsiFile) : "FileElementInfo must be used for file: "+anchor;
}
@Override
@Nullable
public PsiElement restoreElement() {
if (stubId != -1) {
- PsiFile file = SelfElementInfo.restoreFileFromVirtual(getVirtualFile(), myProject);
+ PsiFile file = restoreFile();
if (!(file instanceof PsiFileWithStubSupport)) return null;
return PsiAnchor.restoreFromStubIndex((PsiFileWithStubSupport)file, stubId, myStubElementType, false);
}
if (!mySyncMarkerIsValid) return null;
- PsiFile file = SelfElementInfo.restoreFileFromVirtual(getVirtualFile(), myProject);
+ PsiFile file = restoreFile();
if (file == null) return null;
PsiElement anchor = file.findElementAt(getSyncStartOffset());
if (anchor == null) return null;
diff --git a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfoFactory.java b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfoFactory.java
index 57f919f9e63e..a3ed29f87ddd 100644
--- a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfoFactory.java
+++ b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfoFactory.java
@@ -15,7 +15,6 @@
*/
package com.intellij.psi.impl.smartPointers;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiFileWithStubSupport;
import com.intellij.psi.stubs.IStubElementType;
@@ -27,8 +26,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class AnchorElementInfoFactory implements SmartPointerElementInfoFactory {
- private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.smartPointers.AnchorElementInfoFactory");
-
@Override
@Nullable
public SmartPointerElementInfo createElementInfo(@NotNull PsiElement element) {
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/FormatCommentsProcessor.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/FormatCommentsProcessor.java
index 5c80f43240d7..841b8b530e16 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/FormatCommentsProcessor.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/FormatCommentsProcessor.java
@@ -16,9 +16,11 @@
package com.intellij.psi.impl.source.codeStyle;
import com.intellij.lang.ASTNode;
-import com.intellij.lang.StdLanguages;
+import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
@@ -31,57 +33,65 @@ public class FormatCommentsProcessor implements PreFormatProcessor {
@NotNull
@Override
public TextRange process(@NotNull final ASTNode element, @NotNull final TextRange range) {
- final Project project = SourceTreeToPsiMap.treeElementToPsi(element).getProject();
+ PsiElement e = SourceTreeToPsiMap.treeElementToPsi(element);
+ assert e != null;
+ final Project project = e.getProject();
if (!CodeStyleSettingsManager.getSettings(project).ENABLE_JAVADOC_FORMATTING ||
- element.getPsi().getContainingFile().getLanguage() != StdLanguages.JAVA) {
+ element.getPsi().getContainingFile().getLanguage() != JavaLanguage.INSTANCE)
+ {
return range;
}
-
return formatCommentsInner(project, element, range);
}
- private static TextRange formatCommentsInner(Project project, ASTNode element, final TextRange range) {
- TextRange result = range;
-
-
- // check for RepositoryTreeElement is optimization
- if (shouldProcess(element)) {
- final TextRange elementRange = element.getTextRange();
+ /**
+ * Formats PsiDocComments of current ASTNode element and all his children PsiDocComments
+ */
+ @NotNull
+ private static TextRange formatCommentsInner(@NotNull Project project, @NotNull ASTNode element, @NotNull final TextRange markedRange) {
+ TextRange resultTextRange = markedRange;
+ final PsiElement elementPsi = element.getPsi();
+ boolean shouldFormat = markedRange.contains(element.getTextRange());
- if (range.contains(elementRange)) {
- new CommentFormatter(project).process(element);
- final TextRange newRange = element.getTextRange();
- result = new TextRange(range.getStartOffset(), range.getEndOffset() + newRange.getLength() - elementRange.getLength());
+ if (shouldFormat) {
+ final ASTNode rangeAnchor;
+ // There are two possible cases:
+ // 1. Given element correspond to comment's owner (e.g. field or method);
+ // 2. Given element corresponds to comment itself;
+ // However, doc comment formatter replaces old comment with the new one, hence, old element becomes invalid. That's why we need
+ // to calculate text length delta not for the given comment element (it's invalid because removed from the AST tree) but for
+ // its parent.
+ if (elementPsi instanceof PsiDocComment) {
+ rangeAnchor = element.getTreeParent();
}
-
- // optimization, does not seek PsiDocComment inside fields / methods or out of range
- if (element.getPsi() instanceof PsiField ||
- element.getPsi() instanceof PsiMethod ||
- element instanceof PsiDocComment ||
- range.getEndOffset() < elementRange.getStartOffset()
- ) {
- return result;
+ else {
+ rangeAnchor = element;
}
+ TextRange before = rangeAnchor.getTextRange();
+ new CommentFormatter(project).processComment(element);
+ int deltaRange = rangeAnchor.getTextRange().getLength() - before.getLength();
+ resultTextRange = new TextRange(markedRange.getStartOffset(), markedRange.getEndOffset() + deltaRange);
+ }
+
+
+ // If element is Psi{Method, Field, DocComment} and was formatted there is no reason to continue - we formatted all possible javadocs.
+ // If element is out of range its children are also out of range. So in both cases formatting is finished. It's just for optimization.
+ if ((shouldFormat && (elementPsi instanceof PsiMethod || elementPsi instanceof PsiField || elementPsi instanceof PsiDocComment))
+ || markedRange.getEndOffset() < element.getStartOffset())
+ {
+ return resultTextRange;
}
ASTNode current = element.getFirstChildNode();
while (current != null) {
- // we expand the chameleons here for effectiveness
- current.getFirstChildNode();
- result = formatCommentsInner(project, current, result);
+ // When element is PsiClass its PsiDocComment is formatted up to this moment, so we didn't need to format it again.
+ if (!(shouldFormat && current.getPsi() instanceof PsiDocComment && elementPsi instanceof PsiClass)) {
+ resultTextRange = formatCommentsInner(project, current, resultTextRange);
+ }
current = current.getTreeNext();
}
- return result;
- }
- private static boolean shouldProcess(final ASTNode element) {
- if (element instanceof PsiDocComment) {
- return true;
- }
- else {
- return true;//element.getElementType() instanceof JavaStubElementType &&
- //(element.getPsi()) instanceof PsiDocCommentOwner;
- }
+ return resultTextRange;
}
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
index 8beff5d7b21e..0fe403b84ff8 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
@@ -748,8 +748,11 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
String suffix = getSuffixByVariableKind(variableKind);
boolean doDecapitalize = false;
- if (name.startsWith(prefix) && name.length() > prefix.length()) {
- name = name.substring(prefix.length());
+ int pLength = prefix.length();
+ if (pLength > 0 && name.startsWith(prefix) && name.length() > pLength &&
+ // check it's not just a long camel word that happens to begin with the specified prefix
+ (!Character.isJavaIdentifierPart(prefix.charAt(pLength - 1)) || Character.isUpperCase(name.charAt(pLength)))) {
+ name = name.substring(pLength);
doDecapitalize = true;
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/CommentFormatter.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/CommentFormatter.java
index 9f900c0f6573..624c5370c4ad 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/CommentFormatter.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/CommentFormatter.java
@@ -15,16 +15,21 @@
*/
package com.intellij.psi.impl.source.codeStyle.javadoc;
+import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.lang.ASTNode;
+import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.LineTokenizer;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.javadoc.PsiDocComment;
+import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -38,7 +43,7 @@ public class CommentFormatter {
private final JDParser myParser;
private final Project myProject;
- public CommentFormatter(Project project) {
+ public CommentFormatter(@NotNull Project project) {
mySettings = CodeStyleSettingsManager.getSettings(project);
myParser = new JDParser(mySettings);
myProject = project;
@@ -52,14 +57,14 @@ public class CommentFormatter {
return myParser;
}
- public void process(ASTNode element) {
+ public void processComment(@Nullable ASTNode element) {
if (!getSettings().ENABLE_JAVADOC_FORMATTING) return;
PsiElement psiElement = SourceTreeToPsiMap.treeElementToPsi(element);
processElementComment(psiElement);
}
- private void processElementComment(PsiElement psiElement) {
+ private void processElementComment(@Nullable PsiElement psiElement) {
if (psiElement instanceof PsiClass) {
String newCommentText = formatClassComment((PsiClass)psiElement);
replaceDocComment(newCommentText, (PsiDocCommentOwner)psiElement);
@@ -77,7 +82,7 @@ public class CommentFormatter {
}
}
- private void replaceDocComment(String newCommentText, final PsiDocCommentOwner psiDocCommentOwner) {
+ private void replaceDocComment(@Nullable String newCommentText, @NotNull final PsiDocCommentOwner psiDocCommentOwner) {
final PsiDocComment oldComment = psiDocCommentOwner.getDocComment();
if (newCommentText != null) newCommentText = stripSpaces(newCommentText);
if (newCommentText == null || oldComment == null || newCommentText.equals(oldComment.getText())) {
@@ -99,7 +104,7 @@ public class CommentFormatter {
private static String stripSpaces(String text) {
String[] lines = LineTokenizer.tokenize(text.toCharArray(), false);
- StringBuffer buf = new StringBuffer(text.length());
+ StringBuilder buf = new StringBuilder(text.length());
for (int i = 0; i < lines.length; i++) {
if (i > 0) buf.append('\n');
buf.append(rTrim(lines[i]));
@@ -117,7 +122,7 @@ public class CommentFormatter {
}
@Nullable
- private String formatClassComment(PsiClass psiClass) {
+ private String formatClassComment(@NotNull PsiClass psiClass) {
final String info = getOrigCommentInfo(psiClass);
if (info == null) return null;
@@ -126,7 +131,7 @@ public class CommentFormatter {
}
@Nullable
- private String formatMethodComment(PsiMethod psiMethod) {
+ private String formatMethodComment(@NotNull PsiMethod psiMethod) {
final String info = getOrigCommentInfo(psiMethod);
if (info == null) return null;
@@ -135,7 +140,7 @@ public class CommentFormatter {
}
@Nullable
- private String formatFieldComment(PsiField psiField) {
+ private String formatFieldComment(@NotNull PsiField psiField) {
final String info = getOrigCommentInfo(psiField);
if (info == null) return null;
@@ -149,8 +154,9 @@ public class CommentFormatter {
* @param element the specified element
* @return text chunk
*/
+ @Nullable
private static String getOrigCommentInfo(PsiDocCommentOwner element) {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
PsiElement e = element.getFirstChild();
if (!(e instanceof PsiComment)) {
// no comments for this element
@@ -188,39 +194,38 @@ public class CommentFormatter {
}
/**
- * For the specified element returns its indentation
- *
- * @param element the specified element
- * @return indentation as string
+ * Computes indentation of PsiClass, PsiMethod and PsiField elements after formatting
+ * @param element PsiClass or PsiMethod or PsiField
+ * @return indentation size
*/
- private static String getIndent(PsiElement element) {
- PsiElement e = element.getFirstChild();
- PsiWhiteSpace lastWS = null;
- for (; ; e = e.getNextSibling()) {
- if (e instanceof PsiWhiteSpace) {
- lastWS = (PsiWhiteSpace)e;
- }
- else if (e instanceof PsiComment) {
- lastWS = null;
- }
- else {
+ private int getIndentSpecial(@NotNull PsiElement element) {
+ assert(element instanceof PsiClass ||
+ element instanceof PsiField ||
+ element instanceof PsiMethod);
+
+ int indentSize = mySettings.getIndentSize(JavaFileType.INSTANCE);
+ boolean doNotIndentTopLevelClassMembers = mySettings.getCommonSettings(JavaLanguage.INSTANCE).DO_NOT_INDENT_TOP_LEVEL_CLASS_MEMBERS;
+
+ int indent = 0;
+ PsiClass top = PsiUtil.getTopLevelClass(element);
+ while (top != null && !element.isEquivalentTo(top)) {
+ if (doNotIndentTopLevelClassMembers && element.getParent().isEquivalentTo(top)) {
break;
}
+ element = element.getParent();
+ indent += indentSize;
}
- e = lastWS == null ? element.getPrevSibling() : lastWS;
- if (!(e instanceof PsiWhiteSpace)) return "";
- PsiWhiteSpace ws = (PsiWhiteSpace)e;
- String t = ws.getText();
- int l = t.length();
- int i = l;
- while (--i >= 0) {
- char ch = t.charAt(i);
- if (ch == '\n' || ch == '\r') break;
- }
- if (i < 0) return t;
- i++;
- if (i == l) return "";
- return t.substring(i);
+ return indent;
+ }
+
+ /**
+ * Used while formatting javadocs. We need precise element indentation after formatting to wrap comments correctly.
+ * Used only for PsiClass, PsiMethod and PsiFields.
+ * @return indent which would be used for the given element when it's formatted according to the current code style settings
+ */
+ @NotNull
+ private String getIndent(@NotNull PsiElement element) {
+ return StringUtil.repeatSymbol(' ', getIndentSpecial(element));
}
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDComment.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDComment.java
index 28dc6a359942..740b77cb2228 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDComment.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDComment.java
@@ -36,6 +36,7 @@ public class JDComment {
private List<String> mySeeAlsoList;
private String mySince;
private String myDeprecated;
+ private boolean myMultiLineComment;
public JDComment(@NotNull CommentFormatter formatter) {
myFormatter = formatter;
@@ -49,6 +50,10 @@ public class JDComment {
return l == null || l.size() == 0;
}
+ public void setMultiLine(boolean value) {
+ myMultiLineComment = value;
+ }
+
@Nullable
public String generate(@NotNull String indent) {
final String prefix;
@@ -118,12 +123,14 @@ public class JDComment {
sb.delete(nlen, sb.length());
}
- if( !myFormatter.getSettings().JD_DO_NOT_WRAP_ONE_LINE_COMMENTS ||
- sb.indexOf("\n") != sb.length()-1 ) {
+ if (myMultiLineComment && myFormatter.getSettings().JD_DO_NOT_WRAP_ONE_LINE_COMMENTS
+ || !myFormatter.getSettings().JD_DO_NOT_WRAP_ONE_LINE_COMMENTS
+ || sb.indexOf("\n") != sb.length() - 1) // If comment has become multiline after formatting - it must be shown as multiline.
+ // Last symbol is always '\n', so we need to check if there is one more LF symbol before it.
+ {
sb.insert(0, "/**\n");
sb.append(indent);
- }
- else {
+ } else {
sb.replace(0, prefix.length(), "/** ");
sb.deleteCharAt(sb.length()-1);
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java
index 859e848d3304..f4ba00070611 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDParser.java
@@ -47,14 +47,24 @@ public class JDParser {
private static final char lineSeparator = '\n';
@NotNull
- public JDComment parse(@Nullable String text, @NotNull JDComment c) {
- if (text == null) return c;
+ public JDComment parse(@Nullable String text, @NotNull JDComment comment) {
+ if (text == null) return comment;
List<Boolean> markers = new ArrayList<Boolean>();
List<String> l = toArray(text, "\n", markers);
- if (l == null) return c;
+
+ //if it is - we are dealing with multiline comment:
+ // /**
+ // * comment
+ // */
+ //which shouldn't be wrapped into one line comment like /** comment */
+ if (text.indexOf('\n') >= 0) {
+ comment.setMultiLine(true);
+ }
+
+ if (l == null) return comment;
int size = l.size();
- if (size == 0) return c;
+ if (size == 0) return comment;
// preprocess strings - removes first '*'
for (int i = 0; i < size; i++) {
@@ -85,17 +95,17 @@ public class JDParser {
if (i == size || line.length() > 0) {
if (i == size || line.charAt(0) == '@') {
if (tag == null) {
- c.setDescription(sb.toString());
+ comment.setDescription(sb.toString());
}
else {
int j = 0;
String myline = sb.toString();
for (; j < tagParsers.length; j++) {
TagParser parser = tagParsers[j];
- if (parser.parse(tag, myline, c)) break;
+ if (parser.parse(tag, myline, comment)) break;
}
if (j == tagParsers.length) {
- c.addUnknownTag("@" + tag + " " + myline);
+ comment.addUnknownTag("@" + tag + " " + myline);
}
}
@@ -127,7 +137,7 @@ public class JDParser {
}
}
- return c;
+ return comment;
}
/**
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/GenericReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/GenericReference.java
index 83e623b64cfe..ca65db6af59f 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/GenericReference.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/GenericReference.java
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.impl.source.resolve.reference.impl;
+import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
import com.intellij.psi.*;
import com.intellij.psi.PsiReferenceProvider;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.GenericReferenceProvider;
@@ -29,7 +30,7 @@ import org.jetbrains.annotations.Nullable;
* Time: 17:33:24
* To change this template use Options | File Templates.
*/
-public abstract class GenericReference extends CachingReference {
+public abstract class GenericReference extends CachingReference implements EmptyResolveMessageProvider {
public static final GenericReference[] EMPTY_ARRAY = new GenericReference[0];
@Nullable
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java
index d14698237643..604b90e896d6 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java
@@ -23,10 +23,8 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.util.ProcessingContext;
-import com.intellij.util.containers.*;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -166,7 +164,7 @@ public class FilePathReferenceProvider extends PsiReferenceProvider {
final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(directory);
if (aPackage != null && aPackage.getName() != null) {
// package prefix
- result.add(PackagePrefixFileSystemItem.create(directory));
+ result.add(PackagePrefixFileSystemItemImpl.create(directory));
}
else {
result.add(directory);
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java
index 4a379e02abb2..5e4f2790d25e 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java
@@ -17,7 +17,6 @@ package com.intellij.psi.impl.source.resolve.reference.impl.providers;
import com.intellij.codeInsight.completion.JavaLookupElementBuilder;
import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
-import com.intellij.codeInsight.daemon.QuickFixProvider;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
@@ -68,7 +67,7 @@ import java.util.Map;
/**
* @author peter
*/
-public class JavaClassReference extends GenericReference implements PsiJavaReference, QuickFixProvider, LocalQuickFixProvider {
+public class JavaClassReference extends GenericReference implements PsiJavaReference, LocalQuickFixProvider {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReference");
protected final int myIndex;
private TextRange myRange;
@@ -94,7 +93,7 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer
}
@Override
- public void processVariants(final PsiScopeProcessor processor) {
+ public void processVariants(@NotNull final PsiScopeProcessor processor) {
if (processor instanceof JavaCompletionProcessor) {
final Map<CustomizableReferenceProvider.CustomizationKey, Object> options = getOptions();
if (options != null &&
@@ -472,11 +471,6 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer
return new JavaResolveResult[]{javaResolveResult};
}
- @Override
- public void registerQuickfix(HighlightInfo info, PsiReference reference) {
- registerFixes(info);
- }
-
@Nullable
private List<? extends LocalQuickFix> registerFixes(final HighlightInfo info) {
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PackagePrefixFileSystemItem.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PackagePrefixFileSystemItemImpl.java
index 022f69acc9b7..7b85d17470ed 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PackagePrefixFileSystemItem.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PackagePrefixFileSystemItemImpl.java
@@ -36,20 +36,20 @@ import java.util.ArrayList;
/**
* @author Gregory.Shrago
*/
-class PackagePrefixFileSystemItem extends PsiElementBase implements PsiFileSystemItem {
+class PackagePrefixFileSystemItemImpl extends PsiElementBase implements PsiFileSystemItem, PackagePrefixFileSystemItem {
private final PsiDirectory myDirectory;
private final int myIndex;
private final PsiPackage[] myPackages;
- public static PackagePrefixFileSystemItem create(final PsiDirectory directory) {
+ public static PackagePrefixFileSystemItemImpl create(final PsiDirectory directory) {
final ArrayList<PsiPackage> packages = new ArrayList<PsiPackage>();
for (PsiPackage cur = JavaDirectoryService.getInstance().getPackage(directory); cur != null; cur = cur.getParentPackage()) {
packages.add(0, cur);
}
- return new PackagePrefixFileSystemItem(directory, 0, packages.toArray(new PsiPackage[packages.size()]));
+ return new PackagePrefixFileSystemItemImpl(directory, 0, packages.toArray(new PsiPackage[packages.size()]));
}
- private PackagePrefixFileSystemItem(final PsiDirectory directory, int index, final PsiPackage[] packages) {
+ private PackagePrefixFileSystemItemImpl(final PsiDirectory directory, int index, final PsiPackage[] packages) {
myDirectory = directory;
myIndex = index;
myPackages = packages;
@@ -78,7 +78,7 @@ class PackagePrefixFileSystemItem extends PsiElementBase implements PsiFileSyste
@Override
public PsiFileSystemItem getParent() {
- return myIndex > 0 ? new PackagePrefixFileSystemItem(myDirectory, myIndex - 1, myPackages) : myDirectory.getParent();
+ return myIndex > 0 ? new PackagePrefixFileSystemItemImpl(myDirectory, myIndex - 1, myPackages) : myDirectory.getParent();
}
@Override
@@ -207,7 +207,7 @@ class PackagePrefixFileSystemItem extends PsiElementBase implements PsiFileSyste
return myDirectory.processChildren(processor);
}
else {
- return processor.execute(new PackagePrefixFileSystemItem(myDirectory, myIndex+1, myPackages));
+ return processor.execute(new PackagePrefixFileSystemItemImpl(myDirectory, myIndex+1, myPackages));
}
}
@@ -225,7 +225,7 @@ class PackagePrefixFileSystemItem extends PsiElementBase implements PsiFileSyste
@Override
@NotNull
public PsiElement[] getChildren() {
- return myIndex == myPackages.length -1? myDirectory.getChildren() : new PsiElement[] {new PackagePrefixFileSystemItem(myDirectory, myIndex + 1, myPackages)};
+ return myIndex == myPackages.length -1? myDirectory.getChildren() : new PsiElement[] {new PackagePrefixFileSystemItemImpl(myDirectory, myIndex + 1, myPackages)};
}
@Override
@@ -248,4 +248,9 @@ class PackagePrefixFileSystemItem extends PsiElementBase implements PsiFileSyste
public Icon getIcon(final int flags) {
return myDirectory.getIcon(flags);
}
+
+ @Override
+ public PsiDirectory getDirectory() {
+ return myDirectory;
+ }
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiPackageReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiPackageReference.java
index 537b3216df4d..8e287ac310a7 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiPackageReference.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiPackageReference.java
@@ -40,7 +40,7 @@ public class PsiPackageReference extends PsiPolyVariantReferenceBase<PsiElement>
private Set<PsiPackage> getContext() {
if (myIndex == 0) return myReferenceSet.getInitialContext();
Set<PsiPackage> psiPackages = new HashSet<PsiPackage>();
- for (ResolveResult resolveResult : myReferenceSet.getReference(myIndex - 1).multiResolve(false)) {
+ for (ResolveResult resolveResult : myReferenceSet.getReference(myIndex - 1).doMultiResolve()) {
PsiElement psiElement = resolveResult.getElement();
if (psiElement instanceof PsiPackage) {
psiPackages.add((PsiPackage)psiElement);
@@ -69,6 +69,11 @@ public class PsiPackageReference extends PsiPolyVariantReferenceBase<PsiElement>
@Override
@NotNull
public ResolveResult[] multiResolve(final boolean incompleteCode) {
+ return doMultiResolve();
+ }
+
+ @NotNull
+ protected ResolveResult[] doMultiResolve() {
final Collection<PsiPackage> packages = new HashSet<PsiPackage>();
for (PsiPackage parentPackage : getContext()) {
packages.addAll(myReferenceSet.resolvePackageName(parentPackage, getValue()));
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/JavaConcatenationInjectorManager.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/JavaConcatenationInjectorManager.java
index 5b4dd7af48b7..7d70ee9f2cb3 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/JavaConcatenationInjectorManager.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/JavaConcatenationInjectorManager.java
@@ -72,7 +72,7 @@ public class JavaConcatenationInjectorManager implements ModificationTracker {
return myModificationCounter;
}
- private static Pair<PsiElement,PsiElement[]> computeAnchorAndOperandsImpl(PsiElement context) {
+ private static Pair<PsiElement,PsiElement[]> computeAnchorAndOperandsImpl(@NotNull PsiElement context) {
PsiElement element = context;
PsiElement parent = context.getParent();
while (parent instanceof PsiPolyadicExpression && ((PsiPolyadicExpression)parent).getOperationTokenType() == JavaTokenType.PLUS
@@ -102,8 +102,12 @@ public class JavaConcatenationInjectorManager implements ModificationTracker {
return Pair.create(anchor, operands);
}
- private static MultiHostRegistrarImpl doCompute(PsiElement context, Project project, PsiElement anchor, PsiElement[] operands) {
- MultiHostRegistrarImpl registrar = new MultiHostRegistrarImpl(project, context.getContainingFile(), anchor);
+
+ private static MultiHostRegistrarImpl doCompute(@NotNull PsiFile containingFile,
+ @NotNull Project project,
+ @NotNull PsiElement anchor,
+ @NotNull PsiElement[] operands) {
+ MultiHostRegistrarImpl registrar = new MultiHostRegistrarImpl(project, containingFile, anchor);
JavaConcatenationInjectorManager concatenationInjectorManager = getInstance(project);
for (ConcatenationAwareInjector concatenationInjector : concatenationInjectorManager.myConcatenationInjectors) {
concatenationInjector.getLanguagesToInject(registrar, operands);
@@ -119,7 +123,7 @@ public class JavaConcatenationInjectorManager implements ModificationTracker {
private static final Key<ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement>> INJECTED_PSI_IN_CONCATENATION = Key.create("INJECTED_PSI_IN_CONCATENATION");
private static final Key<Integer> NO_CONCAT_INJECTION_TIMESTAMP = Key.create("NO_CONCAT_INJECTION_TIMESTAMP");
- public static abstract class BaseConcatenation2InjectorAdapter implements MultiHostInjector {
+ public abstract static class BaseConcatenation2InjectorAdapter implements MultiHostInjector {
private final JavaConcatenationInjectorManager myManager;
public BaseConcatenation2InjectorAdapter(Project project) {
@@ -130,7 +134,8 @@ public class JavaConcatenationInjectorManager implements ModificationTracker {
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
if (myManager.myConcatenationInjectors.isEmpty()) return;
- Project project = context.getProject();
+ final PsiFile containingFile = ((MultiHostRegistrarImpl)registrar).getHostPsiFile();
+ Project project = containingFile.getProject();
long modificationCount = PsiManager.getInstance(project).getModificationTracker().getModificationCount();
Pair<PsiElement, PsiElement[]> pair = computeAnchorAndOperands(context);
PsiElement anchor = pair.first;
@@ -146,7 +151,7 @@ public class JavaConcatenationInjectorManager implements ModificationTracker {
data = anchor.getUserData(INJECTED_PSI_IN_CONCATENATION);
if (data == null) {
- result = doCompute(context, project, anchor, operands);
+ result = doCompute(containingFile, project, anchor, operands);
}
else {
result = data.getValue(context);
@@ -164,10 +169,11 @@ public class JavaConcatenationInjectorManager implements ModificationTracker {
new ParameterizedCachedValueProvider<MultiHostRegistrarImpl, PsiElement>() {
@Override
public CachedValueProvider.Result<MultiHostRegistrarImpl> compute(PsiElement context) {
- Project project = context.getProject();
+ PsiFile containingFile1 = context.getContainingFile();
+ Project project1 = containingFile1.getProject();
Pair<PsiElement, PsiElement[]> pair = computeAnchorAndOperands(context);
- MultiHostRegistrarImpl registrar = doCompute(context, project, pair.first, pair.second);
- return registrar == null ? null : CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, getInstance(project));
+ MultiHostRegistrarImpl registrar = doCompute(containingFile1, project1, pair.first, pair.second);
+ return registrar == null ? null : CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, getInstance(project1));
}
}, false);
((PsiParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement>)data).setValue(cachedResult);
@@ -187,7 +193,7 @@ public class JavaConcatenationInjectorManager implements ModificationTracker {
}
}
- protected abstract Pair<PsiElement, PsiElement[]> computeAnchorAndOperands(PsiElement context);
+ protected abstract Pair<PsiElement, PsiElement[]> computeAnchorAndOperands(@NotNull PsiElement context);
}
public static class Concatenation2InjectorAdapter extends BaseConcatenation2InjectorAdapter implements MultiHostInjector {
@@ -197,7 +203,7 @@ public class JavaConcatenationInjectorManager implements ModificationTracker {
}
@Override
- public Pair<PsiElement, PsiElement[]> computeAnchorAndOperands(PsiElement context) {
+ public Pair<PsiElement, PsiElement[]> computeAnchorAndOperands(@NotNull PsiElement context) {
return computeAnchorAndOperandsImpl(context);
}
diff --git a/java/java-impl/src/com/intellij/psi/resolve/JavaMethodResolveHelper.java b/java/java-impl/src/com/intellij/psi/resolve/JavaMethodResolveHelper.java
index 3db0c30e8fb4..2a17536550d1 100644
--- a/java/java-impl/src/com/intellij/psi/resolve/JavaMethodResolveHelper.java
+++ b/java/java-impl/src/com/intellij/psi/resolve/JavaMethodResolveHelper.java
@@ -21,8 +21,8 @@ import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.scope.PsiConflictResolver;
import com.intellij.psi.scope.PsiScopeProcessor;
-import com.intellij.psi.scope.conflictResolvers.JavaMethodsConflictResolver;
import com.intellij.psi.scope.conflictResolvers.DuplicateConflictResolver;
+import com.intellij.psi.scope.conflictResolvers.JavaMethodsConflictResolver;
import com.intellij.psi.scope.processor.MethodCandidatesProcessor;
import com.intellij.psi.scope.processor.MethodResolverProcessor;
import com.intellij.psi.util.MethodSignature;
@@ -33,7 +33,9 @@ import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
import java.util.Set;
/**
@@ -45,11 +47,12 @@ public class JavaMethodResolveHelper {
private final MethodCandidatesProcessor myProcessor;
@Nullable private final PsiType[] myArgumentTypes;
- public JavaMethodResolveHelper(final PsiElement argumentList, @Nullable final PsiType[] argumentTypes) {
+ public JavaMethodResolveHelper(@NotNull final PsiElement argumentList, PsiFile containingFile, @Nullable final PsiType[] argumentTypes) {
myArgumentTypes = argumentTypes;
final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(argumentList);
- final PsiConflictResolver resolver = argumentTypes == null ? DuplicateConflictResolver.INSTANCE : new JavaMethodsConflictResolver(argumentList, argumentTypes);
- myProcessor = new MethodResolverProcessor(argumentList, new PsiConflictResolver[]{resolver}) {
+ final PsiConflictResolver resolver = argumentTypes == null ? DuplicateConflictResolver.INSTANCE : new JavaMethodsConflictResolver(argumentList, argumentTypes,
+ languageLevel);
+ myProcessor = new MethodResolverProcessor(argumentList, containingFile, new PsiConflictResolver[]{resolver}) {
@Override
protected MethodCandidateInfo createCandidateInfo(final PsiMethod method, final PsiSubstitutor substitutor,
final boolean staticProblem,
@@ -72,7 +75,8 @@ public class JavaMethodResolveHelper {
PsiElement currentFileContext,
boolean accessProblem,
PsiElement argumentList,
- PsiType[] argumentTypes, LanguageLevel languageLevel) {
+ PsiType[] argumentTypes,
+ @NotNull LanguageLevel languageLevel) {
return new MethodCandidateInfo(method, substitutor, accessProblem, staticProblem, argumentList, currentFileContext, argumentTypes,
PsiType.EMPTY_ARRAY, languageLevel);
}
@@ -85,12 +89,16 @@ public class JavaMethodResolveHelper {
@NotNull
public ErrorType getResolveError() {
- final CandidateInfo[] candidates = myProcessor.getCandidates();
- if (candidates.length != 1) return ErrorType.RESOLVE;
+ final List<CandidateInfo> candidates = getCandidates();
+ if (candidates.size() != 1) return ErrorType.RESOLVE;
- if (!candidates[0].isStaticsScopeCorrect()) return ErrorType.STATIC;
+ if (!candidates.get(0).isStaticsScopeCorrect()) return ErrorType.STATIC;
+
+ return getResolveError((MethodCandidateInfo)candidates.get(0));
+ }
- return getResolveError((MethodCandidateInfo)candidates[0]);
+ protected List<CandidateInfo> getCandidates() {
+ return Arrays.asList(myProcessor.getCandidates());
}
protected ErrorType getResolveError(MethodCandidateInfo info) {
@@ -125,7 +133,7 @@ public class JavaMethodResolveHelper {
}
public Collection<JavaMethodCandidateInfo> getMethods() {
- return ContainerUtil.mapNotNull(myProcessor.getResult(), new Function<JavaResolveResult, JavaMethodCandidateInfo>() {
+ return ContainerUtil.mapNotNull(getCandidates(), new Function<JavaResolveResult, JavaMethodCandidateInfo>() {
@Override
public JavaMethodCandidateInfo fun(final JavaResolveResult javaResolveResult) {
return new JavaMethodCandidateInfo((PsiMethod)javaResolveResult.getElement(), javaResolveResult.getSubstitutor());
diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java
index b5d0e0966205..8b721b62a009 100644
--- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java
+++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java
@@ -258,10 +258,11 @@ class JavaChangeInfoImpl implements JavaChangeInfo {
}
protected void setupPropagationEnabled(final PsiParameter[] parameters, final ParameterInfoImpl[] newParms) {
- if (parameters.length != newParms.length) {
+ if (parameters.length >= newParms.length) {
isPropagationEnabled = false;
}
else {
+ isPropagationEnabled = !propagateParametersMethods.isEmpty();
for (int i = 0; i < parameters.length; i++) {
final ParameterInfoImpl newParm = newParms[i];
if (newParm.oldParameterIndex != i) {
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 d46fa203f7e0..bfbe8b2413e0 100644
--- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.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.
@@ -192,7 +192,7 @@ public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase<Paramet
myPropExceptionsButton.setShortcut(CustomShortcutSet.fromString("alt X"));
final JPanel panel = ToolbarDecorator.createDecorator(table).addExtraAction(myPropExceptionsButton).createPanel();
- panel.setBorder(IdeBorderFactory.createEmptyBorder(0));
+ panel.setBorder(IdeBorderFactory.createEmptyBorder());
myExceptionsModel.addTableModelListener(mySignatureUpdater);
diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java
index cc4d0cd7443d..e8bb45ce350d 100644
--- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java
@@ -380,7 +380,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
else {
newArg = factory.createExpressionFromText(info.getName(), list);
}
- JavaCodeStyleManager.getInstance(list.getProject()).shortenClassReferences(list.add(newArg));
+ if (newArg != null) JavaCodeStyleManager.getInstance(list.getProject()).shortenClassReferences(list.add(newArg));
}
}
else {
diff --git a/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsDialog.java b/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsDialog.java
index 9943d48fc8d6..e8d41e0efa8c 100644
--- a/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsDialog.java
@@ -15,6 +15,7 @@
*/
package com.intellij.refactoring.encapsulateFields;
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.help.HelpManager;
@@ -509,8 +510,8 @@ public String getAccessorsVisibility() {
private PsiMethod generateMethodPrototype(PsiField field, String methodName, boolean isGetter) {
PsiMethod prototype = isGetter
- ? PropertyUtil.generateGetterPrototype(field)
- : PropertyUtil.generateSetterPrototype(field);
+ ? GenerateMembersUtil.generateGetterPrototype(field)
+ : GenerateMembersUtil.generateSetterPrototype(field);
try {
PsiElementFactory factory = JavaPsiFacade.getInstance(field.getProject()).getElementFactory();
PsiIdentifier identifier = factory.createIdentifier(methodName);
diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java
index 284433f7c4f0..90131299c98d 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java
@@ -21,6 +21,7 @@
package com.intellij.refactoring.extractMethodObject;
import com.intellij.codeInsight.NullableNotNullManager;
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -255,7 +256,7 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
field = PropertyUtil.findPropertyField(myProject, myInnerClass, name, false);
}
LOG.assertTrue(field != null, "i:" + i + "; output variables: " + Arrays.toString(outputVariables) + "; parameters: " + Arrays.toString(getMethod().getParameterList().getParameters()) + "; output field: " + outputField );
- myInnerClass.add(PropertyUtil.generateGetterPrototype(field));
+ myInnerClass.add(GenerateMembersUtil.generateGetterPrototype(field));
}
PsiParameter[] params = getMethod().getParameterList().getParameters();
diff --git a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java
index d096db58b1cf..3969ae580919 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java
@@ -15,6 +15,7 @@
*/
package com.intellij.refactoring.extractclass;
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.ide.util.PackageUtil;
import com.intellij.openapi.application.ApplicationManager;
@@ -311,11 +312,11 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
if (myGenerateAccessors) {
final NecessaryAccessorsVisitor visitor = checkNecessaryGettersSetters4SourceClass();
for (PsiField field : visitor.getFieldsNeedingGetter()) {
- sourceClass.add(PropertyUtil.generateGetterPrototype(field));
+ sourceClass.add(GenerateMembersUtil.generateGetterPrototype(field));
}
for (PsiField field : visitor.getFieldsNeedingSetter()) {
- sourceClass.add(PropertyUtil.generateSetterPrototype(field));
+ sourceClass.add(GenerateMembersUtil.generateSetterPrototype(field));
}
}
super.performRefactoring(usageInfos);
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java
index 0ef27c9b930d..a94f41155c54 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java
@@ -15,11 +15,11 @@
*/
package com.intellij.refactoring.introduceParameter;
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
-import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.IntroduceParameterRefactoring;
import com.intellij.refactoring.util.RefactoringUtil;
@@ -217,7 +217,7 @@ public class OldReferenceResolver {
}
PsiElement newExpr = expr;
- PsiMethod getterPrototype = PropertyUtil.generateGetterPrototype(psiField);
+ PsiMethod getterPrototype = GenerateMembersUtil.generateGetterPrototype(psiField);
PsiMethod getter = psiField.getContainingClass().findMethodBySignature(getterPrototype, true);
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/usageInfo/AppendAccessorsUsageInfo.java b/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/usageInfo/AppendAccessorsUsageInfo.java
index 59ec81a7ec48..e862915d8db8 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/usageInfo/AppendAccessorsUsageInfo.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/usageInfo/AppendAccessorsUsageInfo.java
@@ -20,12 +20,12 @@
*/
package com.intellij.refactoring.introduceparameterobject.usageInfo;
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiParameter;
-import com.intellij.psi.util.PropertyUtil;
import com.intellij.refactoring.RefactorJBundle;
import com.intellij.refactoring.introduceparameterobject.IntroduceParameterObjectProcessor;
import com.intellij.refactoring.util.FixableUsageInfo;
@@ -70,8 +70,8 @@ public class AppendAccessorsUsageInfo extends FixableUsageInfo{
final PsiField field = parameterChunk.getField();
if (field != null) {
element.add(isGetter
- ? PropertyUtil.generateGetterPrototype(field)
- : PropertyUtil.generateSetterPrototype(field));
+ ? GenerateMembersUtil.generateGetterPrototype(field)
+ : GenerateMembersUtil.generateSetterPrototype(field));
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/removemiddleman/RemoveMiddlemanProcessor.java b/java/java-impl/src/com/intellij/refactoring/removemiddleman/RemoveMiddlemanProcessor.java
index ab14d4f8f2c9..091e6f7fc0d3 100644
--- a/java/java-impl/src/com/intellij/refactoring/removemiddleman/RemoveMiddlemanProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/removemiddleman/RemoveMiddlemanProcessor.java
@@ -15,6 +15,7 @@
*/
package com.intellij.refactoring.removemiddleman;
+import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
@@ -99,7 +100,7 @@ public class RemoveMiddlemanProcessor extends FixableUsagesRefactoringProcessor
} else {
access = getterName + "()";
if (getter == null) {
- getter = PropertyUtil.generateGetterPrototype(field);
+ getter = GenerateMembersUtil.generateGetterPrototype(field);
}
}
usages.add(new InlineDelegatingCall(call, paramPermutation, access, delegatedMethod.getName()));
diff --git a/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticTestRenamerFactory.java b/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticTestRenamerFactory.java
index 6c296231d6dc..5045c2b99ac4 100644
--- a/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticTestRenamerFactory.java
+++ b/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticTestRenamerFactory.java
@@ -15,16 +15,20 @@
*/
package com.intellij.refactoring.rename.naming;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.JavaPsiFacade;
+import com.intellij.codeInsight.TestFrameworks;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.refactoring.JavaRefactoringSettings;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.usageView.UsageInfo;
+import com.intellij.util.containers.HashSet;
import java.util.Collection;
+import java.util.regex.Pattern;
/**
* @author yole
@@ -59,18 +63,33 @@ public class AutomaticTestRenamerFactory implements AutomaticRenamerFactory {
private static class TestsRenamer extends AutomaticRenamer {
public TestsRenamer(PsiClass aClass, String newClassName) {
- appendTestClass(aClass, "Test");
- appendTestClass(aClass, "TestCase");
+ final Module module = ModuleUtilCore.findModuleForPsiElement(aClass);
+ if (module != null) {
+ final GlobalSearchScope moduleScope = GlobalSearchScope.moduleWithDependentsScope(module);
- suggestAllNames(aClass.getName(), newClassName);
+ appendTestClass(aClass, "Test", moduleScope);
+ appendTestClass(aClass, "TestCase", moduleScope);
+
+ suggestAllNames(aClass.getName(), newClassName);
+ }
}
- private void appendTestClass(PsiClass aClass, String testSuffix) {
- final Project project = aClass.getProject();
- final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
- final PsiClass psiClassTest = facade.findClass(aClass.getQualifiedName() + testSuffix, GlobalSearchScope.projectScope(project));
- if (psiClassTest != null) {
- myElements.add(psiClassTest);
+ private void appendTestClass(PsiClass aClass, String testSuffix, final GlobalSearchScope moduleScope) {
+ PsiShortNamesCache cache = PsiShortNamesCache.getInstance(aClass.getProject());
+
+ String klassName = aClass.getName();
+ Pattern pattern = Pattern.compile(".*" + klassName + ".*" + testSuffix);
+
+ HashSet<String> names = new HashSet<String>();
+ cache.getAllClassNames(names);
+ for (String eachName : names) {
+ if (pattern.matcher(eachName).matches()) {
+ for (PsiClass eachClass : cache.getClassesByName(eachName, moduleScope)) {
+ if (TestFrameworks.getInstance().isTestClass(eachClass)) {
+ myElements.add(eachClass);
+ }
+ }
+ }
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java
index ac7a6d9ece69..46b604e8d0a7 100644
--- a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java
@@ -457,13 +457,6 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
removeDeletedMethods(OverridingMethodsSearch.search(psiMethod, true).toArray(PsiMethod.EMPTY_ARRAY),
allElementsToDelete);
- for (PsiReference reference : references) {
- final PsiElement element = reference.getElement();
- if (!isInside(element, allElementsToDelete) && !isInside(element, overridingMethods)) {
- usages.add(new SafeDeleteReferenceJavaDeleteUsageInfo(element, psiMethod, PsiTreeUtil.getParentOfType(element, PsiImportStaticStatement.class) != null));
- }
- }
-
final HashMap<PsiMethod, Collection<PsiReference>> methodToReferences = new HashMap<PsiMethod, Collection<PsiReference>>();
for (PsiMethod overridingMethod : overridingMethods) {
final Collection<PsiReference> overridingReferences = ReferencesSearch.search(overridingMethod).findAll();
@@ -472,6 +465,12 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
final Set<PsiMethod> validOverriding =
validateOverridingMethods(psiMethod, references, Arrays.asList(overridingMethods), methodToReferences, usages,
allElementsToDelete);
+ for (PsiReference reference : references) {
+ final PsiElement element = reference.getElement();
+ if (!isInside(element, allElementsToDelete) && !isInside(element, validOverriding)) {
+ usages.add(new SafeDeleteReferenceJavaDeleteUsageInfo(element, psiMethod, PsiTreeUtil.getParentOfType(element, PsiImportStaticStatement.class) != null));
+ }
+ }
return new Condition<PsiElement>() {
public boolean value(PsiElement usage) {
if(usage instanceof PsiFile) return false;
@@ -594,12 +593,12 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
}
for (PsiMethod method : overridingMethods) {
- if (!validOverriding.contains(method) && !multipleInterfaceImplementations.contains(method)) {
- final boolean methodCanBePrivate =
- canBePrivate(method, methodToReferences.get(method), validOverriding, allElementsToDelete);
- if (methodCanBePrivate) {
- usages.add(new SafeDeletePrivatizeMethod(method, originalMethod));
- }
+ if (!validOverriding.contains(method) &&
+ !multipleInterfaceImplementations.contains(method) &&
+ canBePrivate(method, methodToReferences.get(method), validOverriding, allElementsToDelete)) {
+ usages.add(new SafeDeletePrivatizeMethod(method, originalMethod));
+ } else {
+ usages.add(new SafeDeleteOverrideAnnotation(method, originalMethod));
}
}
return validOverriding;
diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteOverrideAnnotation.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteOverrideAnnotation.java
new file mode 100644
index 000000000000..9a3159564ae6
--- /dev/null
+++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteOverrideAnnotation.java
@@ -0,0 +1,43 @@
+/*
+ * 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.refactoring.safeDelete.usageInfo;
+
+import com.intellij.codeInsight.AnnotationUtil;
+import com.intellij.psi.PsiAnnotation;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiMethod;
+import com.intellij.util.IncorrectOperationException;
+
+/**
+ * User: anna
+ * Date: 7/22/13
+ */
+public class SafeDeleteOverrideAnnotation extends SafeDeleteUsageInfo implements SafeDeleteCustomUsageInfo {
+ public SafeDeleteOverrideAnnotation(PsiElement element, PsiElement referencedElement) {
+ super(element, referencedElement);
+ }
+
+ public PsiMethod getMethod() {
+ return (PsiMethod)getElement();
+ }
+
+ public void performRefactoring() throws IncorrectOperationException {
+ final PsiAnnotation annotation = AnnotationUtil.findAnnotation(getMethod(), true, Override.class.getName());
+ if (annotation != null) {
+ annotation.delete();
+ }
+ }
+}
diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeletePrivatizeMethod.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeletePrivatizeMethod.java
index 0e0e70fc8837..70a6b44ce033 100644
--- a/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeletePrivatizeMethod.java
+++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeletePrivatizeMethod.java
@@ -15,8 +15,6 @@
*/
package com.intellij.refactoring.safeDelete.usageInfo;
-import com.intellij.codeInsight.AnnotationUtil;
-import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.util.PsiUtil;
@@ -25,20 +23,13 @@ import com.intellij.util.IncorrectOperationException;
/**
* @author dsl
*/
-public class SafeDeletePrivatizeMethod extends SafeDeleteUsageInfo implements SafeDeleteCustomUsageInfo {
+public class SafeDeletePrivatizeMethod extends SafeDeleteOverrideAnnotation {
public SafeDeletePrivatizeMethod(PsiMethod method, PsiMethod overridenMethod) {
super(method, overridenMethod);
}
- public PsiMethod getMethod() {
- return (PsiMethod) getElement();
- }
-
public void performRefactoring() throws IncorrectOperationException {
PsiUtil.setModifierProperty(getMethod(), PsiModifier.PRIVATE, true);
- final PsiAnnotation annotation = AnnotationUtil.findAnnotation(getMethod(), true, Override.class.getName());
- if (annotation != null) {
- annotation.delete();
- }
+ super.performRefactoring();
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
index ca905b0f252d..abf333ce4f1e 100644
--- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
+++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
@@ -1137,7 +1137,7 @@ public class RefactoringUtil {
paramTag.delete();
}
for (PsiDocTag psiDocTag : newTags) {
- anchor = docComment.addAfter(psiDocTag, anchor);
+ anchor = anchor != null && anchor.isValid() ? docComment.addAfter(psiDocTag, anchor) : docComment.add(psiDocTag);
}
}
diff --git a/java/java-impl/src/com/intellij/unscramble/ThreadDumpConsoleFactory.java b/java/java-impl/src/com/intellij/unscramble/ThreadDumpConsoleFactory.java
new file mode 100644
index 000000000000..94fa4f24575b
--- /dev/null
+++ b/java/java-impl/src/com/intellij/unscramble/ThreadDumpConsoleFactory.java
@@ -0,0 +1,40 @@
+/*
+ * 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.unscramble;
+
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.actionSystem.DefaultActionGroup;
+import com.intellij.openapi.project.Project;
+
+import javax.swing.*;
+import java.util.List;
+
+/**
+* Created by Irina.Chernushina on 7/13/13.
+*/
+public class ThreadDumpConsoleFactory implements AnalyzeStacktraceUtil.ConsoleFactory {
+ private final Project myProject;
+ private final List<ThreadState> myThreadDump;
+
+ public ThreadDumpConsoleFactory(Project project, List<ThreadState> threadDump) {
+ myProject = project;
+ myThreadDump = threadDump;
+ }
+
+ public JComponent createConsoleComponent(ConsoleView consoleView, DefaultActionGroup toolbarActions) {
+ return new ThreadDumpPanel(myProject, consoleView, toolbarActions, myThreadDump);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java b/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java
index 2627fd298b4e..37311251a2c0 100644
--- a/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java
+++ b/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java
@@ -15,12 +15,10 @@
*/
package com.intellij.unscramble;
-import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.util.PropertiesComponent;
-import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
@@ -410,11 +408,7 @@ public class UnscrambleDialog extends DialogWrapper {
message = IdeBundle.message("unscramble.unscrambled.deadlock.tab");
icon = AllIcons.Debugger.KillProcess;
}
- return AnalyzeStacktraceUtil.addConsole(project, threadDump.size() > 1 ? new AnalyzeStacktraceUtil.ConsoleFactory() {
- public JComponent createConsoleComponent(ConsoleView consoleView, DefaultActionGroup toolbarActions) {
- return new ThreadDumpPanel(project, consoleView, toolbarActions, threadDump);
- }
- } : null, message, unscrambledTrace, icon);
+ return AnalyzeStacktraceUtil.addConsole(project, threadDump.size() > 1 ? new ThreadDumpConsoleFactory(project, threadDump) : null, message, unscrambledTrace, icon);
}
protected String getDimensionServiceKey(){
diff --git a/java/java-impl/src/com/intellij/usages/impl/rules/ClassGroupingRule.java b/java/java-impl/src/com/intellij/usages/impl/rules/ClassGroupingRule.java
index 3878aaaca0a3..8cd847129573 100644
--- a/java/java-impl/src/com/intellij/usages/impl/rules/ClassGroupingRule.java
+++ b/java/java-impl/src/com/intellij/usages/impl/rules/ClassGroupingRule.java
@@ -48,6 +48,8 @@ public class ClassGroupingRule implements UsageGroupingRule {
}
final PsiElement psiElement = ((PsiElementUsage)usage).getElement();
final PsiFile containingFile = psiElement.getContainingFile();
+ if (containingFile == null) return null;
+
PsiFile topLevelFile = InjectedLanguageManager.getInstance(containingFile.getProject()).getTopLevelFile(containingFile);
if (!(topLevelFile instanceof PsiJavaFile) || topLevelFile instanceof JspFile) {
diff --git a/java/java-impl/src/com/intellij/util/xml/CanonicalPsiTypeConverterImpl.java b/java/java-impl/src/com/intellij/util/xml/CanonicalPsiTypeConverterImpl.java
index 152e51aad40b..88ccc0a629ef 100644
--- a/java/java-impl/src/com/intellij/util/xml/CanonicalPsiTypeConverterImpl.java
+++ b/java/java-impl/src/com/intellij/util/xml/CanonicalPsiTypeConverterImpl.java
@@ -91,7 +91,7 @@ public class CanonicalPsiTypeConverterImpl extends CanonicalPsiTypeConverter imp
return super.advancedResolve(incompleteCode);
}
- public void processVariants(final PsiScopeProcessor processor) {
+ public void processVariants(@NotNull final PsiScopeProcessor processor) {
if (processor instanceof JavaCompletionProcessor) {
((JavaCompletionProcessor)processor).setCompletionElements(getVariants());
} else {