summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2014-01-27 09:36:41 -0800
committerTor Norbye <tnorbye@google.com>2014-01-27 09:36:49 -0800
commit809cb3e73653399e59e45e0b10749a8e37b85a75 (patch)
tree8aa7262925cc4eed902baa00f2193e98f6bb64e0
parente2d6089d43d7ac1f62bafe06638d5ac2c21f5283 (diff)
downloadidea-809cb3e73653399e59e45e0b10749a8e37b85a75.tar.gz
Snapshot 9e6329d622cc9649c9c035f28faddc29564a5b7a from idea/133.696 of git://git.jetbrains.org/idea/community.git
9e6329d: IDEA-119035 Select All shortcut for any table on mac with Darcula 7642139: [log] IDEA-116322 Fix structure filter for multiple roots 5fe2227: [log] refactor: group filters before passing them to providers a9bda1e: Problem with several users in log filter fixed. bb353f3: [log] IDEA-119316 Fix "go to commit" if there are log filters 2825dd1: IDEA-119467 Gradle: auto discovery of buildSrc project (cherry picked from commit 3cb5420) ca05350: Gradle: respect the order of dependencies (cherry picked from commit dca7107) 8a1d099: IDEA-115351 Idea UI hangs after performing Move Module to group (cherry picked from commit 673ed61) [r=Maxim.Mossienko] 9f006a4: NPE fix (cherry picked from commit 1eb3644) 2089b40: Gradle: test data fix (cherry picked from commit c864c4b) 6208324: IDEA-119336 Gradle build files: build.gradle scripts are checkout from Perforce even if the file is not changed (cherry picked from commit 3234c0b) d1d776c: IDEA-119467 Gradle: auto discovery of buildSrc project IDEA-98930 IDEA does not resolve dependencies in Gradle buildSrc/ project (cherry picked from commit 0982afc) 6f6c403: Gradle: dependencies scope merge and sourceSets type handling updated related issues: IDEA-119365 Gradle import does not respect model customisations IDEA-118280 Gradle import: IDEA detect java folder as a resource folder IDEA-117668 IDEA v13 spontaneously changes additional test source root to source root (cherry picked from commit 68bfa5e) a7f9d6f: Gradle: respect module build classpath for build scripts resolving review: http://crucible.labs.intellij.net/cru/CR-IC-4038 742c670: isEAP = false, time to release 13.0.2 3a5cfc7: add profiling parameters to the right part of the classpath (has been broken after Launcher was introduced) ca42a66: fixed empty headers and import (dependant in language level) for qt, gtk... skeletons. ba68876: update copyright in artworks 7c12cb3: IDEA-119619 Settings / Language Injections: project level XML tag injection loses Sub-Tags value on IDE restart f7bd727: don't call robot on alt on Windows and when window is inactive (cherry picked from commit 0fe2cac) 8b62b1e: add WinXP definition (cherry picked from commit dde1494) 62c528a: consume Alt events on WinXP in default handler to avoid WindowsRootPaneUI.AltProcessor (cherry picked from commit f14aab9) 20c7faa: support table decoration on IntelliJ laf (cherry picked from commit 04425c9) 7dc2f34: IDEA-118211 (cherry picked from commit 55ee980) [r=Peter.Gromov] b15f65d: fixed PY-11823 Test Runner detection in settings doesn't pick up just installed test runner 7a2bec9: Fixed dedent in case of tabs ( PY-10120). 56b5f81: Python keywords extracted. Cleanup. f195253: Fixed test data to satisfy PEP8. 6b6bbc1: Make right par indent=none in import statement (PY-9075). 6a39911: Make continuation indent after continuation in indenting statement (PY-9573). cf19307: Test for PY-9573 fb5186fa: Handle 'mode' as a keyword argument to open() as well 27a4d26: Detect text or binary I/O in pathlib.Path.open() a5600e3: Return instance types for instance types of superclasses f56e9b1: fixed PY-11837 nose test runner errors while formatting a test error 7420dd6: Nullity annotations 97ffd71: fixed test data d0eb725: fixed test data 326185d: generator: do not drop the whole module in case there are broken __repr__ defined 982687a: performance for generator: Split big generated modules (like _Gtk, PyQt) into smaller ones af679a5: Simplified always true condition 3174b9c: Extracted PyClassTypeImpl.findProperty() 777280e: Added 'inherited' parameter to PyClass.findProperty() d5d8b23: Python skeletons class members provider now can provide new overridden members 6775ed3: Fixed code insight for returning 'self' in base class methods (PY-10977, PY-11413) d4c641f: Fix formatter to add two blank lines between declarations with comment (PY-9923). 9c8134a: add field after super call 37813c6: Revert "Detect SQL fragments only in the beginning of string literals" (PY-11828) 9d5973f: Use default charset as python console encoding. 7fed382: Added Python 3.4 modules to the stdlib modules list c772246: Don't ignore unused attributes of empty constructors (PY-7527) 91ae6bf: Fixed NPE in PyUnusedLocalInspectionVisitor.visitPyCallExpression() 464ae1c: fixed PY-11800 Parameter unfilled false positive for decorators with '*' arguments. e3ec532: fixed test data 31bb1dd: fixed add field declaration to the beginning of __init__ 2910f7d: fixed EA-52897 - CCE: ImportToggleAliasIntention$.execute cca9133: fixed EA-53046 - NPE: PyExtractMethodUtil.a 2fcf769: fixed quickdoc test fcf329f: fixed editing test 859c599: fixed testdata ab7782a: fixed PY-11765 @ivar and @type in class documentation cause PyUnresolvedReferences inspection to file 8303e4f: IDEA-112303 Tool Windows Quick Access button: impossible to select item in list by mouse (cherry picked from commit 8e2ce03) b206d2d: fix NPE d923a83: Trying to fix EA-51665 - assert: FTManager.createAndStoreBundledTemplate (cherry picked from commit 47dee08) +review CR-IC 72fa58b: Add additional diagnostic to investigate EA-51665 (assert: FTManager.createAndStoreBundledTemplate). (cherry picked from commit a5e4cf4) +review CR-IC 6548f1a: java: incorrect parsing of bounds in class files fixed 8f5b22c: EA-42899 - CCE: XmlLanguageInjectionSupport.doEditInjection & cleanup 2a882e0: EA-53406 - IAE: ServiceManager.getService ed41c77: WI-13685 PhpStorm doesn't save project name CR-PS-181 2c3ccec: IDEA-119445 Remove first slash in "copy reference" (cherry picked from commit 298bb04) 50bf901: IDEA-119153 file search too wide for users folder (cherry picked from commit 37521f0) 8ab790b: IDEA-119470 File and code templates: changes gone when switching tabs (cherry picked from commit 21cdea3) 7402508: EA-53393 - IOOBE: DomAnchorImpl.createAnchor (missing cherry pick) f6ab2da: Bug fix: IDEA incorrect handle escaping. c78400d: IDEA-105253 Missing icon for Thread dumps view 21b6f91: IDEA-104735 Dracula: INVALID string have not dracula style red color (cherry picked from commit 4a5e793) 53885c2: Don't show active editor in recent files 6cf74eb: IDEA-104706 Remove currently active file from "Recent Files" popup (cherry pick from master) ffef358: IDEA-119406 IDEA make corrupts files when performing Maven resource filtering (default value of escapeString is null) b8e9ab1: IDEA-119406 IDEA make corrupts files when performing Maven resource filtering (cherry picked from commit 5b6b3f6) +review CR-IC d3dd646: EA-53308 - CCE: DfaVariableValue.<init> (cherry picked from commit 32a579d) 10f83e0: external build for artifacts: added API to filter contents of directory extracted from jar file [rev by Michael Golubev] b7f4af0: make nonDefaultProject="true" really work 0bebc13: cosmetics 94e0a24: Merge remote-tracking branch 'origin/133' into 133 85cae29: IDEA-119347 ../jre64 JDK not being picked up by idea64.exe 2dd77af: IDEA-117127 Editor: Throwable on Select word at caret inside plain text (cherry picked from commit 2e3a0d8) 0a5e3ad: IDEA-117555 Search everywhere dialog is being closed immediately (cherry picked from commit ba8037d) 520da57: fix getDisplayName nullability assertion 0663734: IDEA-111122 remove attached jar artifact coming from "apklib" dependency from the dependencies of app module: users add it to deploy jar to Maven repository in addition to "apklib" file, but we don't need to add it to the classpath, because it leads to class duplication [rev=sergey.evdokimov] c1fb468: IDEA-79522 need ability to set display names for xml attribute and xml tag language injections 3ae70b9: IDEA-119163 "Language Injections" settings should use toolbar decorator in the same way as other 50c78e9: IDEA-117327 Add a setting to switch off autopopup completion item selection by Enter (cherry picked from commit 84ddafc) ae5ce9b: groovy debugging agent that produces less garbage (cherry picked from commit c7af9fe) f6682f7: Roll-back FileChooserDescriptor API change. 1c64249: Merge remote-tracking branch 'origin/133' into 133 b293f8c: SearchEverywhere doesn't work on Linux 07b98c1: IDEA-74428 Ability to turn on log debug categories from the GUI 4257f6f: CR-IU-511 make abstract class abstract & leave getPresentableText mandatory 7cac7b7: allow to turn off suggestion to create a file when creating a directory with file-like name (IDEA-118250) (cherry picked from commit 5d81e8d) acb9db2: don't show parameter info for invisible editors (EA-53161 - NPE: ParameterInfoComponent.<init>) (cherry picked from commit fb24d98) e6bfbbf: the users don't care if we're preparing editors to open (IDEA-115130) (cherry picked from commit 9a116de) 3f1ebf3: rethrow PCE from KeyedExtensionFactory reflection (cherry picked from commit df8967b) Change-Id: I8083d21f3faff4f899c53a5dea2710713dc1a2a9
-rw-r--r--bin/WinLauncher/WinLauncher64.exebin834048 -> 834048 bytes
-rw-r--r--community-resources/src/idea/IdeaApplicationInfo.xml2
-rw-r--r--community-resources/src/idea_community_about.pngbin73616 -> 73624 bytes
-rw-r--r--community-resources/src/idea_community_about@2x.pngbin213567 -> 213528 bytes
-rw-r--r--community-resources/src/idea_community_logo.pngbin119813 -> 119885 bytes
-rw-r--r--community-resources/src/idea_community_logo@2x.pngbin354139 -> 354398 bytes
-rw-r--r--java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java10
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java3
-rw-r--r--java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java26
-rw-r--r--java/java-impl/src/com/intellij/psi/NonClasspathResolveScopeEnlarger.java4
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java4
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java15
-rw-r--r--java/java-tests/testData/codeInsight/copyReference/CopyFile_after.java2
-rw-r--r--java/java-tests/testData/psi/cls/mirror/Bounds.txt13
-rw-r--r--java/java-tests/testData/psi/cls/mirror/pkg/Bounds.classbin0 -> 589 bytes
-rw-r--r--java/java-tests/testData/psi/cls/mirror/src/pkg/Bounds.java29
-rw-r--r--java/java-tests/testData/psi/cls/stubBuilder/UtilCollections.txt10
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/CopyReferenceTest.groovy2
-rw-r--r--java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java3
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreator.java16
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreatorBase.java15
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java7
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java11
-rw-r--r--native/WinLauncher/WinLauncher/WinLauncher.cpp2
-rw-r--r--platform/core-api/src/com/intellij/patterns/TreeElementPattern.java2
-rw-r--r--platform/extensions/src/com/intellij/openapi/util/KeyedExtensionFactory.java7
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalModuleBuildClasspathPojo.java85
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalProjectBuildClasspathPojo.java102
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/psi/search/ExternalModuleBuildGlobalSearchScope.java40
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemLocalSettings.java32
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java18
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java3
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java4
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/wordSelection/NaturalLanguageTextSelectioner.java3
-rw-r--r--platform/lang-impl/src/com/intellij/execution/ui/layout/actions/RestoreViewAction.java8
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/CopyReferenceAction.java29
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/CreateDirectoryOrPackageHandler.java3
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java19
-rw-r--r--platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java33
-rw-r--r--platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/BundledFileTemplate.java5
-rw-r--r--platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java3
-rw-r--r--platform/lang-impl/src/com/intellij/ide/navigationToolbar/AbstractNavBarModelExtension.java6
-rw-r--r--platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java5
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileCellRenderer.java2
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileModel.java2
-rw-r--r--platform/lang-impl/src/com/intellij/platform/ModuleAttachProcessor.java5
-rw-r--r--platform/lang-impl/src/com/intellij/platform/renameProject/RenameProjectHandler.java19
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java3
-rw-r--r--platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptor.java20
-rw-r--r--platform/platform-api/src/com/intellij/ui/AnActionButton.java5
-rw-r--r--platform/platform-api/src/com/intellij/ui/DumbAwareActionButton.java41
-rw-r--r--platform/platform-api/src/com/intellij/ui/table/JBTable.java3
-rw-r--r--platform/platform-impl/src/com/intellij/diagnostic/DebugLogManager.java100
-rw-r--r--platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java16
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/DebugLogConfigureAction.java91
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java8
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/Switcher.java7
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java3
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java15
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/OpenFilesActivity.java10
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java1
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java7
-rw-r--r--platform/platform-resources-en/src/messages/ActionsBundle.properties2
-rw-r--r--platform/platform-resources-en/src/misc/registry.properties4
-rw-r--r--platform/platform-resources/src/componentSets/Platform.xml4
-rw-r--r--platform/platform-resources/src/idea/PlatformActions.xml1
-rw-r--r--platform/usageView/src/com/intellij/usages/impl/UsageViewTreeCellRenderer.java10
-rw-r--r--platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java5
-rw-r--r--platform/util/src/com/intellij/openapi/util/SystemInfo.java3
-rw-r--r--platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogBranchFilter.java28
-rw-r--r--platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDateFilter.java40
-rw-r--r--platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java7
-rw-r--r--platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogStructureFilter.java37
-rw-r--r--platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogTextFilter.java31
-rw-r--r--platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUserFilter.java18
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogBranchFilterImpl.java (renamed from platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogBranchFilter.java)6
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java28
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDateFilterImpl.java (renamed from platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDateFilter.java)7
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java6
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java (renamed from platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilter.java)6
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogUserFilter.java71
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java72
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java4
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/DateFilterPopupComponent.java4
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java4
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java57
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java2
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogTextFilterImpl.java (renamed from platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogTextFilter.java)6
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java26
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java21
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/NoGraphTableModel.java33
-rw-r--r--plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.form27
-rw-r--r--plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.java26
-rw-r--r--plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/ui/configurables/MethodParameterInjectionConfigurable.java34
-rw-r--r--plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java29
-rw-r--r--plugins/IntelliLang/src/META-INF/plugin.xml2
-rw-r--r--plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java181
-rw-r--r--plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java7
-rw-r--r--plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java4
-rw-r--r--plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java5
-rw-r--r--plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/AbstractInjectionPanel.java24
-rw-r--r--plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/AdvancedPanel.form4
-rw-r--r--plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/BaseInjectionPanel.form4
-rw-r--r--plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/LanguagePanel.form11
-rw-r--r--plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/configurables/InjectionConfigurable.java85
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/AbstractTagInjection.java38
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/XmlAttributeInjection.java23
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/XmlTagInjection.java4
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/AdvancedXmlPanel.form15
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/TagPanel.form35
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/TagPanel.java20
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlAttributePanel.form43
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlAttributePanel.java22
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlTagPanel.form39
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlTagPanel.java14
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/configurables/XmlAttributeInjectionConfigurable.java34
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/configurables/XmlTagInjectionConfigurable.java34
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java53
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java6
-rw-r--r--plugins/git4idea/src/git4idea/log/GitLogProvider.java22
-rw-r--r--plugins/gradle/src/META-INF/plugin.xml2
-rw-r--r--plugins/gradle/src/META-INF/services/org.jetbrains.plugins.gradle.model.ModelBuilderService1
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleClassFinder.java34
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java52
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java7
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/model/BuildScriptClasspathModel.java28
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/model/ClasspathEntryModel.java36
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/model/GradleDependencyScope.java13
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelBuildScriptClasspathBuilderImpl.java93
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImpl.java46
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImpl.java102
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/BuildScriptClasspathData.java49
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/ClasspathEntry.java84
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/BuildScriptClasspathModelImpl.java47
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ClasspathEntryModelImpl.java60
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/buildSrcInit.gradle25
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/init.gradle4
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleBuildClasspathManager.java111
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleInstallationManager.java108
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java29
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java28
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java113
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java6
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/BuildClasspathModuleGradleDataService.java161
-rw-r--r--plugins/gradle/testData/testAddMavenDependencyInEmptyFile.gradle1
-rw-r--r--plugins/gradle/testData/testAddMavenDependencyInEmptyFile_after.gradle1
-rw-r--r--plugins/gradle/testData/testDefaultDependenciesModel/build.gradle4
-rw-r--r--plugins/gradle/testData/testDefaultDependenciesModel/settings.gradle5
-rw-r--r--plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/build.gradle21
-rw-r--r--plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/settings.gradle3
-rw-r--r--plugins/gradle/testData/testGradleSourcesSetsInterpretation/build.gradle74
-rw-r--r--plugins/gradle/testData/testGradleSourcesSetsInterpretation/settings.gradle8
-rw-r--r--plugins/gradle/testData/testModelBuildScriptClasspathBuilder/build.gradle9
-rw-r--r--plugins/gradle/testData/testModelBuildScriptClasspathBuilder/settings.gradle4
-rw-r--r--plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/AbstractModelBuilderTest.java2
-rw-r--r--plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelBuildScriptClasspathBuilderImplTest.java78
-rw-r--r--plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImplTest.java134
-rw-r--r--plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImplTest.java177
-rw-r--r--plugins/groovy/hotswap/agentSrc/org/groovy/debug/hotswap/ResetAgent.java39
-rw-r--r--plugins/groovy/hotswap/gragent.jarbin49320 -> 49431 bytes
-rw-r--r--plugins/groovy/resources/fileTemplates/code/Spock_SetUp_Method.groovy.ft (renamed from plugins/groovy/resources/fileTemplates/code/Spock SetUp Method.groovy.ft)0
-rw-r--r--plugins/groovy/resources/fileTemplates/code/Spock_SetUp_Method.groovy.html (renamed from plugins/groovy/resources/fileTemplates/code/Spock SetUp Method.groovy.html)0
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/navbar/GrNavBarModelExtension.java7
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockTestFramework.java2
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java45
-rw-r--r--plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourcesBuilder.java40
-rw-r--r--plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenModuleResourceConfiguration.java2
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/compiler/MavenResourceCompiler.java9
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java2
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java12
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResourceCompilerConfigurationGenerator.java2
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java21
-rw-r--r--python/IntelliLang-python/src/pyInjections.xml2
-rw-r--r--python/helpers/generator3.py169
-rw-r--r--python/helpers/pycharm/nose_utils.py13
-rw-r--r--python/helpers/pycharm_generator_utils/constants.py2
-rw-r--r--python/helpers/pycharm_generator_utils/module_redeclarator.py94
-rw-r--r--python/helpers/pycharm_generator_utils/util_methods.py58
-rw-r--r--python/helpers/tools/stdlib_packages.txt7
-rw-r--r--python/psi-api/src/com/jetbrains/python/psi/PyClass.java4
-rw-r--r--python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java2
-rw-r--r--python/psi-api/src/com/jetbrains/python/psi/types/PyOverridingAncestorsClassMembersProvider.java22
-rw-r--r--python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java2
-rw-r--r--python/src/META-INF/python-core.xml4
-rw-r--r--python/src/com/jetbrains/python/codeInsight/PyKeywordTypedHandler.java (renamed from python/src/com/jetbrains/python/codeInsight/KeywordTypedHandler.java)4
-rw-r--r--python/src/com/jetbrains/python/codeInsight/PyKeywords.java64
-rw-r--r--python/src/com/jetbrains/python/codeInsight/PyUnindentingInsertHandler.java (renamed from python/src/com/jetbrains/python/codeInsight/UnindentingInsertHandler.java)37
-rw-r--r--python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java55
-rw-r--r--python/src/com/jetbrains/python/codeInsight/intentions/ImportToggleAliasIntention.java17
-rw-r--r--python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java8
-rw-r--r--python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java3
-rw-r--r--python/src/com/jetbrains/python/console/PydevConsoleRunner.java19
-rw-r--r--python/src/com/jetbrains/python/documentation/DocStringParameterReference.java44
-rw-r--r--python/src/com/jetbrains/python/documentation/DocStringReferenceProvider.java20
-rw-r--r--python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java2
-rw-r--r--python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java6
-rw-r--r--python/src/com/jetbrains/python/formatter/PyBlock.java83
-rw-r--r--python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java49
-rw-r--r--python/src/com/jetbrains/python/inspections/PyAttributeOutsideInitInspection.java2
-rw-r--r--python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java2
-rw-r--r--python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java2
-rw-r--r--python/src/com/jetbrains/python/inspections/PyUnusedLocalInspectionVisitor.java5
-rw-r--r--python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java18
-rw-r--r--python/src/com/jetbrains/python/inspections/quickfix/AddGlobalQuickFix.java1
-rw-r--r--python/src/com/jetbrains/python/psi/PyUtil.java32
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyClassImpl.java12
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java4
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java51
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java4
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java4
-rw-r--r--python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java66
-rw-r--r--python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java12
-rw-r--r--python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java3
-rw-r--r--python/src/com/jetbrains/python/testing/PyTestFrameworkService.java50
-rw-r--r--python/src/com/jetbrains/python/testing/VFSTestFrameworkListener.java51
-rw-r--r--python/testData/formatter/commentBetweenClasses_after.py1
-rw-r--r--python/testData/formatter/continuationIndentInIndentingStatement.py31
-rw-r--r--python/testData/formatter/continuationIndentInIndentingStatement_after.py31
-rw-r--r--python/testData/formatter/indentParensInImport.py3
-rw-r--r--python/testData/formatter/indentParensInImport_after.py3
-rw-r--r--python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment.py18
-rw-r--r--python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment_after.py22
-rw-r--r--python/testData/inspections/FieldFromUnusedParameterKeyword.py3
-rw-r--r--python/testData/inspections/FieldFromUnusedParameterKeyword_after.py4
-rw-r--r--python/testData/inspections/FieldFromUnusedParameter_after.py4
-rw-r--r--python/testData/inspections/PyArgumentListInspection/decoratorsPy3K.py7
-rw-r--r--python/testData/inspections/PyUnresolvedReferencesInspection/contextManagerSubclass.py12
-rw-r--r--python/testData/inspections/PyUnresolvedReferencesInspection/ivarInDocstring.py10
-rw-r--r--python/testData/inspections/PyUnresolvedReferencesInspection/returnSelfInSuperClass.py13
-rw-r--r--python/testData/inspections/PyUnusedLocalVariableInspection/test.py13
-rw-r--r--python/testData/inspections/ReplaceNotEqOperator.py2
-rw-r--r--python/testData/quickFixes/AddFieldQuickFixTest/addFieldFromInstance_after.py3
-rw-r--r--python/testData/quickFixes/AddFieldQuickFixTest/addFieldFromMethod_after.py2
-rw-r--r--python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameter.py (renamed from python/testData/inspections/FieldFromUnusedParameter.py)0
-rw-r--r--python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameterKeyword.py3
-rw-r--r--python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameterKeyword_after.py4
-rw-r--r--python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameter_after.py4
-rw-r--r--python/testData/quickFixes/AddMethodQuickFixTest/addMethodFromMethod_after.py1
-rw-r--r--python/testData/quickFixes/PyMoveAttributeToInitQuickFixTest/addPass_after.py2
-rw-r--r--python/testData/quickFixes/PyMoveAttributeToInitQuickFixTest/moveToInit_after.py2
-rw-r--r--python/testData/refactoring/introduceField/py4437.after.py2
-rw-r--r--python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java6
-rw-r--r--python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java4
-rw-r--r--python/testSrc/com/jetbrains/python/PyEditingTest.java21
-rw-r--r--python/testSrc/com/jetbrains/python/PyFormatterTest.java12
-rw-r--r--python/testSrc/com/jetbrains/python/PyQuickDocTest.java13
-rw-r--r--python/testSrc/com/jetbrains/python/PyQuickFixTest.java7
-rw-r--r--python/testSrc/com/jetbrains/python/PyStubsTest.java6
-rw-r--r--python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java10
-rw-r--r--python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java14
-rw-r--r--python/testSrc/com/jetbrains/python/quickFixes/AddFieldQuickFixTest.java11
-rw-r--r--xml/dom-impl/src/com/intellij/util/xml/impl/DomAnchorImpl.java1
-rw-r--r--xml/impl/src/com/intellij/ide/browsers/impl/BrowserSettingsProviderImpl.java2
253 files changed, 4232 insertions, 1452 deletions
diff --git a/bin/WinLauncher/WinLauncher64.exe b/bin/WinLauncher/WinLauncher64.exe
index 447170845665..e2e4348505ce 100644
--- a/bin/WinLauncher/WinLauncher64.exe
+++ b/bin/WinLauncher/WinLauncher64.exe
Binary files differ
diff --git a/community-resources/src/idea/IdeaApplicationInfo.xml b/community-resources/src/idea/IdeaApplicationInfo.xml
index 9e07e0cbb73a..08f4adbdde86 100644
--- a/community-resources/src/idea/IdeaApplicationInfo.xml
+++ b/community-resources/src/idea/IdeaApplicationInfo.xml
@@ -1,5 +1,5 @@
<component>
- <version codename="Community Edition" major="13" minor="0.2" eap="true"/>
+ <version codename="Community Edition" major="13" minor="0.2" eap="false"/>
<company name="JetBrains s.r.o." url="http://www.jetbrains.com/?fromIDE"/>
<build number="__BUILD_NUMBER__" date="__BUILD_DATE__"/>
<install-over minbuild="129.1" maxbuild="132.9999" version="12.1"/>
diff --git a/community-resources/src/idea_community_about.png b/community-resources/src/idea_community_about.png
index 5bed0ec33a17..2b5a763fd9c5 100644
--- a/community-resources/src/idea_community_about.png
+++ b/community-resources/src/idea_community_about.png
Binary files differ
diff --git a/community-resources/src/idea_community_about@2x.png b/community-resources/src/idea_community_about@2x.png
index 428aaa5ed1fb..f159fb0a2e56 100644
--- a/community-resources/src/idea_community_about@2x.png
+++ b/community-resources/src/idea_community_about@2x.png
Binary files differ
diff --git a/community-resources/src/idea_community_logo.png b/community-resources/src/idea_community_logo.png
index 87543ff9b401..91a8153fe2dc 100644
--- a/community-resources/src/idea_community_logo.png
+++ b/community-resources/src/idea_community_logo.png
Binary files differ
diff --git a/community-resources/src/idea_community_logo@2x.png b/community-resources/src/idea_community_logo@2x.png
index 57603bed5536..1f2cfb1dcceb 100644
--- a/community-resources/src/idea_community_logo@2x.png
+++ b/community-resources/src/idea_community_logo@2x.png
Binary files differ
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
index 0f13731ca723..49a0d9d93f57 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
@@ -100,8 +100,7 @@ import org.jetbrains.jps.cmdline.ClasspathBootstrap;
import org.jetbrains.jps.incremental.Utils;
import org.jetbrains.jps.model.serialization.JpsGlobalLoader;
-import javax.tools.JavaCompiler;
-import javax.tools.ToolProvider;
+import javax.tools.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
@@ -878,7 +877,11 @@ public class BuildManager implements ApplicationComponent{
cmdLine.addParameter(option);
}
}
-
+
+ if (isProfilingMode) {
+ cmdLine.addParameter("-agentlib:yjpagent=disablej2ee,disablealloc,delay=10000,sessionname=ExternalBuild");
+ }
+
// debugging
final int debugPort = Registry.intValue("compiler.process.debug.port");
if (debugPort > 0) {
@@ -933,7 +936,6 @@ public class BuildManager implements ApplicationComponent{
cp.addAll(myClasspathManager.getBuildProcessPluginsClasspath(project));
if (isProfilingMode) {
cp.add(new File(workDirectory, "yjp-controller-api-redist.jar").getPath());
- cmdLine.addParameter("-agentlib:yjpagent=disablej2ee,disablealloc,delay=10000,sessionname=ExternalBuild");
}
cmdLine.addParameter(classpathToString(cp));
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java
index 70f2c483a1d4..5ec56b9c2029 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java
@@ -91,7 +91,8 @@ public class DfaVariableValue extends DfaValue {
myIsNegated = isNegated;
myQualifier = qualifier;
myVarType = varType;
- myTypeValue = varType == null ? null : (DfaTypeValue)myFactory.createTypeValue(varType, Nullness.UNKNOWN);
+ DfaValue typeValue = myFactory.createTypeValue(varType, Nullness.UNKNOWN);
+ myTypeValue = typeValue instanceof DfaTypeValue ? (DfaTypeValue)typeValue : null;
}
@Nullable
diff --git a/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java b/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java
index af521568774b..6660080be549 100644
--- a/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java
+++ b/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java
@@ -44,19 +44,21 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
private volatile List<VirtualFile> myCache;
private final PsiManager myManager;
private final boolean myCheckForSources;
- private final boolean myUseExtendedScope;
public NonClasspathClassFinder(Project project) {
- this(project, false, false);
+ this(project, false);
}
- protected NonClasspathClassFinder(Project project, boolean checkForSources, boolean useExtendedScope) {
+ protected NonClasspathClassFinder(Project project, boolean checkForSources) {
myProject = project;
myManager = PsiManager.getInstance(myProject);
- myUseExtendedScope = useExtendedScope;
myCheckForSources = checkForSources;
}
+ protected List<VirtualFile> getClassRoots(@Nullable GlobalSearchScope scope) {
+ return getClassRoots();
+ }
+
protected List<VirtualFile> getClassRoots() {
List<VirtualFile> cache = myCache;
long stamp = myManager.getModificationTracker().getModificationCount();
@@ -82,14 +84,11 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
@Override
public PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) {
- final List<VirtualFile> classRoots = getClassRoots();
+ final List<VirtualFile> classRoots = getClassRoots(scope);
if (classRoots.isEmpty()) {
return null;
}
- if(myUseExtendedScope) {
- scope = addNonClasspathScope(myProject, scope);
- }
final String relPath = qualifiedName.replace('.', '/');
for (final VirtualFile classRoot : classRoots) {
if (scope.contains(classRoot)) {
@@ -131,7 +130,7 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
@NotNull
@Override
public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
- final List<VirtualFile> classRoots = getClassRoots();
+ final List<VirtualFile> classRoots = getClassRoots(scope);
if (classRoots.isEmpty()) {
return PsiClass.EMPTY_ARRAY;
}
@@ -160,7 +159,7 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
@NotNull
@Override
public Set<String> getClassNames(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
- final List<VirtualFile> classRoots = getClassRoots();
+ final List<VirtualFile> classRoots = getClassRoots(scope);
if (classRoots.isEmpty()) {
return Collections.emptySet();
}
@@ -172,7 +171,8 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
final VirtualFile dir = classRoot.findFileByRelativePath(pkgName.replace('.', '/'));
if (dir != null && dir.isDirectory()) {
for (final VirtualFile file : dir.getChildren()) {
- if (!file.isDirectory() && "class".equals(file.getExtension())) {
+ if ((myCheckForSources && !file.isDirectory() && JavaFileType.DEFAULT_EXTENSION.equals(file.getExtension()))
+ || (!file.isDirectory() && "class".equals(file.getExtension()))) {
result.add(file.getNameWithoutExtension());
}
}
@@ -207,7 +207,7 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
@NotNull GlobalSearchScope scope,
@NotNull Processor<PsiDirectory> consumer,
boolean includeLibrarySources) {
- final List<VirtualFile> classRoots = getClassRoots();
+ final List<VirtualFile> classRoots = getClassRoots(scope);
if (classRoots.isEmpty()) {
return true;
}
@@ -237,7 +237,7 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
@NotNull
@Override
public PsiPackage[] getSubPackages(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
- final List<VirtualFile> classRoots = getClassRoots();
+ final List<VirtualFile> classRoots = getClassRoots(scope);
if (classRoots.isEmpty()) {
return super.getSubPackages(psiPackage, scope);
}
diff --git a/java/java-impl/src/com/intellij/psi/NonClasspathResolveScopeEnlarger.java b/java/java-impl/src/com/intellij/psi/NonClasspathResolveScopeEnlarger.java
index f6c8f8eb213e..01114788ac9d 100644
--- a/java/java-impl/src/com/intellij/psi/NonClasspathResolveScopeEnlarger.java
+++ b/java/java-impl/src/com/intellij/psi/NonClasspathResolveScopeEnlarger.java
@@ -1,5 +1,6 @@
package com.intellij.psi;
+import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VfsUtil;
@@ -17,7 +18,8 @@ public class NonClasspathResolveScopeEnlarger extends ResolveScopeEnlarger {
@Override
public SearchScope getAdditionalResolveScope(@NotNull VirtualFile file, Project project) {
- if ("class".equals(file.getExtension())) {
+ String fileExtension = file.getExtension();
+ if ("class".equals(fileExtension) || JavaFileType.DEFAULT_EXTENSION.equals(fileExtension)) {
for (PsiElementFinder finder : Extensions.getExtensions(PsiElementFinder.EP_NAME, project)) {
if (finder instanceof NonClasspathClassFinder) {
final List<VirtualFile> roots = ((NonClasspathClassFinder)finder).getClassRoots();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java
index 43b57aa4e607..96c48ece31b1 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@ import java.util.*;
public class ClassFileStubBuilder implements BinaryFileStubBuilder {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClassFileStubBuilder");
- public static final int STUB_VERSION = 7 + JavaFileElementType.STUB_VERSION;
+ public static final int STUB_VERSION = 8 + JavaFileElementType.STUB_VERSION;
@Override
public boolean acceptsFile(final VirtualFile file) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java
index 7c40209ff9cd..89ea3bcdf051 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,12 +29,13 @@ import com.intellij.psi.impl.java.stubs.impl.PsiTypeParameterStubImpl;
import com.intellij.psi.stubs.StubElement;
import com.intellij.util.ArrayUtil;
import com.intellij.util.cls.ClsFormatException;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.StringRef;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.text.CharacterIterator;
-import java.util.ArrayList;
+import java.util.List;
@SuppressWarnings({"HardCodedStringLiteral"})
public class SignatureParsing {
@@ -69,16 +70,20 @@ public class SignatureParsing {
//todo parse annotations on type param
PsiTypeParameterStub parameterStub = new PsiTypeParameterStubImpl(parent, StringRef.fromString(name.toString()));
- ArrayList<String> bounds = null;
+ List<String> bounds = ContainerUtil.newSmartList();
while (signatureIterator.current() == ':') {
signatureIterator.next();
String bound = parseTopLevelClassRefSignature(signatureIterator);
- if (bound != null && !bound.equals(CommonClassNames.JAVA_LANG_OBJECT)) {
- if (bounds == null) bounds = new ArrayList<String>();
+ if (bound != null) {
bounds.add(bound);
}
}
+ int size = bounds.size();
+ if (size > 0 && CommonClassNames.JAVA_LANG_OBJECT.equals(bounds.get(size - 1))) {
+ bounds.remove(size - 1);
+ }
+
StubBuildingVisitor.newReferenceList(JavaStubElementTypes.EXTENDS_BOUND_LIST, parameterStub, ArrayUtil.toStringArray(bounds));
return parameterStub;
diff --git a/java/java-tests/testData/codeInsight/copyReference/CopyFile_after.java b/java/java-tests/testData/codeInsight/copyReference/CopyFile_after.java
index b0c0783cccee..f1120f4828eb 100644
--- a/java/java-tests/testData/codeInsight/copyReference/CopyFile_after.java
+++ b/java/java-tests/testData/codeInsight/copyReference/CopyFile_after.java
@@ -1,3 +1,3 @@
class X {
- String s = "/x/x.txt<caret>";
+ String s = "x/x.txt<caret>";
}
diff --git a/java/java-tests/testData/psi/cls/mirror/Bounds.txt b/java/java-tests/testData/psi/cls/mirror/Bounds.txt
new file mode 100644
index 000000000000..ab190fdddf30
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/Bounds.txt
@@ -0,0 +1,13 @@
+
+ // IntelliJ API Decompiler stub source generated from a class file
+ // Implementation of methods is not available
+
+package pkg;
+
+class Bounds {
+ Bounds() { /* compiled code */ }
+
+ public static <T extends java.lang.Object & java.lang.Comparable<? super T>> T max(java.util.Collection<? extends T> collection) { /* compiled code */ }
+
+ public static <T> T max(java.util.Collection<? extends T> collection, java.util.Comparator<? super T> comparator) { /* compiled code */ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/Bounds.class b/java/java-tests/testData/psi/cls/mirror/pkg/Bounds.class
new file mode 100644
index 000000000000..ce57f184578b
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/Bounds.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/src/pkg/Bounds.java b/java/java-tests/testData/psi/cls/mirror/src/pkg/Bounds.java
new file mode 100644
index 000000000000..81bd3a012750
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/src/pkg/Bounds.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pkg;
+
+import java.util.Collection;
+import java.util.Comparator;
+
+class Bounds {
+ public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
+ return null;
+ }
+
+ public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) {
+ return null;
+ }
+}
diff --git a/java/java-tests/testData/psi/cls/stubBuilder/UtilCollections.txt b/java/java-tests/testData/psi/cls/stubBuilder/UtilCollections.txt
index d58e2e68de90..82d04fec4659 100644
--- a/java/java-tests/testData/psi/cls/stubBuilder/UtilCollections.txt
+++ b/java/java-tests/testData/psi/cls/stubBuilder/UtilCollections.txt
@@ -1693,7 +1693,7 @@ PsiJavaFileStub [java.util]
PsiModifierListStub[mask=9]
PsiTypeParameterListStub
PsiTypeParameter[T]
- PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Comparable<? super T>]
+ PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Object, java.lang.Comparable<? super T>]
PsiParameterListStub
PsiParameterStub[p1:java.util.List<? extends T>]
PsiModifierListStub[mask=0]
@@ -1704,7 +1704,7 @@ PsiJavaFileStub [java.util]
PsiModifierListStub[mask=10]
PsiTypeParameterListStub
PsiTypeParameter[T]
- PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Comparable<? super T>]
+ PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Object, java.lang.Comparable<? super T>]
PsiParameterListStub
PsiParameterStub[p1:java.util.List<? extends T>]
PsiModifierListStub[mask=0]
@@ -1715,7 +1715,7 @@ PsiJavaFileStub [java.util]
PsiModifierListStub[mask=10]
PsiTypeParameterListStub
PsiTypeParameter[T]
- PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Comparable<? super T>]
+ PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Object, java.lang.Comparable<? super T>]
PsiParameterListStub
PsiParameterStub[p1:java.util.List<? extends T>]
PsiModifierListStub[mask=0]
@@ -1843,7 +1843,7 @@ PsiJavaFileStub [java.util]
PsiModifierListStub[mask=9]
PsiTypeParameterListStub
PsiTypeParameter[T]
- PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Comparable<? super T>]
+ PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Object, java.lang.Comparable<? super T>]
PsiParameterListStub
PsiParameterStub[p1:java.util.Collection<? extends T>]
PsiModifierListStub[mask=0]
@@ -1863,7 +1863,7 @@ PsiJavaFileStub [java.util]
PsiModifierListStub[mask=9]
PsiTypeParameterListStub
PsiTypeParameter[T]
- PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Comparable<? super T>]
+ PsiRefListStub[EXTENDS_BOUNDS_LIST:java.lang.Object, java.lang.Comparable<? super T>]
PsiParameterListStub
PsiParameterStub[p1:java.util.Collection<? extends T>]
PsiModifierListStub[mask=0]
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/CopyReferenceTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/CopyReferenceTest.groovy
index fbae4d18ba7e..ae14f4857e8d 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/CopyReferenceTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/CopyReferenceTest.groovy
@@ -90,7 +90,7 @@ class Foo {
performCopy()
myFixture.configureByText 'a.txt', ''
performPaste()
- myFixture.checkResult "/a.java:2"
+ myFixture.checkResult "a.java:2"
}
public void _testMethodOverloadCopy() {
diff --git a/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java b/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java
index b9a4a189a6b0..728fd72951cc 100644
--- a/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@ public class ClsMirrorBuildingTest extends LightIdeaTestCase {
public void testClassRefs() { doTest(); }
public void testEA46236() { doTest("ValuedEnum"); }
public void testKotlinFunList() { doTest(); }
+ public void testBounds() { doTest(); }
private void doTest() {
doTest(getTestName(false));
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreator.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreator.java
index eb2987e13e03..5648eb96f16a 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreator.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreator.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.jps.incremental.artifacts.instructions;
+import com.intellij.openapi.util.Condition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -31,8 +32,23 @@ public interface ArtifactCompilerInstructionCreator {
void addDirectoryCopyInstructions(@NotNull File directory, @Nullable SourceFileFilter filter);
+ /**
+ * Add instruction to extract directory from a jar file into the current place in the artifact layout.
+ *
+ * @param jarFile jar file to extract
+ * @param pathInJar relative path to directory inside {@code jarFile} which need to be extracted. Use "/" to extract the whole jar contents
+ */
void addExtractDirectoryInstruction(@NotNull File jarFile, @NotNull String pathInJar);
+ /**
+ * Add instruction to extract directory from a jar file into the current place in the artifact layout.
+ * @param jarFile jar file to extract
+ * @param pathInJar relative path to directory inside {@code jarFile} which need to be extracted. Use "/" to extract the whole jar contents
+ * @param pathInJarFilter a filter instance specifying which entries should be extracted. It should accept paths inside the jar file
+ * relative to {@code pathInJar} root and return {@code true} if the entry should be extracted and {@code false} otherwise
+ */
+ void addExtractDirectoryInstruction(@NotNull File jarFile, @NotNull String pathInJar, @NotNull Condition<String> pathInJarFilter);
+
ArtifactCompilerInstructionCreator subFolder(@NotNull String directoryName);
ArtifactCompilerInstructionCreator archive(@NotNull String archiveFileName);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreatorBase.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreatorBase.java
index ee1ee1798f55..2e5aa50ad45b 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreatorBase.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreatorBase.java
@@ -15,14 +15,16 @@
*/
package org.jetbrains.jps.incremental.artifacts.instructions;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Conditions;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.PathUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.artifacts.JarPathUtil;
import org.jetbrains.jps.indices.IgnoredFileIndex;
import org.jetbrains.jps.indices.ModuleExcludeIndex;
-import org.jetbrains.jps.incremental.artifacts.JarPathUtil;
import java.io.File;
import java.io.IOException;
@@ -56,15 +58,22 @@ public abstract class ArtifactCompilerInstructionCreatorBase implements Artifact
@Override
public void addExtractDirectoryInstruction(@NotNull File jarFile, @NotNull String pathInJar) {
+ addExtractDirectoryInstruction(jarFile, pathInJar, Conditions.<String>alwaysTrue());
+ }
+
+ @Override
+ public void addExtractDirectoryInstruction(@NotNull File jarFile,
+ @NotNull String pathInJar,
+ @NotNull Condition<String> pathInJarFilter) {
//an entry of a jar file is excluded if and only if the jar file itself is excluded. In that case we should unpack entries to the artifact
- // because the jar itself is explicitly added to the artifact layout.
+ //because the jar itself is explicitly added to the artifact layout.
boolean includeExcluded = true;
final SourceFileFilterImpl filter = new SourceFileFilterImpl(null, myInstructionsBuilder.getRootsIndex(),
myInstructionsBuilder.getIgnoredFileIndex(), includeExcluded);
DestinationInfo destination = createDirectoryDestination();
if (destination != null) {
- ArtifactRootDescriptor descriptor = myInstructionsBuilder.createJarBasedRoot(jarFile, pathInJar, filter, destination);
+ ArtifactRootDescriptor descriptor = myInstructionsBuilder.createJarBasedRoot(jarFile, pathInJar, filter, destination, pathInJarFilter);
if (myInstructionsBuilder.addDestination(descriptor)) {
onAdded(descriptor);
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java
index ae9993d7214e..0352417b0e24 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.jps.incremental.artifacts.instructions;
+import com.intellij.openapi.util.Condition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTarget;
import org.jetbrains.jps.indices.IgnoredFileIndex;
@@ -79,7 +80,9 @@ public class ArtifactInstructionsBuilderImpl implements ArtifactInstructionsBuil
public JarBasedArtifactRootDescriptor createJarBasedRoot(@NotNull File jarFile,
@NotNull String pathInJar,
- @NotNull SourceFileFilter filter, final DestinationInfo destinationInfo) {
- return new JarBasedArtifactRootDescriptor(jarFile, pathInJar, filter, myRootIndex++, myBuildTarget, destinationInfo);
+ @NotNull SourceFileFilter filter,
+ @NotNull DestinationInfo destinationInfo,
+ @NotNull Condition<String> pathInJarFilter) {
+ return new JarBasedArtifactRootDescriptor(jarFile, pathInJar, filter, myRootIndex++, myBuildTarget, destinationInfo, pathInJarFilter);
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java
index 8c3f762238a0..c5eb04940b85 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.jps.incremental.artifacts.instructions;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
@@ -39,14 +40,18 @@ import java.util.zip.ZipFile;
*/
public class JarBasedArtifactRootDescriptor extends ArtifactRootDescriptor {
private final String myPathInJar;
+ private final Condition<String> myPathInJarFilter;
public JarBasedArtifactRootDescriptor(@NotNull File jarFile,
@NotNull String pathInJar,
@NotNull SourceFileFilter filter,
int index,
- ArtifactBuildTarget target, DestinationInfo destinationInfo) {
+ @NotNull ArtifactBuildTarget target,
+ @NotNull DestinationInfo destinationInfo,
+ @NotNull Condition<String> pathInJarFilter) {
super(jarFile, filter, index, target, destinationInfo);
myPathInJar = pathInJar;
+ myPathInJarFilter = pathInJarFilter;
}
public void processEntries(EntryProcessor processor) throws IOException {
@@ -68,7 +73,9 @@ public class JarBasedArtifactRootDescriptor extends ArtifactRootDescriptor {
final String name = entry.getName();
if (name.startsWith(prefix)) {
String relativePath = name.substring(prefix.length());
- processor.process(entry.isDirectory() ? null : zipFile.getInputStream(entry), relativePath, entry);
+ if (myPathInJarFilter.value(relativePath)) {
+ processor.process(entry.isDirectory() ? null : zipFile.getInputStream(entry), relativePath, entry);
+ }
}
}
}
diff --git a/native/WinLauncher/WinLauncher/WinLauncher.cpp b/native/WinLauncher/WinLauncher/WinLauncher.cpp
index e085b186a1b8..8d5ff13a46ed 100644
--- a/native/WinLauncher/WinLauncher/WinLauncher.cpp
+++ b/native/WinLauncher/WinLauncher/WinLauncher.cpp
@@ -190,7 +190,7 @@ bool LocateJVM()
return result;
}
- std::string jreDir = GetAdjacentDir("jre");
+ std::string jreDir = GetAdjacentDir(need64BitJRE ? "jre64":"jre");
if (FindValidJVM(jreDir.c_str()) && Is64BitJRE(jvmPath) == need64BitJRE)
{
return true;
diff --git a/platform/core-api/src/com/intellij/patterns/TreeElementPattern.java b/platform/core-api/src/com/intellij/patterns/TreeElementPattern.java
index 084be74c0031..f955f357007b 100644
--- a/platform/core-api/src/com/intellij/patterns/TreeElementPattern.java
+++ b/platform/core-api/src/com/intellij/patterns/TreeElementPattern.java
@@ -110,7 +110,7 @@ public abstract class TreeElementPattern<ParentType, T extends ParentType, Self
return withSuperParent(level, StandardPatterns.instanceOf(aClass));
}
public Self withSuperParent(final int level, @NotNull final ElementPattern<? extends ParentType> pattern) {
- return with(new PatternConditionPlus<T, ParentType>("withSuperParent", pattern) {
+ return with(new PatternConditionPlus<T, ParentType>(level == 1 ? "withParent" : "withSuperParent", pattern) {
@Override
public boolean processValues(T t,
diff --git a/platform/extensions/src/com/intellij/openapi/util/KeyedExtensionFactory.java b/platform/extensions/src/com/intellij/openapi/util/KeyedExtensionFactory.java
index 054cfe0d7f19..f815acf63c14 100644
--- a/platform/extensions/src/com/intellij/openapi/util/KeyedExtensionFactory.java
+++ b/platform/extensions/src/com/intellij/openapi/util/KeyedExtensionFactory.java
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.NotNull;
import org.picocontainer.PicoContainer;
import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@@ -94,6 +95,12 @@ public abstract class KeyedExtensionFactory<T, KeyT> {
break;
}
}
+ catch (InvocationTargetException e) {
+ if (e.getCause() instanceof RuntimeException) {
+ throw (RuntimeException)e.getCause();
+ }
+ throw new RuntimeException(e);
+ }
catch (RuntimeException e) {
throw e;
}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalModuleBuildClasspathPojo.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalModuleBuildClasspathPojo.java
new file mode 100644
index 000000000000..5783f9444d07
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalModuleBuildClasspathPojo.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.model.project;
+
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/14/14
+ */
+public class ExternalModuleBuildClasspathPojo {
+
+ @NotNull private List<String> myEntries;
+ @NotNull private String myPath;
+
+ @SuppressWarnings("UnusedDeclaration")
+ public ExternalModuleBuildClasspathPojo() {
+ // Used by IJ serialization
+ this("___DUMMY___", ContainerUtil.<String>newArrayList());
+ }
+
+ public ExternalModuleBuildClasspathPojo(@NotNull String path, @NotNull List<String> entries) {
+ myPath = path;
+ myEntries = entries;
+ }
+
+ @NotNull
+ public String getPath() {
+ return myPath;
+ }
+
+ public void setPath(@NotNull String path) {
+ myPath = path;
+ }
+
+ @NotNull
+ public List<String> getEntries() {
+ return myEntries;
+ }
+
+ public void setEntries(@NotNull List<String> entries) {
+ myEntries = entries;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myEntries.hashCode();
+ result = 31 * result + myPath.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ExternalModuleBuildClasspathPojo pojo = (ExternalModuleBuildClasspathPojo)o;
+
+ if (!myEntries.equals(pojo.myEntries)) return false;
+ if (!myPath.equals(pojo.myPath)) return false;
+
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return myPath;
+ }
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalProjectBuildClasspathPojo.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalProjectBuildClasspathPojo.java
new file mode 100644
index 000000000000..9fb2ea65bb48
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalProjectBuildClasspathPojo.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.model.project;
+
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/14/14
+ */
+public class ExternalProjectBuildClasspathPojo {
+
+ /**
+ * Common for all project modules build classpath. E.g. it can be build system SDK libraries, configured at project level.
+ */
+ @NotNull private List<String> myProjectBuildClasspath;
+ @NotNull private Map<String, ExternalModuleBuildClasspathPojo> myModulesBuildClasspath;
+ @NotNull private String myName;
+
+ @SuppressWarnings("UnusedDeclaration")
+ public ExternalProjectBuildClasspathPojo() {
+ // Used by IJ serialization
+ this("___DUMMY___", ContainerUtil.<String>newArrayList(), ContainerUtil.<String, ExternalModuleBuildClasspathPojo>newHashMap());
+ }
+
+ public ExternalProjectBuildClasspathPojo(@NotNull String name,
+ @NotNull List<String> projectBuildClasspath,
+ @NotNull Map<String, ExternalModuleBuildClasspathPojo> modulesBuildClasspath) {
+ myName = name;
+ myProjectBuildClasspath = projectBuildClasspath;
+ myModulesBuildClasspath = modulesBuildClasspath;
+ }
+
+ @NotNull
+ public String getName() {
+ return myName;
+ }
+
+ public void setName(@NotNull String name) {
+ myName = name;
+ }
+
+ @NotNull
+ public Map<String, ExternalModuleBuildClasspathPojo> getModulesBuildClasspath() {
+ return myModulesBuildClasspath;
+ }
+
+ public void setModulesBuildClasspath(@NotNull Map<String, ExternalModuleBuildClasspathPojo> modulesBuildClasspath) {
+ myModulesBuildClasspath = modulesBuildClasspath;
+ }
+
+ @NotNull
+ public List<String> getProjectBuildClasspath() {
+ return myProjectBuildClasspath;
+ }
+
+ public void setProjectBuildClasspath(@NotNull List<String> projectBuildClasspath) {
+ myProjectBuildClasspath = projectBuildClasspath;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myModulesBuildClasspath.hashCode();
+ result = 31 * result + myModulesBuildClasspath.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ExternalProjectBuildClasspathPojo pojo = (ExternalProjectBuildClasspathPojo)o;
+
+ if (!myModulesBuildClasspath.equals(pojo.myModulesBuildClasspath)) return false;
+ if (!myName.equals(pojo.myName)) return false;
+
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return myName;
+ }
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/psi/search/ExternalModuleBuildGlobalSearchScope.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/psi/search/ExternalModuleBuildGlobalSearchScope.java
new file mode 100644
index 000000000000..acd5c80c671c
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/psi/search/ExternalModuleBuildGlobalSearchScope.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.psi.search;
+
+import com.intellij.psi.search.DelegatingGlobalSearchScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/15/14
+ */
+public class ExternalModuleBuildGlobalSearchScope extends DelegatingGlobalSearchScope {
+
+ @NotNull
+ private final String externalModulePath;
+
+ public ExternalModuleBuildGlobalSearchScope(@NotNull GlobalSearchScope baseScope, @NotNull String externalModulePath) {
+ super(baseScope);
+ this.externalModulePath = externalModulePath;
+ }
+
+ @NotNull
+ public String getExternalModulePath() {
+ return externalModulePath;
+ }
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemLocalSettings.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemLocalSettings.java
index 86550eea5b22..aa6950933390 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemLocalSettings.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemLocalSettings.java
@@ -19,6 +19,7 @@ import com.intellij.openapi.externalSystem.ExternalSystemManager;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.model.execution.ExternalTaskExecutionInfo;
import com.intellij.openapi.externalSystem.model.execution.ExternalTaskPojo;
+import com.intellij.openapi.externalSystem.model.project.ExternalProjectBuildClasspathPojo;
import com.intellij.openapi.externalSystem.model.project.ExternalProjectPojo;
import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
@@ -64,6 +65,10 @@ public abstract class AbstractExternalSystemLocalSettings {
new AtomicReference<Map<String, Collection<ExternalTaskPojo>>>(
ContainerUtilRt.<String, Collection<ExternalTaskPojo>>newHashMap()
);
+ private final AtomicReference<Map<String/* external project config path */, ExternalProjectBuildClasspathPojo>> myProjectBuildClasspath =
+ new AtomicReference<Map<String, ExternalProjectBuildClasspathPojo>>(
+ ContainerUtilRt.<String, ExternalProjectBuildClasspathPojo>newHashMap()
+ );
private final AtomicReference<Map<String/* external project config path */, Long>>
myExternalConfigModificationStamps =
new AtomicReference<Map<String, Long>>(ContainerUtilRt.<String, Long>newHashMap());
@@ -114,6 +119,15 @@ public abstract class AbstractExternalSystemLocalSettings {
}
}
+ for (Iterator<Map.Entry<String, ExternalProjectBuildClasspathPojo>> it = myProjectBuildClasspath.get().entrySet().iterator(); it.hasNext(); ) {
+ Map.Entry<String, ExternalProjectBuildClasspathPojo> entry = it.next();
+ if (linkedProjectPathsToForget.contains(entry.getKey())
+ || linkedProjectPathsToForget.contains(ExternalSystemApiUtil.getRootProjectPath(entry.getKey(), myExternalSystemId, myProject)))
+ {
+ it.remove();
+ }
+ }
+
Map<String, Long> modificationStamps = myExternalConfigModificationStamps.get();
for (String path : linkedProjectPathsToForget) {
modificationStamps.remove(path);
@@ -152,7 +166,7 @@ public abstract class AbstractExternalSystemLocalSettings {
public void setRecentTasks(@NotNull List<ExternalTaskExecutionInfo> tasks) {
myRecentTasks.set(tasks);
}
-
+
@NotNull
public Map<String, Long> getExternalConfigModificationStamps() {
return myExternalConfigModificationStamps.get();
@@ -163,7 +177,18 @@ public abstract class AbstractExternalSystemLocalSettings {
// Required for IJ serialization.
myExternalConfigModificationStamps.set(modificationStamps);
}
-
+
+ @NotNull
+ public Map<String, ExternalProjectBuildClasspathPojo> getProjectBuildClasspath() {
+ return myProjectBuildClasspath.get();
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ public void setProjectBuildClasspath(@NotNull Map<String, ExternalProjectBuildClasspathPojo> projectsBuildClasspath) {
+ // Required for IJ serialization.
+ myProjectBuildClasspath.set(projectsBuildClasspath);
+ }
+
public void fillState(@NotNull State state) {
if (PRESERVE_EXPAND_STATE) {
state.tasksExpandState = myExpandStates.get();
@@ -175,6 +200,7 @@ public abstract class AbstractExternalSystemLocalSettings {
state.availableProjects = myAvailableProjects.get();
state.availableTasks = myAvailableTasks.get();
state.modificationStamps = myExternalConfigModificationStamps.get();
+ state.projectBuildClasspath = myProjectBuildClasspath.get();
}
public void loadState(@NotNull State state) {
@@ -182,6 +208,7 @@ public abstract class AbstractExternalSystemLocalSettings {
setIfNotNull(myAvailableProjects, state.availableProjects);
setIfNotNull(myAvailableTasks, state.availableTasks);
setIfNotNull(myExternalConfigModificationStamps, state.modificationStamps);
+ setIfNotNull(myProjectBuildClasspath, state.projectBuildClasspath);
if (state.recentTasks != null) {
List<ExternalTaskExecutionInfo> recentTasks = myRecentTasks.get();
if (recentTasks != state.recentTasks) {
@@ -242,5 +269,6 @@ public abstract class AbstractExternalSystemLocalSettings {
public Map<String/* linked project path */, Long/* last config modification stamp */> modificationStamps
= ContainerUtilRt.newHashMap();
+ public Map<String/* linked project path */, ExternalProjectBuildClasspathPojo> projectBuildClasspath = ContainerUtilRt.newHashMap();
}
}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java
index 7b078c7debfe..af0772dd7b31 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java
@@ -318,6 +318,24 @@ public class ExternalSystemApiUtil {
}
@SuppressWarnings("unchecked")
+ @Nullable
+ public static <T> DataNode<T> findParent(@NotNull DataNode<?> node, @NotNull Key<T> key) {
+ return findParent(node, key, null);
+ }
+
+
+ @SuppressWarnings("unchecked")
+ @Nullable
+ public static <T> DataNode<T> findParent(@NotNull DataNode<?> node,
+ @NotNull Key<T> key,
+ @Nullable BooleanFunction<DataNode<T>> predicate) {
+ DataNode<?> parent = node.getParent();
+ if (parent == null) return null;
+ return key.equals(parent.getKey()) && (predicate == null || predicate.fun((DataNode<T>)parent))
+ ? (DataNode<T>)parent : findParent(parent, key, predicate);
+ }
+
+ @SuppressWarnings("unchecked")
@NotNull
public static <T> Collection<DataNode<T>> findAll(@NotNull DataNode<?> parent, @NotNull Key<T> key) {
Collection<DataNode<T>> result = null;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java b/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java
index 89413c5899b0..9f14e0021900 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java
@@ -171,8 +171,9 @@ public class AutoPopupController implements Disposable {
final Runnable request = new Runnable(){
@Override
public void run(){
- if (myProject.isDisposed() || DumbService.isDumb(myProject) || editor.isDisposed()) return;
+ if (myProject.isDisposed() || DumbService.isDumb(myProject)) return;
documentManager.commitAllDocuments();
+ if (editor.isDisposed() || !editor.getComponent().isShowing()) return;
int lbraceOffset = editor.getCaretModel().getOffset() - 1;
try {
ShowParameterInfoHandler.invoke(myProject, editor, file1, lbraceOffset, highlightedMethod);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java
index 1aa02d4cbe3d..39e0b5d32e2c 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java
@@ -705,6 +705,10 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
}
private static boolean shouldPreselectFirstSuggestion(CompletionParameters parameters) {
+ if (!Registry.is("ide.completion.autopopup.choose.by.enter")) {
+ return false;
+ }
+
if (!ApplicationManager.getApplication().isUnitTestMode()) {
return true;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/wordSelection/NaturalLanguageTextSelectioner.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/wordSelection/NaturalLanguageTextSelectioner.java
index a574ce0c5465..dc5d9f32072e 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/wordSelection/NaturalLanguageTextSelectioner.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/wordSelection/NaturalLanguageTextSelectioner.java
@@ -44,6 +44,9 @@ public class NaturalLanguageTextSelectioner extends ExtendWordSelectionHandlerBa
private static TextRange findParagraphRange(String text, int start, int end) {
int paragraphStart = text.lastIndexOf("\n\n", start);
int paragraphEnd = text.indexOf("\n\n", end);
+ if (paragraphStart >= paragraphEnd) {
+ return new TextRange(0, text.length());
+ }
return new TextRange(paragraphStart >= 0 ? paragraphStart + 2 : 0, paragraphEnd < 0 ? text.length() : paragraphEnd);
}
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/RestoreViewAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/RestoreViewAction.java
index cff9749eaf04..61676bbc7044 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/RestoreViewAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/RestoreViewAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,12 +17,15 @@
package com.intellij.execution.ui.layout.actions;
import com.intellij.execution.ui.layout.CellTransform;
+import com.intellij.icons.AllIcons;
import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.ui.content.Content;
+import javax.swing.*;
+
public class RestoreViewAction extends AnAction {
private final Content myContent;
@@ -38,7 +41,8 @@ public class RestoreViewAction extends AnAction {
Presentation p = e.getPresentation();
p.setText(ActionsBundle.message("action.Runner.RestoreView.text", myContent.getDisplayName()));
p.setDescription(ActionsBundle.message("action.Runner.RestoreView.description"));
- p.setIcon(myContent.getIcon());
+ Icon icon = myContent.getIcon();
+ p.setIcon(icon == null ? AllIcons.Debugger.RestoreLayout : icon);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/CopyReferenceAction.java b/platform/lang-impl/src/com/intellij/ide/actions/CopyReferenceAction.java
index 6cc5dda69dff..7d53a7d3a5d9 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/CopyReferenceAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/CopyReferenceAction.java
@@ -20,7 +20,10 @@ import com.intellij.codeInsight.daemon.impl.IdentifierUtil;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.dnd.FileCopyPasteUtil;
-import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.ActionPlaces;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.EditorColors;
@@ -33,14 +36,12 @@ import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.ex.StatusBarEx;
import com.intellij.psi.*;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.LogicalRoot;
-import com.intellij.util.LogicalRootsManager;
+import com.intellij.util.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -84,7 +85,7 @@ public class CopyReferenceAction extends DumbAwareAction {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
PsiElement element = getElementToCopy(editor, dataContext);
- if (!doCopy(element, project, editor) && editor != null) {
+ if (!doCopy(element, project, editor) && editor != null && project != null) {
Document document = editor.getDocument();
PsiFile file = PsiDocumentManager.getInstance(project).getCachedPsiFile(document);
if (file != null) {
@@ -98,7 +99,7 @@ public class CopyReferenceAction extends DumbAwareAction {
HighlightManager highlightManager = HighlightManager.getInstance(project);
EditorColorsManager manager = EditorColorsManager.getInstance();
TextAttributes attributes = manager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
- if (element != null && editor != null) {
+ if (element != null && editor != null && project != null) {
PsiElement nameIdentifier = IdentifierUtil.getNameIdentifier(element);
if (nameIdentifier != null) {
highlightManager.addOccurrenceHighlights(editor, new PsiElement[]{nameIdentifier}, attributes, true, null);
@@ -181,7 +182,7 @@ public class CopyReferenceAction extends DumbAwareAction {
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
- return ArrayUtil.find(getTransferDataFlavors(), flavor) != -1;
+ return ArrayUtilRt.find(getTransferDataFlavors(), flavor) != -1;
}
@Override
@@ -238,16 +239,16 @@ public class CopyReferenceAction extends DumbAwareAction {
}
final Project project = file.getProject();
final LogicalRoot logicalRoot = LogicalRootsManager.getLogicalRootsManager(project).findLogicalRoot(virtualFile);
- if (logicalRoot != null) {
- String logical = FileUtil.toSystemIndependentName(VfsUtil.virtualToIoFile(logicalRoot.getVirtualFile()).getPath());
- String path = FileUtil.toSystemIndependentName(VfsUtil.virtualToIoFile(virtualFile).getPath());
- return "/" + FileUtil.getRelativePath(logical, path, '/');
+ if (logicalRoot != null && logicalRoot.getVirtualFile() != null) {
+ String logical = FileUtil.toSystemIndependentName(VfsUtilCore.virtualToIoFile(logicalRoot.getVirtualFile()).getPath());
+ String path = FileUtil.toSystemIndependentName(VfsUtilCore.virtualToIoFile(virtualFile).getPath());
+ return ObjectUtils.assertNotNull(FileUtil.getRelativePath(logical, path, '/'));
}
final VirtualFile contentRoot = ProjectRootManager.getInstance(project).getFileIndex().getContentRootForFile(virtualFile);
if (contentRoot != null) {
- return "/" + FileUtil.getRelativePath(VfsUtil.virtualToIoFile(contentRoot), VfsUtil.virtualToIoFile(virtualFile));
- }
+ return ObjectUtils.assertNotNull(FileUtil.getRelativePath(VfsUtilCore.virtualToIoFile(contentRoot), VfsUtilCore.virtualToIoFile(virtualFile)));
+ }
return virtualFile.getPath();
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/CreateDirectoryOrPackageHandler.java b/platform/lang-impl/src/com/intellij/ide/actions/CreateDirectoryOrPackageHandler.java
index e95196cecd54..9b8fc331a471 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/CreateDirectoryOrPackageHandler.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/CreateDirectoryOrPackageHandler.java
@@ -28,6 +28,7 @@ import com.intellij.openapi.fileTypes.UnknownFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.InputValidatorEx;
import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFileSystemItem;
@@ -104,7 +105,7 @@ public class CreateDirectoryOrPackageHandler implements InputValidatorEx {
}
boolean createFile = false;
- if (StringUtil.countChars(subDirName, '.') == 1) {
+ if (StringUtil.countChars(subDirName, '.') == 1 && Registry.is("ide.suggest.file.when.creating.filename.like.directory")) {
FileType fileType = findFileTypeBoundToName(subDirName);
if (fileType != null) {
String message = "The name you entered looks like a file name. Do you want to create a file named " + subDirName + " instead?";
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
index 558a29c4aae1..6da322a9ad11 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@ import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.actions.TextComponentEditorAction;
+import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileEditor.impl.EditorHistoryManager;
import com.intellij.openapi.keymap.KeymapManager;
@@ -438,10 +439,10 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
parent.repaint();
}
});
- if (myPopup != null && myPopup.isVisible()) {
- myPopup.cancel();
- myPopup = null;
- }
+ //if (myPopup != null && myPopup.isVisible()) {
+ // myPopup.cancel();
+ // myPopup = null;
+ //}
rebuildList("");
}
@@ -674,6 +675,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
myBalloon = builder
.setCancelOnClickOutside(true)
.setModalContext(false)
+ .setRequestFocus(true)
.setCancelCallback(new Computable<Boolean>() {
@Override
public Boolean compute() {
@@ -1393,7 +1395,14 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
private void buildRecentFiles(String pattern) {
final MinusculeMatcher matcher = new MinusculeMatcher("*" + pattern, NameUtil.MatchingCaseSensitivity.NONE);
final ArrayList<VirtualFile> files = new ArrayList<VirtualFile>();
+ FileEditorManager editorManager = FileEditorManager.getInstance(project);
+ //we skip active editor
+ boolean skip = editorManager.getOpenFiles().length > 1;
for (VirtualFile file : ArrayUtil.reverseArray(EditorHistoryManager.getInstance(project).getFiles())) {
+ if (skip) {
+ skip = false;
+ continue;
+ }
if (StringUtil.isEmptyOrSpaces(pattern) || matcher.matches(file.getName())) {
if (!files.contains(file)) {
files.add(file);
diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java
index c9cb262b46af..0b0055748132 100644
--- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java
@@ -358,6 +358,8 @@ public class AllFileTemplatesConfigurable implements SearchableConfigurable, Con
}
private void onTabChanged() {
+ applyEditor(myCurrentTab.getSelectedTemplate());
+
final int selectedIndex = myTabbedPane.getSelectedIndex();
if (0 <= selectedIndex && selectedIndex < myTabs.length) {
myCurrentTab = myTabs[selectedIndex];
@@ -371,17 +373,8 @@ public class AllFileTemplatesConfigurable implements SearchableConfigurable, Con
if (prevTemplate != selectedValue) {
LOG.assertTrue(myEditor != null, "selected:" + selectedValue + "; prev:" + prevTemplate);
//selection has changed
- if (myEditor.isModified() && Arrays.asList(myCurrentTab.getTemplates()).contains(prevTemplate)) {
- try {
- myModified = true;
- myEditor.apply();
- fireListChanged();
- }
- catch (ConfigurationException e) {
- myCurrentTab.selectTemplate(prevTemplate);
- Messages.showErrorDialog(myMainPanel, e.getMessage(), IdeBundle.message("title.cannot.save.current.template"));
- return;
- }
+ if (Arrays.asList(myCurrentTab.getTemplates()).contains(prevTemplate) && !applyEditor(prevTemplate)) {
+ return;
}
if (selectedValue == null) {
myEditor.setTemplate(null, FileTemplateManagerImpl.getInstanceImpl().getDefaultTemplateDescription());
@@ -393,6 +386,24 @@ public class AllFileTemplatesConfigurable implements SearchableConfigurable, Con
}
}
+ private boolean applyEditor(FileTemplate prevTemplate) {
+ if (myEditor.isModified()) {
+ try {
+ myModified = true;
+ myEditor.apply();
+ fireListChanged();
+ }
+ catch (ConfigurationException e) {
+ if (Arrays.asList(myCurrentTab.getTemplates()).contains(prevTemplate)) {
+ myCurrentTab.selectTemplate(prevTemplate);
+ }
+ Messages.showErrorDialog(myMainPanel, e.getMessage(), IdeBundle.message("title.cannot.save.current.template"));
+ return false;
+ }
+ }
+ return true;
+ }
+
private void selectTemplate(FileTemplate template) {
URL defDesc = null;
if (myCurrentTab == myTemplatesList) {
diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/BundledFileTemplate.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/BundledFileTemplate.java
index 43833e79b3e1..0a1b4a5cb579 100644
--- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/BundledFileTemplate.java
+++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/BundledFileTemplate.java
@@ -101,4 +101,9 @@ public final class BundledFileTemplate extends FileTemplateBase {
public boolean isTextModified() {
return !getText().equals(getDefaultText());
}
+
+ @Override
+ public String toString() {
+ return myDefaultTemplate.getTemplateURL() == null ? "" : myDefaultTemplate.getTemplateURL().toString();
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java
index 1938241e6dab..b1b6cec2d2ad 100644
--- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java
+++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java
@@ -188,7 +188,8 @@ class FTManager {
final FileTemplateBase previous = myTemplates.put(qName, bundled);
mySortedTemplates = null;
- LOG.assertTrue(previous == null, "Duplicate bundled template " + qName);
+ LOG.assertTrue(previous == null, "Duplicate bundled template " + qName +
+ " [" + template.getTemplateURL() + ", " + previous + ']');
return bundled;
}
diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/AbstractNavBarModelExtension.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/AbstractNavBarModelExtension.java
index 91202fbce271..50079c02b027 100644
--- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/AbstractNavBarModelExtension.java
+++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/AbstractNavBarModelExtension.java
@@ -27,12 +27,10 @@ import java.util.Collections;
/**
* @author gregsh
*/
-public class AbstractNavBarModelExtension implements NavBarModelExtension {
+public abstract class AbstractNavBarModelExtension implements NavBarModelExtension {
@Nullable
@Override
- public String getPresentableText(Object object) {
- return null;
- }
+ public abstract String getPresentableText(Object object);
@Nullable
@Override
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java b/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java
index 4f7cae42da78..dd46f6496c46 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -406,7 +406,8 @@ public abstract class BaseProjectTreeBuilder extends AbstractTreeBuilder {
}
}
} else {
- async.setRejected();
+ //filter tells us to stop here (for instance, in case of module nodes)
+ break;
}
}
async.setRejected();
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileCellRenderer.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileCellRenderer.java
index 51f93300ca70..108868ccd192 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileCellRenderer.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileCellRenderer.java
@@ -82,7 +82,7 @@ public class GotoFileCellRenderer extends PsiElementListCellRenderer<PsiFileSyst
}
@Nullable
- private static String getRelativePath(final VirtualFile virtualFile, final Project project) {
+ static String getRelativePath(final VirtualFile virtualFile, final Project project) {
String url = virtualFile.getPresentableUrl();
if (project == null) {
return url;
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileModel.java
index 49081c710bde..de43de525209 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileModel.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileModel.java
@@ -128,7 +128,7 @@ public class GotoFileModel extends FilteringGotoByModel<FileType> {
public String getFullName(final Object element) {
if (element instanceof PsiFileSystemItem) {
final VirtualFile virtualFile = ((PsiFileSystemItem)element).getVirtualFile();
- return virtualFile != null ? virtualFile.getPath() : null;
+ return virtualFile != null ? GotoFileCellRenderer.getRelativePath(virtualFile, myProject) : null;
}
return getElementName(element);
diff --git a/platform/lang-impl/src/com/intellij/platform/ModuleAttachProcessor.java b/platform/lang-impl/src/com/intellij/platform/ModuleAttachProcessor.java
index 6053d01cded8..e5f458af9293 100644
--- a/platform/lang-impl/src/com/intellij/platform/ModuleAttachProcessor.java
+++ b/platform/lang-impl/src/com/intellij/platform/ModuleAttachProcessor.java
@@ -161,6 +161,11 @@ public class ModuleAttachProcessor extends ProjectAttachProcessor {
if (!canAttachToProject()) {
return null;
}
+ return findModuleInBaseDir(project);
+ }
+
+ @Nullable
+ public static Module findModuleInBaseDir(Project project) {
for (Module module : ModuleManager.getInstance(project).getModules()) {
final VirtualFile[] roots = ModuleRootManager.getInstance(module).getContentRoots();
for (VirtualFile root : roots) {
diff --git a/platform/lang-impl/src/com/intellij/platform/renameProject/RenameProjectHandler.java b/platform/lang-impl/src/com/intellij/platform/renameProject/RenameProjectHandler.java
index 9baec60bca13..2d44c86723e9 100644
--- a/platform/lang-impl/src/com/intellij/platform/renameProject/RenameProjectHandler.java
+++ b/platform/lang-impl/src/com/intellij/platform/renameProject/RenameProjectHandler.java
@@ -33,6 +33,7 @@ import com.intellij.openapi.ui.InputValidator;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import com.intellij.platform.ModuleAttachProcessor;
+import com.intellij.projectImport.ProjectAttachProcessor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.refactoring.RefactoringBundle;
@@ -101,7 +102,7 @@ public class RenameProjectHandler implements RenameHandler, TitledHandler {
@Override
public boolean canClose(final String inputString) {
- if (!inputString.equals(myProject.getName()) && (myModule == null || myModule == ModuleAttachProcessor.getPrimaryModule(myProject))) {
+ if (shouldRenameProject(inputString)) {
myProject.setProjectName(inputString);
myProject.save();
}
@@ -132,5 +133,21 @@ public class RenameProjectHandler implements RenameHandler, TitledHandler {
}
return true;
}
+
+ private boolean shouldRenameProject(String inputString) {
+ if (inputString.equals(myProject.getName())) {
+ return false;
+ }
+
+ if (myModule == null) {
+ return true;
+ }
+
+ if (ProjectAttachProcessor.canAttachToProject()) {
+ return myModule == ModuleAttachProcessor.getPrimaryModule(myProject);
+ }
+
+ return myModule == ModuleAttachProcessor.findModuleInBaseDir(myProject);
+ }
}
}
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
index bb98b700cf1a..1e8c431a5c0d 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
@@ -2457,7 +2457,8 @@ public class FileBasedIndexImpl extends FileBasedIndex {
@Override
public void removeIndexableSet(@NotNull IndexableFileSet set) {
- myChangedFilesCollector.forceUpdate(null, null, null, true);
+ if (!myIndexableSetToProjectMap.containsKey(set)) return; // avoid second unfiltered forceUpdate
+ myChangedFilesCollector.forceUpdate(myIndexableSetToProjectMap.get(set), null, null, true);
IndexingStamp.flushCaches();
myIndexableSets.remove(set);
myIndexableSetToProjectMap.remove(set);
diff --git a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptor.java b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptor.java
index a024b5b9d395..edcc97ec7cd5 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptor.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptor.java
@@ -81,27 +81,24 @@ public class FileChooserDescriptor implements Cloneable {
return myTitle;
}
- public final FileChooserDescriptor setTitle(String title) {
+ public final void setTitle(String title) {
myTitle = title;
- return this;
}
public boolean isShowFileSystemRoots() {
return myShowFileSystemRoots;
}
- public FileChooserDescriptor setShowFileSystemRoots(boolean showFileSystemRoots) {
+ public void setShowFileSystemRoots(boolean showFileSystemRoots) {
myShowFileSystemRoots = showFileSystemRoots;
- return this;
}
public final String getDescription() {
return myDescription;
}
- public final FileChooserDescriptor setDescription(String description) {
+ public final void setDescription(String description) {
myDescription = description;
- return this;
}
public final boolean isChooseJarContents() {
@@ -185,7 +182,6 @@ public class FileChooserDescriptor implements Cloneable {
/**
* the method is called upon pressing Ok in the FileChooserDialog
* Override the method in order to customize validation of user input
- *
* @param files - selected files to be checked
* @throws Exception if the the files cannot be accepted
*/
@@ -220,23 +216,21 @@ public class FileChooserDescriptor implements Cloneable {
return JarFileSystem.getInstance().findFileByPath(path + JarFileSystem.JAR_SEPARATOR);
}
- public final FileChooserDescriptor setHideIgnored(boolean hideIgnored) {
+ public final void setHideIgnored(boolean hideIgnored) {
myHideIgnored = hideIgnored;
- return this;
}
public final List<VirtualFile> getRoots() {
return Collections.unmodifiableList(myRoots);
}
- public final FileChooserDescriptor setRoots(final VirtualFile... roots) {
- return setRoots(Arrays.asList(roots));
+ public final void setRoots(final VirtualFile... roots) {
+ setRoots(Arrays.asList(roots));
}
- public final FileChooserDescriptor setRoots(@NotNull final List<VirtualFile> roots) {
+ public final void setRoots(@NotNull final List<VirtualFile> roots) {
myRoots.clear();
myRoots.addAll(roots);
- return this;
}
public boolean isTreeRootVisible() {
diff --git a/platform/platform-api/src/com/intellij/ui/AnActionButton.java b/platform/platform-api/src/com/intellij/ui/AnActionButton.java
index ca695085c33a..0e84519c3bf8 100644
--- a/platform/platform-api/src/com/intellij/ui/AnActionButton.java
+++ b/platform/platform-api/src/com/intellij/ui/AnActionButton.java
@@ -15,6 +15,7 @@
*/
package com.intellij.ui;
+import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.*;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.ui.UIUtil;
@@ -130,6 +131,10 @@ public abstract class AnActionButton extends AnAction implements ShortcutProvide
return myContextComponent;
}
+ public DataContext getDataContext() {
+ return DataManager.getInstance().getDataContext(getContextComponent());
+ }
+
private boolean isContextComponentOk() {
return myContextComponent == null
|| (myContextComponent.isVisible() && UIUtil.getParentOfType(JLayeredPane.class, myContextComponent) != null);
diff --git a/platform/platform-api/src/com/intellij/ui/DumbAwareActionButton.java b/platform/platform-api/src/com/intellij/ui/DumbAwareActionButton.java
new file mode 100644
index 000000000000..552ee968397f
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ui/DumbAwareActionButton.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ui;
+
+import com.intellij.openapi.project.DumbAware;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+ * @author gregsh
+ */
+public abstract class DumbAwareActionButton extends AnActionButton implements DumbAware {
+ public DumbAwareActionButton(String text) {
+ super(text);
+ }
+
+ public DumbAwareActionButton(String text, String description, @Nullable Icon icon) {
+ super(text, description, icon);
+ }
+
+ public DumbAwareActionButton(String text, Icon icon) {
+ super(text, icon);
+ }
+
+ public DumbAwareActionButton() {
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/ui/table/JBTable.java b/platform/platform-api/src/com/intellij/ui/table/JBTable.java
index ea2eebb5a127..f7f183fedbf2 100644
--- a/platform/platform-api/src/com/intellij/ui/table/JBTable.java
+++ b/platform/platform-api/src/com/intellij/ui/table/JBTable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -449,6 +449,7 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
return UIUtil.isUnderAlloyLookAndFeel()
|| UIUtil.isUnderNativeMacLookAndFeel()
|| UIUtil.isUnderDarcula()
+ || UIUtil.isUnderIntelliJLaF()
|| UIUtil.isUnderNimbusLookAndFeel()
|| UIUtil.isUnderWindowsLookAndFeel();
}
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/DebugLogManager.java b/platform/platform-impl/src/com/intellij/diagnostic/DebugLogManager.java
new file mode 100644
index 000000000000..39fa3c23eeb3
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/diagnostic/DebugLogManager.java
@@ -0,0 +1,100 @@
+/*
+ * 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.diagnostic;
+
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.components.ApplicationComponent;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.apache.log4j.Level;
+import org.apache.log4j.LogManager;
+import com.intellij.openapi.diagnostic.Logger;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+
+/**
+ * Allows to apply & persist custom log debug categories which can be turned on by user via the {@link com.intellij.ide.actions.DebugLogConfigureAction}. <br/>
+ * Applies these custom categories on startup.
+ */
+public class DebugLogManager extends ApplicationComponent.Adapter {
+
+ private static final Logger LOG = Logger.getInstance(DebugLogManager.class);
+ private static final String LOG_DEBUG_CATEGORIES = "log.debug.categories";
+
+ @Override
+ public void initComponent() {
+ List<String> categories = getSavedCategories();
+ if (categories.isEmpty()) {
+ saveCategories(getCurrentCategories());
+ }
+ else {
+ applyCategories(categories);
+ }
+ }
+
+ @NotNull
+ public List<String> getSavedCategories() {
+ String value = PropertiesComponent.getInstance().getValue(LOG_DEBUG_CATEGORIES);
+ return value == null ? Collections.<String>emptyList() : fromString(value);
+ }
+
+ public void applyCategories(@NotNull List<String> categories) {
+ for (String category : categories) {
+ org.apache.log4j.Logger logger = LogManager.getLogger(category);
+ if (logger != null) {
+ logger.setLevel(Level.DEBUG);
+ }
+ }
+ LOG.info("Set DEBUG for the following categories: " + categories);
+ }
+
+ public void saveCategories(@NotNull List<String> categories) {
+ PropertiesComponent.getInstance().setValue(LOG_DEBUG_CATEGORIES, toString(categories));
+ }
+
+ @NotNull
+ private static List<String> fromString(@NotNull String text) {
+ return Arrays.asList(StringUtil.splitByLines(text, true));
+ }
+
+ @NotNull
+ private static String toString(@NotNull List<String> categories) {
+ return StringUtil.join(categories, "\n");
+ }
+
+ @NotNull
+ private static List<String> getCurrentCategories() {
+ Enumeration currentLoggers = LogManager.getCurrentLoggers();
+ return ContainerUtil.mapNotNull(ContainerUtil.toList(currentLoggers), new Function<Object, String>() {
+ @Override
+ public String fun(Object o) {
+ if (o instanceof org.apache.log4j.Logger) {
+ String category = ((org.apache.log4j.Logger)o).getName();
+ if (Logger.getInstance(category).isDebugEnabled()) {
+ return category;
+ }
+ }
+ return null;
+ }
+ });
+ }
+
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
index 9e67590713ef..96d11aa2a2e3 100644
--- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
+++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -692,6 +692,7 @@ public class IdeEventQueue extends EventQueue {
myDispatchingFocusEvent = e instanceof FocusEvent;
maybeReady();
+ fixStickyAlt(e);
super.dispatchEvent(e);
}
@@ -705,6 +706,13 @@ public class IdeEventQueue extends EventQueue {
}
}
+ //IDEA-17359
+ private static void fixStickyAlt(AWTEvent e) {
+ if (SystemInfo.isWindowsXP && e instanceof KeyEvent && ((KeyEvent)e).getKeyCode() == KeyEvent.VK_ALT) {
+ ((KeyEvent)e).consume();
+ }
+ }
+
public boolean isDispatchingFocusEvent() {
return myDispatchingFocusEvent;
}
@@ -889,6 +897,8 @@ public class IdeEventQueue extends EventQueue {
boolean dispatch = true;
if (e instanceof KeyEvent) {
KeyEvent ke = (KeyEvent)e;
+ final Component component = ke.getComponent();
+ final Window window = component == null ? null : SwingUtilities.windowForComponent(component);
boolean pureAlt = ke.getKeyCode() == KeyEvent.VK_ALT && (ke.getModifiers() | InputEvent.ALT_MASK) == InputEvent.ALT_MASK;
if (!pureAlt) {
myPureAltWasPressed = false;
@@ -917,10 +927,14 @@ public class IdeEventQueue extends EventQueue {
}
else {
myWaiterScheduled = true;
+ //noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
+ if (SystemInfo.isWindows || window == null || !window.isActive()) {
+ return;
+ }
myWaitingForAltRelease = true;
if (myRobot == null) {
myRobot = new Robot();
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/DebugLogConfigureAction.java b/platform/platform-impl/src/com/intellij/ide/actions/DebugLogConfigureAction.java
new file mode 100644
index 000000000000..8cefd4eb320e
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/actions/DebugLogConfigureAction.java
@@ -0,0 +1,91 @@
+/*
+ * 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.ide.actions;
+
+import com.intellij.diagnostic.DebugLogManager;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.List;
+
+public class DebugLogConfigureAction extends DumbAwareAction {
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ Project project = e.getProject() == null ? ProjectManager.getInstance().getDefaultProject() : e.getProject();
+ DebugLogManager logCustomizer = ServiceManager.getService(DebugLogManager.class);
+ DebugLogConfigureDialog dialog = new DebugLogConfigureDialog(project, logCustomizer.getSavedCategories());
+ if (dialog.showAndGet()) {
+ List<String> categories = dialog.getLogCategories();
+ logCustomizer.applyCategories(categories);
+ logCustomizer.saveCategories(categories);
+ }
+ }
+
+ private static class DebugLogConfigureDialog extends DialogWrapper {
+
+ private static final String ALL_POSSIBLE_SEPARATORS = "(\n|,|;)+";
+ @NotNull private final JTextArea myTextArea;
+
+ protected DebugLogConfigureDialog(@Nullable Project project, List<String> categories) {
+ super(project, false);
+ myTextArea = new JTextArea(10, 30);
+ myTextArea.setText(StringUtil.join(categories, "\n"));
+ setTitle("Custom Debug Log Configuration");
+ init();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createNorthPanel() {
+ return new JBLabel("Add log categories separated by new lines");
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ return ScrollPaneFactory.createScrollPane(myTextArea);
+ }
+
+ @NotNull
+ public List<String> getLogCategories() {
+ return parseCategories(myTextArea.getText());
+ }
+
+ @NotNull
+ private static List<String> parseCategories(@NotNull String text) {
+ return ContainerUtil.mapNotNull(text.split(ALL_POSSIBLE_SEPARATORS), new Function<String, String>() {
+ @Override
+ public String fun(String s) {
+ return StringUtil.isEmptyOrSpaces(s) ? null : s.trim();
+ }
+ });
+ }
+ }
+
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java
index 47cb36d0f166..b05f14283689 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@ import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
@@ -36,10 +35,7 @@ public class ShowRecentFilesAction extends DumbAwareAction {
final Project project = e.getData(CommonDataKeys.PROJECT);
if (project != null) {
FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.recent.files");
- final Switcher.SwitcherPanel switcher = Switcher.createAndShowSwitcher(project, IdeBundle.message("title.popup.recent.files"), true);
- if (FileEditorManagerEx.getInstanceEx(project).hasOpenedFile()) {
- switcher.goForward();
- }
+ Switcher.createAndShowSwitcher(project, IdeBundle.message("title.popup.recent.files"), true);
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
index 57b707b54947..8884e7d42ab5 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -345,7 +345,12 @@ public class Switcher extends AnAction implements DumbAware {
final int maxFiles = Math.max(editors.size(), recentFiles.length);
final int len = isPinnedMode() ? recentFiles.length : Math.min(toolWindows.getModel().getSize(), maxFiles);
boolean firstRecentMarked = false;
+ final List<VirtualFile> selectedFiles = Arrays.asList(editorManager.getSelectedFiles());
for (int i = 0; i < len; i++) {
+ if (isPinnedMode() && selectedFiles.contains(recentFiles[i])) {
+ continue;
+ }
+
final FileInfo info = new FileInfo(recentFiles[i], null);
boolean add = true;
if (isPinnedMode()) {
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
index a708844200b7..f858002f0743 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -227,6 +227,7 @@ public class DarculaLaf extends BasicLookAndFeel {
//"ENTER", "selectNextRowCell",
"shift ENTER", "selectPreviousRowCell",
"ctrl A", "selectAll",
+ "meta A", "selectAll",
//"ESCAPE", "cancel",
"F2", "startEditing"
}));
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java
index cc0903619e28..0eba3d3ce28a 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -309,14 +309,19 @@ public class DarculaComboBoxUI extends BasicComboBoxUI implements Border {
comboBoxEditor.getEditorComponent().addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
- comboBox.revalidate();
- comboBox.repaint();
+ update();
+ }
+
+ void update() {
+ if (comboBox != null) {
+ comboBox.revalidate();
+ comboBox.repaint();
+ }
}
@Override
public void focusLost(FocusEvent e) {
- comboBox.revalidate();
- comboBox.repaint();
+ update();
}
});
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/OpenFilesActivity.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/OpenFilesActivity.java
index 94d0883c325c..62866d357dde 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/OpenFilesActivity.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/OpenFilesActivity.java
@@ -16,8 +16,6 @@
package com.intellij.openapi.fileEditor.impl;
import com.intellij.openapi.fileEditor.FileEditorManager;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupActivity;
@@ -44,15 +42,7 @@ public class OpenFilesActivity implements StartupActivity, DumbAware {
}
};
if (Registry.is("ide.open.editors.asynchronously")) {
- ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
- if (indicator != null) {
- indicator.pushState();
- indicator.setText("Preparing editors to open...");
- }
runnable.run();
- if (indicator != null) {
- indicator.popState();
- }
}
else {
UIUtil.invokeLaterIfNeeded(runnable);
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java
index 516480781c80..5d27509a6702 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java
@@ -114,6 +114,7 @@ public abstract class DummyCachingFileSystem<T extends VirtualFile> extends Dumm
throw new UnsupportedOperationException("not implemented");
}
+ @Nullable
public Project getProject(String projectId) {
List<Project> list = myProject2Id.getKeysByValue(projectId);
return list == null || list.size() > 1 ? null : list.get(0);
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java
index 08504b9e2609..d4477a330542 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@ import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.*;
import com.intellij.openapi.wm.impl.IdeFrameImpl;
@@ -110,7 +111,7 @@ class ToolWindowsWidget extends JLabel implements CustomStatusBarWidget, StatusB
popup.cancel();
}
}
- }, 150);
+ }, 300);
return true;
}
}
@@ -155,7 +156,7 @@ class ToolWindowsWidget extends JLabel implements CustomStatusBarWidget, StatusB
final Dimension size = list.getPreferredSize();
final JComponent c = ToolWindowsWidget.this;
final Insets padding = UIUtil.getListViewportPadding();
- final RelativePoint point = new RelativePoint(c, new Point(-4, -padding.top - padding.bottom -4 - size.height));
+ final RelativePoint point = new RelativePoint(c, new Point(-4, -padding.top - padding.bottom -4 - size.height + (SystemInfo.isMac ? 2 : 0)));
if (popup != null && popup.isVisible()) {
return;
diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties
index 87e2cb151662..a65aac00aa55 100644
--- a/platform/platform-resources-en/src/messages/ActionsBundle.properties
+++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties
@@ -1062,6 +1062,8 @@ action.Graph.print.preview=Print Preview
action.SendFeedback.text=Submit _Feedback
action.SendFeedback.description=Submit feedback to the JetBrains Web site
+action.LogDebugConfigure.text=Configure Debug Log Settings
+action.LogDebugConfigure.description=Enable or disable additional log categories. Allows to provide more information to the support team by request.
action.ShowLog.text=Open Log file
action.ShowLog.description=Opens folder with log file
action.TechnicalSupport.text=Contact _Support Team
diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties
index a12f869d2b64..9dfe64a0dc28 100644
--- a/platform/platform-resources-en/src/misc/registry.properties
+++ b/platform/platform-resources-en/src/misc/registry.properties
@@ -216,6 +216,9 @@ psi.incremental.reparse.depth.limit=1000
psi.viewer.selection.color=0,153,153
psi.deferIconLoading=true
+ide.suggest.file.when.creating.filename.like.directory=true
+ide.suggest.file.when.creating.filename.like.directory.description=When creating a directory named foo.txt, suggest to create a file with such a name instead
+
find.search.in.project.files=false
structureView.coalesceTime=500
@@ -235,6 +238,7 @@ projectView.showHierarchyErrors=true
projectView.hide.dot.idea=true
show.live.templates.in.completion=false
ide.completion.autopopup.select.live.templates=false
+ide.completion.autopopup.choose.by.enter=true
documentation.component.editor.font=false
ide.completion.show.better.matching.classes=true
diff --git a/platform/platform-resources/src/componentSets/Platform.xml b/platform/platform-resources/src/componentSets/Platform.xml
index 93daf4fceee2..ef911ec4b8b1 100644
--- a/platform/platform-resources/src/componentSets/Platform.xml
+++ b/platform/platform-resources/src/componentSets/Platform.xml
@@ -137,6 +137,10 @@
<implementation-class>com.intellij.ide.SystemHealthMonitor</implementation-class>
<headless-implementation-class/>
</component>
+
+ <component>
+ <implementation-class>com.intellij.diagnostic.DebugLogManager</implementation-class>
+ </component>
</application-components>
<project-components>
diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml
index f5ac0d5e0e6f..f31b83c52802 100644
--- a/platform/platform-resources/src/idea/PlatformActions.xml
+++ b/platform/platform-resources/src/idea/PlatformActions.xml
@@ -409,6 +409,7 @@
<separator/>
<action id="TechnicalSupport" class="com.intellij.ide.actions.TechnicalSupportAction"/>
<action id="SendFeedback" class="com.intellij.ide.actions.SendFeedbackAction"/>
+ <action id="LogDebugConfigure" class="com.intellij.ide.actions.DebugLogConfigureAction"/>
<action id="ShowLog" class="com.intellij.ide.actions.ShowLogAction"/>
<separator/>
<action id="OnlineDocAction" class="com.intellij.ide.actions.OnlineDocAction"/>
diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewTreeCellRenderer.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewTreeCellRenderer.java
index 06913a5667e6..06815acf5d73 100644
--- a/platform/usageView/src/com/intellij/usages/impl/UsageViewTreeCellRenderer.java
+++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewTreeCellRenderer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,19 +18,24 @@ package com.intellij.usages.impl;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.ui.ColoredTreeCellRenderer;
+import com.intellij.ui.DarculaColors;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.speedSearch.SpeedSearchUtil;
import com.intellij.usageView.UsageTreeColors;
import com.intellij.usageView.UsageTreeColorsScheme;
import com.intellij.usageView.UsageViewBundle;
import com.intellij.usages.*;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
+import java.awt.*;
/**
* @author max
@@ -40,6 +45,7 @@ class UsageViewTreeCellRenderer extends ColoredTreeCellRenderer {
private static final EditorColorsScheme ourColorsScheme = UsageTreeColorsScheme.getInstance().getScheme();
private static final SimpleTextAttributes ourInvalidAttributes = SimpleTextAttributes.fromTextAttributes(ourColorsScheme.getAttributes(UsageTreeColors.INVALID_PREFIX));
private static final SimpleTextAttributes ourReadOnlyAttributes = SimpleTextAttributes.fromTextAttributes(ourColorsScheme.getAttributes(UsageTreeColors.READONLY_PREFIX));
+ private static final SimpleTextAttributes ourInvalidAttributesDarcula = new SimpleTextAttributes(null, DarculaColors.RED, null, ourInvalidAttributes.getStyle());
private final SimpleTextAttributes myNumberOfUsagesAttribute;
private final UsageViewPresentation myPresentation;
@@ -57,7 +63,7 @@ class UsageViewTreeCellRenderer extends ColoredTreeCellRenderer {
if (value instanceof Node && tree != null && value != tree.getModel().getRoot()) {
Node node = (Node)value;
if (!node.isValid()) {
- append(UsageViewBundle.message("node.invalid") + " ", ourInvalidAttributes);
+ append(UsageViewBundle.message("node.invalid") + " ", UIUtil.isUnderDarcula() ? ourInvalidAttributesDarcula : ourInvalidAttributes);
}
if (myPresentation.isShowReadOnlyStatusAsRed() && node.isReadOnly()) {
showAsReadOnly = true;
diff --git a/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java b/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java
index 453b3bda47e1..2304be050c11 100644
--- a/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java
+++ b/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java
@@ -21,6 +21,7 @@ import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.io.Serializable;
import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
@@ -236,7 +237,9 @@ public class ContainerUtilRt {
* A variant of {@link java.util.Collections#emptyList()},
* except that {@link #toArray()} here does not create garbage <code>new Object[0]</code> constantly.
*/
- private static class EmptyList<T> extends AbstractList<T> implements RandomAccess {
+ private static class EmptyList<T> extends AbstractList<T> implements RandomAccess, Serializable {
+ private static final long serialVersionUID = 1L;
+
private static final EmptyList INSTANCE = new EmptyList();
@Override
diff --git a/platform/util/src/com/intellij/openapi/util/SystemInfo.java b/platform/util/src/com/intellij/openapi/util/SystemInfo.java
index c5ce5bb7e95d..aff4475faa94 100644
--- a/platform/util/src/com/intellij/openapi/util/SystemInfo.java
+++ b/platform/util/src/com/intellij/openapi/util/SystemInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,6 +52,7 @@ public class SystemInfo extends SystemInfoRt {
public static final boolean isWin2kOrNewer = isWindows && isOsVersionAtLeast("5.0");
public static final boolean isWinVistaOrNewer = isWindows && isOsVersionAtLeast("6.0");
public static final boolean isWin7OrNewer = isWindows && isOsVersionAtLeast("6.1");
+ public static final boolean isWindowsXP = isWindows && (OS_VERSION.equals("5.1") || OS_VERSION.equals("5.2"));
public static final boolean isXWindow = isUnix && !isMac;
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogBranchFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogBranchFilter.java
new file mode 100644
index 000000000000..2b658cbd3520
--- /dev/null
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogBranchFilter.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.vcs.log;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Tells to filter by some branch name.
+ */
+public interface VcsLogBranchFilter extends VcsLogFilter {
+
+ @NotNull
+ String getBranchName();
+
+}
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDateFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDateFilter.java
new file mode 100644
index 000000000000..d080b67a3e4c
--- /dev/null
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDateFilter.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.vcs.log;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Date;
+
+/**
+ * Tells to filter by date. <br/>
+ * Only before or after dates can be given, or both can be given.
+ */
+public interface VcsLogDateFilter {
+
+ /**
+ * If not null, only commits made after the returned date (inclusively) should be accepted.
+ */
+ @Nullable
+ Date getAfter();
+
+ /**
+ * If not null, only commits made before the returned date (inclusively) should be accepted.
+ */
+ @Nullable
+ Date getBefore();
+
+}
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java
index 0a730270c4a3..ae8ee646a898 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java
@@ -84,7 +84,12 @@ public interface VcsLogProvider {
*/
@NotNull
List<? extends VcsFullCommitDetails> getFilteredDetails(@NotNull VirtualFile root,
- @NotNull Collection<VcsLogFilter> filters, int maxCount) throws VcsException;
+ @NotNull Collection<VcsLogBranchFilter> branchFilters,
+ @NotNull Collection<VcsLogUserFilter> userFilters,
+ @NotNull Collection<VcsLogDateFilter> dateFilters,
+ @NotNull Collection<VcsLogTextFilter> textFilters,
+ @NotNull Collection<VcsLogStructureFilter> structureFilters,
+ int maxCount) throws VcsException;
/**
* Returns the name of current user as specified for the given root,
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogStructureFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogStructureFilter.java
new file mode 100644
index 000000000000..dd0ed62857c4
--- /dev/null
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogStructureFilter.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.vcs.log;
+
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+/**
+ * Tells the log to filter by files and folders.
+ */
+public interface VcsLogStructureFilter {
+
+ /**
+ * <p>Returns files from the given VCS root, which are affected by matching commits, and folders containing such files.</p>
+ *
+ * <p>That is: the commit A (made in the given VCS root) modifying file f.txt matches this filter,
+ * if this method returns a set which includes a folder containing f.txt, or the file f.txt itself.</p>
+ */
+ @NotNull
+ Collection<VirtualFile> getFiles(@NotNull VirtualFile root);
+
+}
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogTextFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogTextFilter.java
new file mode 100644
index 000000000000..06d84e997201
--- /dev/null
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogTextFilter.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.vcs.log;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Specifies the log filter by text.
+ */
+public interface VcsLogTextFilter {
+
+ /**
+ * Only commits containing the returned text it their commit messages should match the filter.
+ */
+ @NotNull
+ String getText();
+
+}
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUserFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUserFilter.java
new file mode 100644
index 000000000000..1cd6d95dd82d
--- /dev/null
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUserFilter.java
@@ -0,0 +1,18 @@
+package com.intellij.vcs.log;
+
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Filters log by user.
+ */
+public interface VcsLogUserFilter extends VcsLogFilter {
+
+ /**
+ * Returns the user name selected in the filter for the given root.
+ * If it is a name-as-text filter, of course, values don't differ per root. The difference appears if the special "me" filter is used.
+ */
+ @NotNull
+ String getUserName(@NotNull VirtualFile root);
+
+}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogBranchFilter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogBranchFilterImpl.java
index f7a4a62d1b05..90ca1e3cc000 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogBranchFilter.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogBranchFilterImpl.java
@@ -2,17 +2,18 @@ package com.intellij.vcs.log.data;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.vcs.log.VcsLogBranchFilter;
import com.intellij.vcs.log.VcsRef;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
-public class VcsLogBranchFilter implements VcsLogGraphFilter {
+public class VcsLogBranchFilterImpl implements VcsLogBranchFilter, VcsLogGraphFilter {
@NotNull private final Collection<Integer> myMatchingHeads;
@NotNull private final String myBranchName;
- public VcsLogBranchFilter(@NotNull Collection<VcsRef> allRefs, @NotNull final String selectedBranchName) {
+ public VcsLogBranchFilterImpl(@NotNull Collection<VcsRef> allRefs, @NotNull final String selectedBranchName) {
myBranchName = selectedBranchName;
myMatchingHeads = ContainerUtil.mapNotNull(allRefs, new Function<VcsRef, Integer>() {
@Override
@@ -35,6 +36,7 @@ public class VcsLogBranchFilter implements VcsLogGraphFilter {
return "on: " + myBranchName;
}
+ @Override
@NotNull
public String getBranchName() {
return myBranchName;
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java
index 547bb248dd48..f18697ae60b2 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java
@@ -24,6 +24,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.VcsException;
@@ -485,11 +486,25 @@ public class VcsLogDataHolder implements Disposable {
runInBackground(new ThrowableConsumer<ProgressIndicator, VcsException>() {
@Override
public void consume(ProgressIndicator indicator) throws VcsException {
+ List<VcsLogBranchFilter> branchFilters = ContainerUtil.findAll(filters, VcsLogBranchFilter.class);
+ List<VcsLogUserFilter> userFilters = ContainerUtil.findAll(filters, VcsLogUserFilter.class);
+ List<VcsLogDateFilter> dateFilters = ContainerUtil.findAll(filters, VcsLogDateFilter.class);
+ List<VcsLogTextFilter> textFilters = ContainerUtil.findAll(filters, VcsLogTextFilter.class);
+ List<VcsLogStructureFilter> structureFilters = ContainerUtil.findAll(filters, VcsLogStructureFilter.class);
Collection<List<? extends TimedVcsCommit>> logs = ContainerUtil.newArrayList();
final Map<Hash, VcsFullCommitDetails> allDetails = ContainerUtil.newHashMap();
for (Map.Entry<VirtualFile, VcsLogProvider> entry : myLogProviders.entrySet()) {
- List<? extends VcsFullCommitDetails> details = entry.getValue().getFilteredDetails(entry.getKey(), filters, maxCount);
+ VirtualFile root = entry.getKey();
+
+ List<VcsLogStructureFilter> rootMatchingStructureFilters = filterStructureFiltersByRoot(root, structureFilters);
+ if (rootMatchingStructureFilters.isEmpty() && !structureFilters.isEmpty()) {
+ // there were structure filters but none matches the root
+ continue;
+ }
+
+ List<? extends VcsFullCommitDetails> details = entry.getValue().getFilteredDetails(
+ root, branchFilters, userFilters, dateFilters, textFilters, rootMatchingStructureFilters, maxCount);
logs.add(getCommitsFromDetails(details));
for (VcsFullCommitDetails detail : details) {
allDetails.put(detail.getHash(), detail);
@@ -530,6 +545,17 @@ public class VcsLogDataHolder implements Disposable {
}
@NotNull
+ private static List<VcsLogStructureFilter> filterStructureFiltersByRoot(@NotNull final VirtualFile root,
+ @NotNull List<VcsLogStructureFilter> structureFilters) {
+ return ContainerUtil.filter(structureFilters, new Condition<VcsLogStructureFilter>() {
+ @Override
+ public boolean value(VcsLogStructureFilter filter) {
+ return !filter.getFiles(root).isEmpty();
+ }
+ });
+ }
+
+ @NotNull
public Map<VirtualFile, VcsUser> getCurrentUser() {
return myCurrentUser;
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDateFilter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDateFilterImpl.java
index 52103a5cd2b7..c879ddd88838 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDateFilter.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDateFilterImpl.java
@@ -16,17 +16,18 @@
package com.intellij.vcs.log.data;
import com.intellij.vcs.log.VcsFullCommitDetails;
+import com.intellij.vcs.log.VcsLogDateFilter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Date;
-public class VcsLogDateFilter implements VcsLogDetailsFilter {
+public class VcsLogDateFilterImpl implements VcsLogDateFilter, VcsLogDetailsFilter {
@Nullable private final Date myAfter;
@Nullable private final Date myBefore;
- public VcsLogDateFilter(@Nullable Date after, @Nullable Date before) {
+ public VcsLogDateFilterImpl(@Nullable Date after, @Nullable Date before) {
myAfter = after;
myBefore = before;
}
@@ -44,11 +45,13 @@ public class VcsLogDateFilter implements VcsLogDetailsFilter {
return matches;
}
+ @Override
@Nullable
public Date getAfter() {
return myAfter;
}
+ @Override
@Nullable
public Date getBefore() {
return myBefore;
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java
index 2c3011135dd5..da4d79d1ba3e 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java
@@ -3,6 +3,7 @@ package com.intellij.vcs.log.data;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.util.Ref;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
@@ -87,13 +88,13 @@ public class VcsLogFilterer {
myUI.updateUI();
if (model.getRowCount() == 0) {
- model.requestToLoadMore();
+ model.requestToLoadMore(EmptyRunnable.INSTANCE);
}
}
});
}
- public void requestVcs(@NotNull Collection<VcsLogFilter> filters, final LoadMoreStage loadMoreStage) {
+ public void requestVcs(@NotNull Collection<VcsLogFilter> filters, final LoadMoreStage loadMoreStage, @NotNull final Runnable onSuccess) {
ApplicationManager.getApplication().assertIsDispatchThread();
int maxCount;
if (loadMoreStage == LoadMoreStage.INITIAL) {
@@ -108,6 +109,7 @@ public class VcsLogFilterer {
LoadMoreStage newLoadMoreStage = advanceLoadMoreStage(loadMoreStage);
myUI.setModel(new NoGraphTableModel(myUI, details, myLogDataHolder.getDataPack().getRefsModel(), newLoadMoreStage));
myUI.updateUI();
+ onSuccess.run();
}
}, maxCount);
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java
index 6a0f4e3b7ce4..678cfd6fea17 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilter.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java
@@ -24,17 +24,18 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.vcs.log.VcsFullCommitDetails;
+import com.intellij.vcs.log.VcsLogStructureFilter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
-public class VcsLogStructureFilter implements VcsLogDetailsFilter {
+public class VcsLogStructureFilterImpl implements VcsLogDetailsFilter, VcsLogStructureFilter {
@NotNull private final Collection<VirtualFile> myFiles;
@NotNull private final MultiMap<VirtualFile, VirtualFile> myFilesByRoots;
- public VcsLogStructureFilter(@NotNull Collection<VirtualFile> files, Collection<VirtualFile> roots) {
+ public VcsLogStructureFilterImpl(@NotNull Collection<VirtualFile> files, Collection<VirtualFile> roots) {
myFiles = files;
myFilesByRoots = groupFilesByVcsRoots(files, roots);
}
@@ -87,6 +88,7 @@ public class VcsLogStructureFilter implements VcsLogDetailsFilter {
}) != null;
}
+ @Override
@NotNull
public Collection<VirtualFile> getFiles(@NotNull VirtualFile root) {
return myFilesByRoots.get(root);
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogUserFilter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogUserFilter.java
deleted file mode 100644
index 492c3108a91d..000000000000
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogUserFilter.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.intellij.vcs.log.data;
-
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.vcs.log.VcsFullCommitDetails;
-import com.intellij.vcs.log.VcsUser;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Map;
-
-/**
- * Filters log by user.
- */
-public abstract class VcsLogUserFilter implements VcsLogDetailsFilter {
-
- /**
- * Filters by the given name or part of it.
- */
- public static class ByName extends VcsLogUserFilter {
-
- @NotNull private final String myUser;
-
- public ByName(@NotNull String user) {
- myUser = user;
- }
-
- @Override
- public boolean matches(@NotNull VcsFullCommitDetails detail) {
- return detail.getAuthor().getName().toLowerCase().contains(myUser.toLowerCase()) ||
- detail.getAuthor().getEmail().toLowerCase().contains(myUser.toLowerCase());
- }
-
- @NotNull
- @Override
- public String getUserName(@NotNull VirtualFile root) {
- return myUser;
- }
- }
-
- /**
- * Looks for commits matching the current user,
- * i.e. looks for the value stored in the VCS config and compares the configured name with the one returned in commit details.
- */
- public static class Me extends VcsLogUserFilter {
-
- @NotNull private final Map<VirtualFile, VcsUser> myMeData;
-
- public Me(@NotNull Map<VirtualFile, VcsUser> meData) {
- myMeData = meData;
- }
-
- @Override
- public boolean matches(@NotNull VcsFullCommitDetails details) {
- VcsUser meInThisRoot = myMeData.get(details.getRoot());
- return meInThisRoot != null && meInThisRoot.equals(details.getAuthor());
- }
-
- @NotNull
- @Override
- public String getUserName(@NotNull VirtualFile root) {
- return myMeData.get(root).getName();
- }
- }
-
- /**
- * Returns the user name selected in the filter for the given root.
- * If it is a name-as-text filter, of course, values don't differ per root. The difference appears if the special "me" filter is used.
- */
- @NotNull
- public abstract String getUserName(@NotNull VirtualFile root);
-
-}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java
index e913daf84e8a..95d1631c5c1c 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java
@@ -3,6 +3,9 @@ package com.intellij.vcs.log.ui;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
+import com.intellij.util.PairFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import com.intellij.vcs.log.Hash;
@@ -234,33 +237,68 @@ public class VcsLogUI {
updateUI();
}
- public void jumpToCommit(final Hash commitHash) {
- int row = myLogDataHolder.getDataPack().getRowByHash(commitHash);
- if (row != -1) {
+ public void jumpToCommit(@NotNull Hash commitHash) {
+ jumpTo(commitHash, new PairFunction<AbstractVcsLogTableModel, Hash, Integer>() {
+ @Override
+ public Integer fun(AbstractVcsLogTableModel model, Hash hash) {
+ return model.getRowOfCommit(hash);
+ }
+ });
+ }
+
+ public void jumpToCommitByPartOfHash(@NotNull String commitHash) {
+ jumpTo(commitHash, new PairFunction<AbstractVcsLogTableModel, String, Integer>() {
+ @Override
+ public Integer fun(AbstractVcsLogTableModel model, String hash) {
+ return model.getRowOfCommitByPartOfHash(hash);
+ }
+ });
+ }
+
+ private <T> void jumpTo(@NotNull final T commitId, @NotNull final PairFunction<AbstractVcsLogTableModel, T, Integer> rowGetter) {
+ AbstractVcsLogTableModel model = getModel();
+ if (model == null) {
+ return;
+ }
+
+ int row = rowGetter.fun(model, commitId);
+ if (row >= 0) {
jumpToRow(row);
}
- else {
- myLogDataHolder.showFullLog(new Runnable() {
+ else if (model.canRequestMore()) {
+ model.requestToLoadMore(new Runnable() {
@Override
public void run() {
- jumpToCommit(commitHash);
+ jumpTo(commitId, rowGetter);
}
});
}
+ else {
+ commitNotFound(commitId.toString());
+ }
}
- public void jumpToCommitByPartOfHash(final String hash) {
- Node node = myLogDataHolder.getDataPack().getNodeByPartOfHash(hash);
- if (node != null) {
- jumpToRow(node.getRowIndex());
+ @Nullable
+ private AbstractVcsLogTableModel getModel() {
+ TableModel model = getTable().getModel();
+ if (model instanceof AbstractVcsLogTableModel) {
+ return (AbstractVcsLogTableModel)model;
}
- else if (!myLogDataHolder.isFullLogShowing()) {
- myLogDataHolder.showFullLog(new Runnable() {
- @Override
- public void run() {
- jumpToCommitByPartOfHash(hash);
- }
- });
+ showMessage(MessageType.WARNING, "The log is not ready to search yet");
+ return null;
+ }
+
+ private void showMessage(@NotNull MessageType messageType, @NotNull String message) {
+ LOG.info(message);
+ VcsBalloonProblemNotifier.showOverChangesView(myProject, message, messageType);
+ }
+
+ private void commitNotFound(@NotNull String commitHash) {
+ if (collectFilters().isEmpty()) {
+ showMessage(MessageType.WARNING, "Commit " + commitHash + " not found");
+ }
+ else {
+ showMessage(MessageType.WARNING, "Commit " + commitHash + " doesn't exist or doesn't match the active filters");
}
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java
index 4318e92e2433..aa7f1f9384e3 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java
@@ -20,7 +20,7 @@ import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.*;
-import com.intellij.vcs.log.data.VcsLogBranchFilter;
+import com.intellij.vcs.log.data.VcsLogBranchFilterImpl;
import com.intellij.vcs.log.impl.VcsLogUtil;
import com.intellij.vcs.log.ui.VcsLogUI;
import org.jetbrains.annotations.NotNull;
@@ -127,7 +127,7 @@ class BranchFilterPopupComponent extends FilterPopupComponent {
protected Collection<VcsLogFilter> getFilters() {
String value = getValue();
Collection<VcsRef> allBranches = myUi.getLogDataHolder().getDataPack().getRefsModel().getBranches();
- return value == ALL ? null : Collections.<VcsLogFilter>singleton(new VcsLogBranchFilter(allBranches, value));
+ return value == ALL ? null : Collections.<VcsLogFilter>singleton(new VcsLogBranchFilterImpl(allBranches, value));
}
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/DateFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/DateFilterPopupComponent.java
index 4c98df60957a..abac979df5df 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/DateFilterPopupComponent.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/DateFilterPopupComponent.java
@@ -24,7 +24,7 @@ import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.vcs.versionBrowser.DateFilterComponent;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.vcs.log.VcsLogFilter;
-import com.intellij.vcs.log.data.VcsLogDateFilter;
+import com.intellij.vcs.log.data.VcsLogDateFilterImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -69,7 +69,7 @@ class DateFilterPopupComponent extends FilterPopupComponent {
@Nullable
@Override
protected Collection<VcsLogFilter> getFilters() {
- return myAfter == null && myBefore == null ? null : Collections.<VcsLogFilter>singleton(new VcsLogDateFilter(myAfter, myBefore));
+ return myAfter == null && myBefore == null ? null : Collections.<VcsLogFilter>singleton(new VcsLogDateFilterImpl(myAfter, myBefore));
}
private void setOnlyAfter(Date after) {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java
index ed0f8cfd511d..ab5d4dd0e575 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java
@@ -24,7 +24,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.VcsLogFilter;
-import com.intellij.vcs.log.data.VcsLogStructureFilter;
+import com.intellij.vcs.log.data.VcsLogStructureFilterImpl;
import com.intellij.vcs.log.ui.VcsStructureChooser;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -53,7 +53,7 @@ class StructureFilterPopupComponent extends FilterPopupComponent {
@Nullable
@Override
protected Collection<VcsLogFilter> getFilters() {
- return getValue() == ALL || myFiles.isEmpty() ? null : Collections.<VcsLogFilter>singleton(new VcsLogStructureFilter(myFiles, myRoots));
+ return getValue() == ALL || myFiles.isEmpty() ? null : Collections.<VcsLogFilter>singleton(new VcsLogStructureFilterImpl(myFiles, myRoots));
}
private void setValue(@NotNull Collection<VirtualFile> files) {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java
index 69488bb5ad01..102d32e9fff5 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java
@@ -25,6 +25,7 @@ import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.*;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.spellchecker.ui.SpellCheckingEditorCustomization;
import com.intellij.ui.EditorCustomization;
import com.intellij.ui.EditorTextField;
@@ -33,11 +34,13 @@ import com.intellij.ui.SoftWrapsEditorCustomization;
import com.intellij.util.Function;
import com.intellij.util.TextFieldCompletionProviderDumbAware;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.vcs.log.VcsFullCommitDetails;
import com.intellij.vcs.log.VcsLogFilter;
import com.intellij.vcs.log.VcsUser;
import com.intellij.vcs.log.data.VcsLogDataHolder;
+import com.intellij.vcs.log.data.VcsLogDetailsFilter;
import com.intellij.vcs.log.data.VcsLogUiProperties;
-import com.intellij.vcs.log.data.VcsLogUserFilter;
+import com.intellij.vcs.log.VcsLogUserFilter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -101,7 +104,7 @@ class UserFilterPopupComponent extends FilterPopupComponent {
return ContainerUtil.map(mySelectedUsers, new Function<String, VcsLogFilter>() {
@Override
public VcsLogFilter fun(String name) {
- return name == ME ? new VcsLogUserFilter.Me(myDataHolder.getCurrentUser()) : new VcsLogUserFilter.ByName(name);
+ return name == ME ? new Me(myDataHolder.getCurrentUser()) : new ByName(name);
}
});
}
@@ -265,4 +268,54 @@ class UserFilterPopupComponent extends FilterPopupComponent {
}
}
}
+
+ /**
+ * Filters by the given name or part of it.
+ */
+ public static class ByName implements VcsLogUserFilter, VcsLogDetailsFilter {
+
+ @NotNull private final String myUser;
+
+ public ByName(@NotNull String user) {
+ myUser = user;
+ }
+
+ @Override
+ public boolean matches(@NotNull VcsFullCommitDetails detail) {
+ return detail.getAuthor().getName().toLowerCase().contains(myUser.toLowerCase()) ||
+ detail.getAuthor().getEmail().toLowerCase().contains(myUser.toLowerCase());
+ }
+
+ @NotNull
+ @Override
+ public String getUserName(@NotNull VirtualFile root) {
+ return myUser;
+ }
+ }
+
+ /**
+ * Looks for commits matching the current user,
+ * i.e. looks for the value stored in the VCS config and compares the configured name with the one returned in commit details.
+ */
+ public static class Me implements VcsLogUserFilter, VcsLogDetailsFilter {
+
+ @NotNull private final Map<VirtualFile, VcsUser> myMeData;
+
+ public Me(@NotNull Map<VirtualFile, VcsUser> meData) {
+ myMeData = meData;
+ }
+
+ @Override
+ public boolean matches(@NotNull VcsFullCommitDetails details) {
+ VcsUser meInThisRoot = myMeData.get(details.getRoot());
+ return meInThisRoot != null && meInThisRoot.equals(details.getAuthor());
+ }
+
+ @NotNull
+ @Override
+ public String getUserName(@NotNull VirtualFile root) {
+ return myMeData.get(root).getName();
+ }
+ }
+
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java
index d8bd69633b06..3cdf018f1a5c 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java
@@ -86,7 +86,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
public Collection<VcsLogFilter> getFilters() {
List<VcsLogFilter> filters = getPopupFilters();
if (!myTextFilter.getText().isEmpty()) {
- filters.add(new VcsLogTextFilter(myTextFilter.getText()));
+ filters.add(new VcsLogTextFilterImpl(myTextFilter.getText()));
}
return filters;
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogTextFilter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogTextFilterImpl.java
index 7c4c767161ba..64bb6eaf20b7 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogTextFilter.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogTextFilterImpl.java
@@ -16,14 +16,15 @@
package com.intellij.vcs.log.ui.filter;
import com.intellij.vcs.log.VcsFullCommitDetails;
+import com.intellij.vcs.log.VcsLogTextFilter;
import com.intellij.vcs.log.data.VcsLogDetailsFilter;
import org.jetbrains.annotations.NotNull;
-public class VcsLogTextFilter implements VcsLogDetailsFilter {
+public class VcsLogTextFilterImpl implements VcsLogDetailsFilter, VcsLogTextFilter {
@NotNull private final String myText;
- public VcsLogTextFilter(@NotNull String text) {
+ public VcsLogTextFilterImpl(@NotNull String text) {
myText = text;
}
@@ -32,6 +33,7 @@ public class VcsLogTextFilter implements VcsLogDetailsFilter {
return details.getFullMessage().toLowerCase().contains(myText.toLowerCase());
}
+ @Override
@NotNull
public String getText() {
return myText;
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java
index 7ff8c110baf3..aba0808a0117 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java
@@ -1,5 +1,6 @@
package com.intellij.vcs.log.ui.tables;
+import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile;
@@ -46,7 +47,7 @@ public abstract class AbstractVcsLogTableModel<CommitColumnClass, CommitId> exte
@Override
public final Object getValueAt(int rowIndex, int columnIndex) {
if (rowIndex >= getRowCount() - 1) {
- requestToLoadMore();
+ requestToLoadMore(EmptyRunnable.INSTANCE);
}
VcsShortCommitDetails data = getShortDetails(rowIndex);
@@ -74,7 +75,16 @@ public abstract class AbstractVcsLogTableModel<CommitColumnClass, CommitId> exte
}
}
- public abstract void requestToLoadMore();
+ /**
+ * Requests the proper data provider to load more data from the log & recreate the model.
+ * @param onLoaded will be called upon task completion on the EDT.
+ */
+ public abstract void requestToLoadMore(@NotNull Runnable onLoaded);
+
+ /**
+ * Returns true if not all data has been loaded, i.e. there is sense to {@link #requestToLoadMore(Runnable) request more data}.
+ */
+ public abstract boolean canRequestMore();
/**
* Returns Changes for commits at selected rows.<br/>
@@ -102,6 +112,18 @@ public abstract class AbstractVcsLogTableModel<CommitColumnClass, CommitId> exte
@Nullable
public abstract Hash getHashAtRow(int row);
+ /**
+ * Returns the row number containing the given commit,
+ * or -1 if the requested commit is not contained in this table model (possibly because not all data has been loaded).
+ */
+ public abstract int getRowOfCommit(@NotNull Hash hash);
+
+ /**
+ * Returns the number of the first row which contains a commit which hash starts with the given value,
+ * or -1 if no such commit was found (possibly because not all data has been loaded).
+ */
+ public abstract int getRowOfCommitByPartOfHash(@NotNull String hash);
+
@Override
public Class<?> getColumnClass(int column) {
switch (column) {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java
index 21e6cd4ecac7..2b48965e2686 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java
@@ -1,7 +1,6 @@
package com.intellij.vcs.log.ui.tables;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.vcs.log.Hash;
@@ -57,8 +56,13 @@ public class GraphTableModel extends AbstractVcsLogTableModel<GraphCommitCell, N
}
@Override
- public void requestToLoadMore() {
- myDataHolder.showFullLog(EmptyRunnable.INSTANCE);
+ public void requestToLoadMore(@NotNull Runnable onLoaded) {
+ myDataHolder.showFullLog(onLoaded);
+ }
+
+ @Override
+ public boolean canRequestMore() {
+ return !myDataHolder.isFullLogShowing();
}
@Nullable
@@ -120,4 +124,15 @@ public class GraphTableModel extends AbstractVcsLogTableModel<GraphCommitCell, N
return node == null ? null : myDataHolder.getHash(node.getCommitIndex());
}
+ @Override
+ public int getRowOfCommit(@NotNull final Hash hash) {
+ return myDataPack.getRowByHash(hash);
+ }
+
+ @Override
+ public int getRowOfCommitByPartOfHash(@NotNull String hash) {
+ Node node = myDataPack.getNodeByPartOfHash(hash);
+ return node != null ? node.getRowIndex() : -1;
+ }
+
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/NoGraphTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/NoGraphTableModel.java
index 1cdd138a6fc7..1cf9474b4a58 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/NoGraphTableModel.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/NoGraphTableModel.java
@@ -61,14 +61,19 @@ public class NoGraphTableModel extends AbstractVcsLogTableModel<CommitCell, Hash
}
@Override
- public void requestToLoadMore() {
+ public void requestToLoadMore(@NotNull Runnable onLoaded) {
if (myLoadMoreWasRequested.compareAndSet(false, true) // Don't send the request to VCS twice
&& myLoadMoreStage != LoadMoreStage.ALL_REQUESTED) { // or when everything possible is loaded
myUi.getTable().setPaintBusy(true);
- myUi.getFilterer().requestVcs(myUi.collectFilters(), myLoadMoreStage);
+ myUi.getFilterer().requestVcs(myUi.collectFilters(), myLoadMoreStage, onLoaded);
}
}
+ @Override
+ public boolean canRequestMore() {
+ return myLoadMoreStage != LoadMoreStage.ALL_REQUESTED;
+ }
+
@Nullable
@Override
public List<Change> getSelectedChanges(@NotNull List<Integer> selectedRows) {
@@ -115,4 +120,28 @@ public class NoGraphTableModel extends AbstractVcsLogTableModel<CommitCell, Hash
public Hash getHashAtRow(int row) {
return myCommits.get(row).getHash();
}
+
+ @Override
+ public int getRowOfCommit(@NotNull Hash hash) {
+ for (int i = 0; i < myCommits.size(); i++) {
+ VcsFullCommitDetails commit = myCommits.get(i);
+ if (commit.getHash().equals(hash)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int getRowOfCommitByPartOfHash(@NotNull String hash) {
+ String lowercaseHash = hash.toLowerCase();
+ for (int i = 0; i < myCommits.size(); i++) {
+ VcsFullCommitDetails commit = myCommits.get(i);
+ if (commit.getHash().toString().toLowerCase().startsWith(lowercaseHash)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
}
diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.form b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.form
index b77dd37c29d0..62fdc0efa396 100644
--- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.form
+++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.form
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.intellij.plugins.intelliLang.inject.config.ui.MethodParameterPanel">
- <grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <xy x="20" y="20" width="500" height="400"/>
+ <xy x="20" y="20" width="500" height="697"/>
</constraints>
<properties/>
<border type="none"/>
@@ -13,16 +13,16 @@
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</nested-form>
- <grid id="84778" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="84778" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="0" vgap="0">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<clientProperties>
- <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
+ <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithoutIndent"/>
</clientProperties>
- <border type="none" title="Class-Name"/>
+ <border type="none" title="Class Methods"/>
<children>
<grid id="5081f" binding="myClassPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
@@ -32,22 +32,9 @@
<border type="none"/>
<children/>
</grid>
- </children>
- </grid>
- <grid id="b75a2" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
- <margin top="0" left="0" bottom="0" right="0"/>
- <constraints>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- <clientProperties>
- <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithoutIndent"/>
- </clientProperties>
- <border type="none" title="Parameters"/>
- <children>
<scrollpane id="5dfaa" class="com.intellij.ui.components.JBScrollPane">
<constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -62,7 +49,7 @@
</grid>
<nested-form id="b6e0b" form-file="org/intellij/plugins/intelliLang/inject/config/ui/AdvancedPanel.form" binding="myAdvancedPanel" custom-create="true">
<constraints>
- <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</nested-form>
</children>
diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.java
index 36da2a930603..0c1cf6408c26 100644
--- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.java
+++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/ui/MethodParameterPanel.java
@@ -28,6 +28,7 @@ import com.intellij.openapi.util.Condition;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiFormatUtil;
+import com.intellij.psi.util.PsiFormatUtilBase;
import com.intellij.ui.*;
import com.intellij.ui.dualView.TreeTableView;
import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns;
@@ -42,6 +43,7 @@ import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.intellij.plugins.intelliLang.inject.config.MethodParameterInjection;
import org.intellij.plugins.intelliLang.util.PsiUtilEx;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -91,23 +93,23 @@ public class MethodParameterPanel extends AbstractInjectionPanel<MethodParameter
myParamsTable.getTree().setShowsRootHandles(true);
myParamsTable.getTree().setCellRenderer(new ColoredTreeCellRenderer() {
- public void customizeCellRenderer(final JTree tree,
- final Object value,
- final boolean selected,
- final boolean expanded,
- final boolean leaf,
- final int row,
- final boolean hasFocus) {
+ public void customizeCellRenderer(@NotNull JTree tree,
+ Object value,
+ boolean selected,
+ boolean expanded,
+ boolean leaf,
+ int row,
+ boolean hasFocus) {
final Object o = ((DefaultMutableTreeNode)value).getUserObject();
setIcon(o instanceof PsiMethod ? PlatformIcons.METHOD_ICON : o instanceof PsiParameter ? PlatformIcons.PARAMETER_ICON : null);
final String name;
if (o instanceof PsiMethod) {
- name = PsiFormatUtil.formatMethod((PsiMethod)o, PsiSubstitutor.EMPTY, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_PARAMETERS,
- PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE);
+ name = PsiFormatUtil.formatMethod((PsiMethod)o, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS,
+ PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_TYPE);
}
else if (o instanceof PsiParameter) {
- name = PsiFormatUtil.formatVariable((PsiParameter)o, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE, PsiSubstitutor.EMPTY);
+ name = PsiFormatUtil.formatVariable((PsiParameter)o, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_TYPE, PsiSubstitutor.EMPTY);
}
else name = null;
final boolean missing = o instanceof PsiElement && !((PsiElement)o).isPhysical();
@@ -362,7 +364,7 @@ public class MethodParameterPanel extends AbstractInjectionPanel<MethodParameter
return valueOf(o) != null;
}
- }, new TreeColumnInfo("Method/Parameters")
+ }, new TreeColumnInfo(" ")
};
}
@@ -386,7 +388,7 @@ public class MethodParameterPanel extends AbstractInjectionPanel<MethodParameter
}
}
- private class MyView extends TreeTableView implements TypeSafeDataProvider {
+ private static class MyView extends TreeTableView implements TypeSafeDataProvider {
public MyView(ListTreeTableModelOnColumns treeTableModel) {
super(treeTableModel);
}
diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/ui/configurables/MethodParameterInjectionConfigurable.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/ui/configurables/MethodParameterInjectionConfigurable.java
deleted file mode 100644
index 1b14fc204eca..000000000000
--- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/config/ui/configurables/MethodParameterInjectionConfigurable.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2006 Sascha Weinreuter
- *
- * 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 org.intellij.plugins.intelliLang.inject.config.ui.configurables;
-
-import com.intellij.openapi.project.Project;
-import org.intellij.plugins.intelliLang.inject.config.MethodParameterInjection;
-import org.intellij.plugins.intelliLang.inject.config.ui.MethodParameterPanel;
-
-public class MethodParameterInjectionConfigurable extends InjectionConfigurable<MethodParameterInjection, MethodParameterPanel> {
- public MethodParameterInjectionConfigurable(MethodParameterInjection injection, Runnable treeUpdater, Project project) {
- super(injection, treeUpdater, project);
- }
-
- protected MethodParameterPanel createOptionsPanelImpl() {
- return new MethodParameterPanel(myInjection, myProject);
- }
-
- public String getBannerSlogan() {
- return "Edit Method Parameter Injection";
- }
-}
diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java
index 99a3ccd21eab..14c7535f8044 100644
--- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java
+++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java
@@ -55,7 +55,6 @@ import org.intellij.plugins.intelliLang.inject.config.InjectionPlace;
import org.intellij.plugins.intelliLang.inject.config.MethodParameterInjection;
import org.intellij.plugins.intelliLang.inject.config.ui.AbstractInjectionPanel;
import org.intellij.plugins.intelliLang.inject.config.ui.MethodParameterPanel;
-import org.intellij.plugins.intelliLang.inject.config.ui.configurables.MethodParameterInjectionConfigurable;
import org.intellij.plugins.intelliLang.util.ContextComputationProcessor;
import org.intellij.plugins.intelliLang.util.PsiUtilEx;
import org.jdom.Element;
@@ -175,10 +174,7 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo
}
public BaseInjection createInjection(final Element element) {
- if (element.getName().equals(MethodParameterInjection.class.getSimpleName())) {
- return new MethodParameterInjection();
- }
- else return new BaseInjection(JAVA_SUPPORT_ID);
+ return new BaseInjection(JAVA_SUPPORT_ID);
}
private static boolean doInjectInJava(final Project project,
@@ -371,16 +367,21 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo
originalCopy.setPlaceEnabled(currentPlace.getText(), true);
methodParameterInjection = createFrom(project, originalCopy, contextMethod, false);
}
- if (InjectLanguageAction.doEditConfigurable(project, new MethodParameterInjectionConfigurable(methodParameterInjection, null, project))) {
- final BaseInjection newInjection = new BaseInjection(methodParameterInjection.getSupportId()).copyFrom(methodParameterInjection);
- if (originalInjection != null) {
- newInjection.mergeOriginalPlacesFrom(originalInjection, true);
- }
- configuration.replaceInjectionsWithUndo(
- project, Collections.singletonList(newInjection),
- ContainerUtil.createMaybeSingletonList(originalInjection),
- Collections.<PsiElement>emptyList());
+ mergePlacesAndAddToConfiguration(project, configuration, methodParameterInjection, originalInjection);
+ }
+
+ private static void mergePlacesAndAddToConfiguration(@NotNull Project project,
+ @NotNull Configuration configuration,
+ @NotNull MethodParameterInjection injection,
+ @Nullable BaseInjection originalInjection) {
+ BaseInjection newInjection = new BaseInjection(injection.getSupportId()).copyFrom(injection);
+ if (originalInjection != null) {
+ newInjection.mergeOriginalPlacesFrom(originalInjection, true);
}
+ configuration.replaceInjectionsWithUndo(
+ project, Collections.singletonList(newInjection),
+ ContainerUtil.createMaybeSingletonList(originalInjection),
+ Collections.<PsiElement>emptyList());
}
private static void collectInjections(PsiLiteralExpression host,
diff --git a/plugins/IntelliLang/src/META-INF/plugin.xml b/plugins/IntelliLang/src/META-INF/plugin.xml
index 8dad5cb4e41a..975422e0fdfc 100644
--- a/plugins/IntelliLang/src/META-INF/plugin.xml
+++ b/plugins/IntelliLang/src/META-INF/plugin.xml
@@ -36,7 +36,7 @@
<highlightErrorFilter implementation="org.intellij.plugins.intelliLang.inject.FrankensteinErrorFilter"/>
<daemon.highlightInfoFilter implementation="org.intellij.plugins.intelliLang.inject.FrankensteinErrorFilter"/>
- <projectConfigurable instance="org.intellij.plugins.intelliLang.InjectionsSettingsUI" nonDefaultProject="true"/>
+ <projectConfigurable displayName="Language Injections" instance="org.intellij.plugins.intelliLang.InjectionsSettingsUI" nonDefaultProject="true"/>
<multiHostInjector implementation="org.intellij.plugins.intelliLang.inject.CommentLanguageInjector"/>
<multiHostInjector implementation="org.intellij.plugins.intelliLang.inject.TemporaryPlacesInjector"/>
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java
index 414500ba2096..a0420939dfdc 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java
@@ -30,6 +30,7 @@ import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.SplitterProportionsData;
@@ -47,7 +48,6 @@ import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ListTableModel;
-import gnu.trove.THashMap;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
import org.intellij.plugins.intelliLang.inject.AbstractLanguageInjectionSupport;
@@ -81,19 +81,14 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, Conf
private final JPanel myRoot;
private final InjectionsTable myInjectionsTable;
- private final Map<String, LanguageInjectionSupport> mySupports = new THashMap<String, LanguageInjectionSupport>();
- private final Map<String, AnAction> myEditActions = new THashMap<String, AnAction>();
- private final List<AnAction> myAddActions = new ArrayList<AnAction>();
- private final ActionToolbar myToolbar;
+ private final Map<String, LanguageInjectionSupport> mySupports = ContainerUtil.newLinkedHashMap();
+ private final Map<String, AnAction> myEditActions = ContainerUtil.newLinkedHashMap();
+ private final List<AnAction> myAddActions = ContainerUtil.newArrayList();
private final JLabel myCountLabel;
private Configurable[] myConfigurables;
private Configuration myConfiguration;
- public InjectionsSettingsUI(final Project project) {
- this(project, Configuration.getProjectInstance(project));
- }
-
public InjectionsSettingsUI(final Project project, final Configuration configuration) {
myProject = project;
myConfiguration = configuration;
@@ -107,16 +102,12 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, Conf
myInjectionsTable = new InjectionsTable(getInjInfoList(myInfos));
myInjectionsTable.getEmptyText().setText("No injections configured");
- final JPanel tablePanel = new JPanel(new BorderLayout());
-
- tablePanel.add(ScrollPaneFactory.createScrollPane(myInjectionsTable), BorderLayout.CENTER);
- final DefaultActionGroup group = createActions();
+ ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myInjectionsTable);
+ createActions(decorator);
- myToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true);
- myToolbar.setTargetComponent(myInjectionsTable);
- myRoot.add(myToolbar.getComponent(), BorderLayout.NORTH);
- myRoot.add(tablePanel, BorderLayout.CENTER);
+ //myRoot.add(new TitledSeparator("Languages injection places"), BorderLayout.NORTH);
+ myRoot.add(decorator.createPanel(), BorderLayout.CENTER);
myCountLabel = new JLabel();
myCountLabel.setHorizontalAlignment(SwingConstants.RIGHT);
myCountLabel.setForeground(SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES.getFgColor());
@@ -124,7 +115,7 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, Conf
updateCountLabel();
}
- private DefaultActionGroup createActions() {
+ private void createActions(ToolbarDecorator decorator) {
final Consumer<BaseInjection> consumer = new Consumer<BaseInjection>() {
public void consume(final BaseInjection injection) {
addInjection(injection);
@@ -148,22 +139,22 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, Conf
return Comparing.compare(o1.getTemplatePresentation().getText(), o2.getTemplatePresentation().getText());
}
});
-
- final DefaultActionGroup group = new DefaultActionGroup();
- final AnAction addAction = new AnAction("Add", "Add", IconUtil.getAddIcon()) {
+ decorator.disableUpDownActions();
+ decorator.setAddActionUpdater(new AnActionButtonUpdater() {
@Override
- public void update(final AnActionEvent e) {
- e.getPresentation().setEnabled(!myAddActions.isEmpty());
+ public boolean isEnabled(AnActionEvent e) {
+ return !myAddActions.isEmpty();
}
-
+ });
+ decorator.setAddAction(new AnActionButtonRunnable() {
@Override
- public void actionPerformed(final AnActionEvent e) {
- performAdd(e);
+ public void run(AnActionButton button) {
+ performAdd(button);
}
- };
- final AnAction removeAction = new AnAction("Remove", "Remove", PlatformIcons.DELETE_ICON) {
+ });
+ decorator.setRemoveActionUpdater(new AnActionButtonUpdater() {
@Override
- public void update(final AnActionEvent e) {
+ public boolean isEnabled(AnActionEvent e) {
boolean enabled = false;
for (InjInfo info : getSelectedInjections()) {
if (!info.bundled) {
@@ -171,69 +162,63 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, Conf
break;
}
}
- e.getPresentation().setEnabled(enabled);
+ return enabled;
}
-
+ });
+ decorator.setRemoveAction(new AnActionButtonRunnable() {
@Override
- public void actionPerformed(final AnActionEvent e) {
+ public void run(AnActionButton button) {
performRemove();
}
- };
+ });
- final AnAction editAction = new AnAction("Edit", "Edit", PlatformIcons.PROPERTIES_ICON) {
+ decorator.setEditActionUpdater(new AnActionButtonUpdater() {
@Override
- public void update(final AnActionEvent e) {
- final AnAction action = getEditAction();
- e.getPresentation().setEnabled(action != null);
- if (action != null) action.update(e);
+ public boolean isEnabled(AnActionEvent e) {
+ AnAction edit = getEditAction();
+ if (edit != null) edit.update(e);
+ return edit != null && edit.getTemplatePresentation().isEnabled();
}
-
+ });
+ decorator.setEditAction(new AnActionButtonRunnable() {
@Override
- public void actionPerformed(final AnActionEvent e) {
- performEditAction(e);
+ public void run(AnActionButton button) {
+ performEditAction();
}
- };
- final AnAction copyAction = new AnAction("Duplicate", "Duplicate", PlatformIcons.COPY_ICON) {
+ });
+ decorator.addExtraAction(new DumbAwareActionButton("Duplicate", "Duplicate", PlatformIcons.COPY_ICON) {
+
@Override
- public void update(final AnActionEvent e) {
- final AnAction action = getEditAction();
- e.getPresentation().setEnabled(action != null);
- if (action != null) action.update(e);
+ public boolean isEnabled() {
+ return getEditAction() != null;
}
@Override
- public void actionPerformed(final AnActionEvent e) {
+ public void actionPerformed(AnActionEvent e) {
final InjInfo injection = getSelectedInjection();
if (injection != null) {
addInjection(injection.injection.copy());
//performEditAction(e);
}
}
- };
- group.add(addAction);
- group.add(removeAction);
- group.add(copyAction);
- group.add(editAction);
+ });
- addAction.registerCustomShortcutSet(CommonShortcuts.INSERT, myInjectionsTable);
- removeAction.registerCustomShortcutSet(CommonShortcuts.DELETE, myInjectionsTable);
- editAction.registerCustomShortcutSet(CommonShortcuts.ENTER, myInjectionsTable);
+ decorator.addExtraAction(new DumbAwareActionButton("Enable Selected Injections", "Enable Selected Injections", PlatformIcons.SELECT_ALL_ICON) {
- group.addSeparator();
- group.add(new AnAction("Enable Selected Injections", "Enable Selected Injections", PlatformIcons.SELECT_ALL_ICON) {
@Override
public void actionPerformed(final AnActionEvent e) {
performSelectedInjectionsEnabled(true);
}
});
- group.add(new AnAction("Disable Selected Injections", "Disable Selected Injections", PlatformIcons.UNSELECT_ALL_ICON) {
- @Override
- public void actionPerformed(final AnActionEvent e) {
- performSelectedInjectionsEnabled(false);
- }
- });
+ decorator.addExtraAction(new DumbAwareActionButton("Disable Selected Injections", "Disable Selected Injections", PlatformIcons.UNSELECT_ALL_ICON) {
- new AnAction("Toggle") {
+ @Override
+ public void actionPerformed(final AnActionEvent e) {
+ performSelectedInjectionsEnabled(false);
+ }
+ });
+
+ new DumbAwareAction("Toggle") {
@Override
public void update(AnActionEvent e) {
SpeedSearchSupply supply = SpeedSearchSupply.getSupply(myInjectionsTable);
@@ -247,8 +232,18 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, Conf
}.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0)), myInjectionsTable);
if (myInfos.length > 1) {
- group.addSeparator();
- final AnAction shareAction = new AnAction("Make Global", null, PlatformIcons.IMPORT_ICON) {
+ AnActionButton shareAction = new DumbAwareActionButton("Make Global", null, PlatformIcons.IMPORT_ICON) {
+ {
+ addCustomUpdater(new AnActionButtonUpdater() {
+ @Override
+ public boolean isEnabled(AnActionEvent e) {
+ CfgInfo cfg = getTargetCfgInfo(getSelectedInjections());
+ e.getPresentation().setText(cfg == getDefaultCfgInfo() ? "Make Global" : "Move to Project");
+ return cfg != null;
+ }
+ });
+ }
+
@Override
public void actionPerformed(final AnActionEvent e) {
final List<InjInfo> injections = getSelectedInjections();
@@ -265,14 +260,6 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, Conf
TableUtil.selectRows(myInjectionsTable, selectedRows);
}
- @Override
- public void update(final AnActionEvent e) {
- final CfgInfo cfg = getTargetCfgInfo(getSelectedInjections());
- e.getPresentation().setEnabled(cfg != null);
- e.getPresentation().setText(cfg == getDefaultCfgInfo() ? "Make Global" : "Move to Project");
- super.update(e);
- }
-
@Nullable
private CfgInfo getTargetCfgInfo(final List<InjInfo> injections) {
CfgInfo cfg = null;
@@ -283,25 +270,26 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, Conf
if (cfg == null) cfg = info.cfgInfo;
else if (cfg != info.cfgInfo) return info.cfgInfo;
}
- if (cfg == null) return cfg;
+ if (cfg == null) return null;
for (CfgInfo info : myInfos) {
if (info != cfg) return info;
}
throw new AssertionError();
}
};
- shareAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.SHIFT_DOWN_MASK)), myInjectionsTable);
- group.add(shareAction);
+ shareAction.setShortcut(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.SHIFT_DOWN_MASK)));
+ decorator.addExtraAction(shareAction);
}
- group.addSeparator();
- group.add(new AnAction("Import", "Import", AllIcons.Actions.Install) {
+ decorator.addExtraAction(new DumbAwareActionButton("Import", "Import", AllIcons.Actions.Install) {
+
@Override
public void actionPerformed(final AnActionEvent e) {
doImportAction(e.getDataContext());
updateCountLabel();
}
});
- group.add(new AnAction("Export", "Export", AllIcons.Actions.Export) {
+ decorator.addExtraAction(new DumbAwareActionButton("Export", "Export", AllIcons.Actions.Export) {
+
@Override
public void actionPerformed(final AnActionEvent e) {
final List<BaseInjection> injections = getInjectionList(getSelectedInjections());
@@ -321,20 +309,19 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, Conf
}
@Override
- public void update(final AnActionEvent e) {
- e.getPresentation().setEnabled(!getSelectedInjections().isEmpty());
+ public boolean isEnabled() {
+ return !getSelectedInjections().isEmpty();
}
});
-
- return group;
}
- private void performEditAction(AnActionEvent e) {
+ private void performEditAction() {
final AnAction action = getEditAction();
if (action != null) {
final int row = myInjectionsTable.getSelectedRow();
- action.actionPerformed(e);
+ action.actionPerformed(new AnActionEvent(null, DataManager.getInstance().getDataContext(myInjectionsTable),
+ ActionPlaces.UNKNOWN, new Presentation(""), ActionManager.getInstance(), 0));
myInjectionsTable.getListTableModel().fireTableDataChanged();
myInjectionsTable.getSelectionModel().setSelectionInterval(row, row);
updateCountLabel();
@@ -352,10 +339,8 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, Conf
if (place.isEnabled()) enablePlacesCount++;
}
}
- final StringBuilder sb = new StringBuilder();
- sb.append(items.size()).append(" injection").append(items.size() > 1 ? "s" : "").append(" (").append(enablePlacesCount)
- .append(" of ").append(placesCount).append(" place").append(placesCount > 1 ? "s" : "").append(" enabled) ");
- myCountLabel.setText(sb.toString());
+ myCountLabel.setText(items.size() + " injection" + (items.size() > 1 ? "s" : "") + " (" + enablePlacesCount + " of " +
+ placesCount + " place" + (placesCount > 1 ? "s" : "") + " enabled) ");
}
else {
myCountLabel.setText("no injections configured ");
@@ -511,17 +496,14 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, Conf
return row < 0? null : myInjectionsTable.getItems().get(myInjectionsTable.convertRowIndexToModel(row));
}
- private void performAdd(final AnActionEvent e) {
- final DefaultActionGroup group = new DefaultActionGroup();
- for (AnAction action : myAddActions) {
- group.add(action);
- }
+ private void performAdd(AnActionButton e) {
+ DefaultActionGroup group = new DefaultActionGroup(myAddActions);
JBPopupFactory.getInstance().createActionGroupPopup(null, group, e.getDataContext(), JBPopupFactory.ActionSelectionAid.NUMBERING, true, new Runnable() {
public void run() {
updateCountLabel();
}
- }, -1).showUnderneathOf(myToolbar.getComponent());
+ }, -1).show(e.getPreferredPopupPoint());
}
@Nls
@@ -552,8 +534,7 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, Conf
if (row < 0) return false;
if (columnAtPoint(e.getPoint()) <= 0) return false;
myInjectionsTable.getSelectionModel().setSelectionInterval(row, row);
- performEditAction(new AnActionEvent(e, DataManager.getInstance().getDataContext(InjectionsTable.this),
- ActionPlaces.UNKNOWN, new Presentation(""), ActionManager.getInstance(), 0));
+ performEditAction();
return true;
}
}.installOn(this);
@@ -632,7 +613,7 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, Conf
public TableCellRenderer getRenderer(final InjInfo injection) {
return booleanCellRenderer;
}
- }, new ColumnInfo<InjInfo, InjInfo>("Display Name") {
+ }, new ColumnInfo<InjInfo, InjInfo>("Name") {
@Override
public InjInfo valueOf(final InjInfo info) {
return info;
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java
index a18a26b529af..132393737525 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java
@@ -114,12 +114,13 @@ public abstract class AbstractLanguageInjectionSupport extends LanguageInjection
public static AnAction createDefaultAddAction(final Project project,
final Consumer<BaseInjection> consumer,
final AbstractLanguageInjectionSupport support) {
+ final String supportTitle = StringUtil.capitalize(support.getId());
Icon icon = FileTypeManager.getInstance().getFileTypeByExtension(support.getId()).getIcon();
- return new AnAction("Generic "+ StringUtil.capitalize(support.getId()), null, icon) {
+ return new AnAction("Generic "+ supportTitle, null, icon) {
@Override
public void actionPerformed(AnActionEvent e) {
final BaseInjection injection = new BaseInjection(support.getId());
- injection.setDisplayName("New "+ StringUtil.capitalize(support.getId())+" Injection");
+ injection.setDisplayName("New "+ supportTitle +" Injection");
final BaseInjection newInjection = showDefaultInjectionUI(project, injection);
if (newInjection != null) {
consumer.consume(injection);
@@ -134,7 +135,7 @@ public abstract class AbstractLanguageInjectionSupport extends LanguageInjection
panel.reset();
final DialogBuilder builder = new DialogBuilder(project);
LanguageInjectionSupport support = InjectorUtils.findInjectionSupport(injection.getSupportId());
- if (support != null && support instanceof AbstractLanguageInjectionSupport) {
+ if (support instanceof AbstractLanguageInjectionSupport) {
builder.setHelpId(((AbstractLanguageInjectionSupport)support).getHelpId());
}
builder.addOkAction();
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java
index 18f4c0147b12..b03a07de7233 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java
@@ -28,7 +28,6 @@ import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.keymap.KeymapUtil;
-import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
@@ -221,7 +220,4 @@ public class InjectLanguageAction implements IntentionAction {
return false;
}
- public static boolean doEditConfigurable(final Project project, final Configurable configurable) {
- return true; //ShowSettingsUtil.getInstance().editConfigurable(project, configurable);
- }
}
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java
index ffd54be5bd67..f5fddc277c04 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java
@@ -56,7 +56,8 @@ public class BaseInjection implements Injection, PersistentStateComponent<Elemen
public static final Key<BaseInjection> INJECTION_KEY = Key.create("INJECTION_KEY");
@NotNull private final String mySupportId;
- private String myDisplayName;
+
+ private String myDisplayName = "";
private String myInjectedLanguageId = "";
private String myPrefix = "";
@@ -98,7 +99,7 @@ public class BaseInjection implements Injection, PersistentStateComponent<Elemen
return myDisplayName;
}
- public void setDisplayName(String displayName) {
+ public void setDisplayName(@NotNull String displayName) {
myDisplayName = displayName;
}
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/AbstractInjectionPanel.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/AbstractInjectionPanel.java
index 2626d4f433ed..9b6fc83533fa 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/AbstractInjectionPanel.java
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/AbstractInjectionPanel.java
@@ -15,8 +15,6 @@
*/
package org.intellij.plugins.intelliLang.inject.config.ui;
-import com.intellij.openapi.editor.event.DocumentAdapter;
-import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.project.Project;
import com.intellij.util.ui.UIUtil;
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
@@ -73,7 +71,6 @@ public abstract class AbstractInjectionPanel<T extends BaseInjection> implements
final InjectionPanel p = getField(panel);
p.init(copy);
}
- reset();
}
public final boolean isModified() {
@@ -89,23 +86,28 @@ public abstract class AbstractInjectionPanel<T extends BaseInjection> implements
@SuppressWarnings({"unchecked"})
public final void apply() {
- apply(myOrigInjection);
-
for (Field panel : myOtherPanels) {
getField(panel).apply();
}
- myOrigInjection.generatePlaces();
- myEditCopy.copyFrom(myOrigInjection);
+
+ // auto-generated name should go last
+ apply(myOrigInjection);
+ if (!myOtherPanels.isEmpty()) {
+ myOrigInjection.generatePlaces();
+ myEditCopy.copyFrom(myOrigInjection);
+ }
}
protected abstract void apply(T other);
@SuppressWarnings({"unchecked"})
public final void reset() {
+ if (!myOtherPanels.isEmpty()) {
+ myEditCopy.copyFrom(myOrigInjection);
+ }
for (Field panel : myOtherPanels) {
getField(panel).reset();
}
- myEditCopy.copyFrom(myOrigInjection);
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
public void run() {
resetImpl();
@@ -138,10 +140,4 @@ public abstract class AbstractInjectionPanel<T extends BaseInjection> implements
updater.run();
}
}
-
- protected class TreeUpdateListener extends DocumentAdapter {
- public void documentChanged(DocumentEvent e) {
- updateTree();
- }
- }
}
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/AdvancedPanel.form b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/AdvancedPanel.form
index a45bfaff44cc..0ac5d480dd01 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/AdvancedPanel.form
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/AdvancedPanel.form
@@ -26,7 +26,7 @@
</constraints>
<properties>
<labelFor value="7bf4e"/>
- <text value="&amp;Value Pattern:"/>
+ <text value="&amp;Value pattern:"/>
<toolTipText value="&lt;html&gt;Enter a regular expression that selects the parts of the tag's or attribute's value the language should be injected into.&lt;br&gt;The pattern should contain exactly one capturing group.&lt;/html&gt;"/>
</properties>
</component>
@@ -43,7 +43,7 @@
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
- <text value="&amp;Single File"/>
+ <text value="&amp;Single file"/>
</properties>
</component>
</children>
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/BaseInjectionPanel.form b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/BaseInjectionPanel.form
index 0c9523fbb1ea..79dafacd8fa8 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/BaseInjectionPanel.form
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/BaseInjectionPanel.form
@@ -21,7 +21,7 @@
<clientProperties>
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithoutIndent"/>
</clientProperties>
- <border type="none" title="Places Pattern"/>
+ <border type="none" title="Places Patterns"/>
<children/>
</grid>
<nested-form id="b6e0b" form-file="org/intellij/plugins/intelliLang/inject/config/ui/AdvancedPanel.form" binding="myAdvancedPanel" custom-create="true">
@@ -43,7 +43,7 @@
</constraints>
<properties>
<labelFor value="5916a"/>
- <text value="Display &amp;Name:"/>
+ <text value="&amp;Name:"/>
</properties>
</component>
<component id="5916a" class="javax.swing.JTextField" binding="myNameTextField">
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/LanguagePanel.form b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/LanguagePanel.form
index 1f582bb85f03..e8e087e03189 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/LanguagePanel.form
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/LanguagePanel.form
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.intellij.plugins.intelliLang.inject.config.ui.LanguagePanel">
- <grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="493" height="143"/>
@@ -44,20 +44,15 @@
</constraints>
<properties/>
</component>
- <hspacer id="7c4e8">
- <constraints>
- <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- </hspacer>
<component id="96508" class="com.intellij.ui.EditorTextField" binding="myPrefix">
<constraints>
- <grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="dcdf7" class="com.intellij.ui.EditorTextField" binding="mySuffix">
<constraints>
- <grid row="2" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/configurables/InjectionConfigurable.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/configurables/InjectionConfigurable.java
deleted file mode 100644
index b09de2e4c915..000000000000
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/configurables/InjectionConfigurable.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2006 Sascha Weinreuter
- *
- * 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 org.intellij.plugins.intelliLang.inject.config.ui.configurables;
-
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.NamedConfigurable;
-import org.intellij.plugins.intelliLang.inject.config.Injection;
-import org.intellij.plugins.intelliLang.inject.config.ui.InjectionPanel;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-
-public abstract class InjectionConfigurable<T extends Injection, P extends InjectionPanel<T>> extends NamedConfigurable<T> {
- private final Runnable myTreeUpdater;
- protected final T myInjection;
- protected final Project myProject;
- private P myPanel;
-
- public InjectionConfigurable(T injection, Runnable treeUpdater, Project project) {
- myProject = project;
- myInjection = injection;
- myTreeUpdater = treeUpdater;
- }
-
- public void setDisplayName(String name) {
- }
-
- public T getEditableObject() {
- return myInjection;
- }
-
- @Nullable
- @NonNls
- public String getHelpTopic() {
- return null;
- }
-
- public JComponent createOptionsPanel() {
- myPanel = createOptionsPanelImpl();
- myPanel.addUpdater(myTreeUpdater);
- return myPanel.getComponent();
- }
-
- protected abstract P createOptionsPanelImpl();
-
- public P getPanel() {
- return myPanel;
- }
-
- public boolean isModified() {
- return myPanel.isModified();
- }
-
- public void apply() throws ConfigurationException {
- myPanel.apply();
- }
-
- public void reset() {
- myPanel.reset();
- }
-
- public void disposeUIResources() {
- myPanel = null;
- }
-
- public String getDisplayName() {
- final P p = getPanel();
- return p != null ? p.getInjection().getDisplayName() : myInjection.getDisplayName();
- }
-}
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/AbstractTagInjection.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/AbstractTagInjection.java
index 0662837d0574..491b277b9393 100644
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/AbstractTagInjection.java
+++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/AbstractTagInjection.java
@@ -16,7 +16,6 @@
package org.intellij.plugins.intelliLang.inject.config;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.JDOMExternalizer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.xml.XmlAttribute;
@@ -44,7 +43,7 @@ import java.util.TreeSet;
*
* @see org.intellij.plugins.intelliLang.inject.config.XPathSupportProxy
*/
-public class AbstractTagInjection extends BaseInjection {
+public abstract class AbstractTagInjection extends BaseInjection {
private static final Logger LOG = Logger.getInstance("org.intellij.plugins.intelliLang.inject.config.AbstractTagInjection");
@@ -57,7 +56,7 @@ public class AbstractTagInjection extends BaseInjection {
private String myXPathCondition = "";
private XPath myCompiledXPathCondition;
- private boolean myApplyToSubTagTexts;
+ private boolean myApplyToSubTags;
public AbstractTagInjection() {
super(XmlLanguageInjectionSupport.XML_SUPPORT_ID);
@@ -134,9 +133,7 @@ public class AbstractTagInjection extends BaseInjection {
}
@Override
- public AbstractTagInjection copy() {
- return new AbstractTagInjection().copyFrom(this);
- }
+ public abstract AbstractTagInjection copy();
public AbstractTagInjection copyFrom(@NotNull BaseInjection o) {
super.copyFrom(o);
@@ -146,30 +143,21 @@ public class AbstractTagInjection extends BaseInjection {
myTagNamespace = other.myTagNamespace;
setXPathCondition(other.getXPathCondition());
- setApplyToSubTagTexts(other.isApplyToSubTagTexts());
+ setApplyToSubTags(other.isApplyToSubTags());
}
return this;
}
protected void readExternalImpl(Element e) {
- if (e.getAttribute("injector-id") == null) {
- setTagName(JDOMExternalizer.readString(e, "TAGNAME"));
- setTagNamespace(JDOMExternalizer.readString(e, "TAGNAMESPACE"));
- setXPathCondition(JDOMExternalizer.readString(e, "XPATH_CONDITION"));
-
- myApplyToSubTagTexts = JDOMExternalizer.readBoolean(e, "APPLY_TO_SUBTAGS");
- }
- else {
- setXPathCondition(e.getChildText("xpath-condition"));
- myApplyToSubTagTexts = e.getChild("apply-to-subtags") != null;
- }
+ setXPathCondition(e.getChildText("xpath-condition"));
+ myApplyToSubTags = e.getChild("apply-to-subtags") != null;
}
protected void writeExternalImpl(Element e) {
if (StringUtil.isNotEmpty(myXPathCondition)) {
e.addContent(new Element("xpath-condition").setText(myXPathCondition));
}
- if (myApplyToSubTagTexts) {
+ if (myApplyToSubTags) {
e.addContent(new Element("apply-to-subtags"));
}
}
@@ -186,7 +174,7 @@ public class AbstractTagInjection extends BaseInjection {
if (!myTagNamespace.equals(that.myTagNamespace)) return false;
if (!myXPathCondition.equals(that.myXPathCondition)) return false;
- if (myApplyToSubTagTexts != that.myApplyToSubTagTexts) return false;
+ if (myApplyToSubTags != that.myApplyToSubTags) return false;
return true;
}
@@ -196,7 +184,7 @@ public class AbstractTagInjection extends BaseInjection {
result = 31 * result + myTagNamespace.hashCode();
result = 31 * result + myXPathCondition.hashCode();
- result = 31 * result + (myApplyToSubTagTexts ? 1 : 0);
+ result = 31 * result + (myApplyToSubTags ? 1 : 0);
return result;
}
@@ -215,12 +203,12 @@ public class AbstractTagInjection extends BaseInjection {
return myXPathCondition.length() == 0;
}
- public boolean isApplyToSubTagTexts() {
- return myApplyToSubTagTexts;
+ public boolean isApplyToSubTags() {
+ return myApplyToSubTags;
}
- public void setApplyToSubTagTexts(final boolean applyToSubTagTexts) {
- myApplyToSubTagTexts = applyToSubTagTexts;
+ public void setApplyToSubTags(final boolean applyToSubTagTexts) {
+ myApplyToSubTags = applyToSubTagTexts;
}
@Override
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/XmlAttributeInjection.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/XmlAttributeInjection.java
index 5ffe3271bb07..32a2239dd3a1 100644
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/XmlAttributeInjection.java
+++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/XmlAttributeInjection.java
@@ -15,7 +15,6 @@
*/
package org.intellij.plugins.intelliLang.inject.config;
-import com.intellij.openapi.util.JDOMExternalizer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.xml.XmlAttribute;
@@ -57,8 +56,7 @@ public class XmlAttributeInjection extends AbstractTagInjection {
return element instanceof XmlAttribute && matches((XmlAttribute)element);
}
- @NotNull
- public String getDisplayName() {
+ public String getGeneratedName() {
final String tag = getTagName();
final String attributeName = getAttributeName();
if (!attributeName.equals(StringMatcher.NONE.getPattern())) {
@@ -74,6 +72,7 @@ public class XmlAttributeInjection extends AbstractTagInjection {
@Override
public void generatePlaces() {
+ if (StringUtil.isEmpty(getDisplayName())) setDisplayName(getGeneratedName());
setInjectionPlaces(new InjectionPlace(getCompiler().createElementPattern(getPatternString(this), getDisplayName()), true));
}
@@ -95,25 +94,14 @@ public class XmlAttributeInjection extends AbstractTagInjection {
public XmlAttributeInjection copyFrom(@NotNull BaseInjection o) {
super.copyFrom(o);
if (o instanceof XmlAttributeInjection) {
- final XmlAttributeInjection other = (XmlAttributeInjection)o;
+ XmlAttributeInjection other = (XmlAttributeInjection)o;
+ setApplyToSubTags(other.isApplyToSubTags());
setAttributeName(other.getAttributeName());
setAttributeNamespace(other.getAttributeNamespace());
}
return this;
}
- protected void readExternalImpl(Element e) {
- super.readExternalImpl(e);
- if (e.getAttribute("injector-id") == null) {
- setAttributeName(JDOMExternalizer.readString(e, "ATT_NAME"));
- setAttributeNamespace(JDOMExternalizer.readString(e, "ATT_NAMESPACE"));
- }
- }
-
- protected void writeExternalImpl(Element e) {
- super.writeExternalImpl(e);
- }
-
@SuppressWarnings({"RedundantIfStatement"})
public boolean equals(Object o) {
if (this == o) return true;
@@ -142,7 +130,8 @@ public class XmlAttributeInjection extends AbstractTagInjection {
if (StringUtil.isNotEmpty(name)) appendStringPattern(result, ".withLocalName(", name, ")");
if (StringUtil.isNotEmpty(namespace)) appendStringPattern(result, ".withNamespace(", namespace, ")");
if (StringUtil.isNotEmpty(injection.getTagName()) || StringUtil.isNotEmpty(injection.getTagNamespace())) {
- result.append(".withParent(").append(XmlTagInjection.getPatternString(injection)).append(")");
+ result.append(".").append(injection.isApplyToSubTags() ? "inside" : "withParent").append("(")
+ .append(XmlTagInjection.getPatternString(injection)).append(")");
}
return result.toString();
}
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/XmlTagInjection.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/XmlTagInjection.java
index ade0c399c84d..19d3a8c64f3b 100644
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/XmlTagInjection.java
+++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/XmlTagInjection.java
@@ -31,8 +31,7 @@ public class XmlTagInjection extends AbstractTagInjection {
return matches(context) && matchXPath(context);
}
- @NotNull
- public String getDisplayName() {
+ public String getGeneratedName() {
final String name = getTagName();
return name.length() > 0 ? name : "*";
}
@@ -49,6 +48,7 @@ public class XmlTagInjection extends AbstractTagInjection {
@Override
public void generatePlaces() {
+ if (StringUtil.isEmpty(getDisplayName())) setDisplayName(getGeneratedName());
setInjectionPlaces(new InjectionPlace(getCompiler().createElementPattern(getPatternString(this), getDisplayName()), true));
}
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/AdvancedXmlPanel.form b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/AdvancedXmlPanel.form
index c4cd838349cd..48df40018f5a 100644
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/AdvancedXmlPanel.form
+++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/AdvancedXmlPanel.form
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.intellij.plugins.intelliLang.inject.config.ui.AdvancedXmlPanel">
- <grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <xy x="20" y="20" width="531" height="97"/>
+ <xy x="20" y="20" width="531" height="123"/>
</constraints>
<properties/>
<border type="none"/>
@@ -25,7 +25,7 @@
</constraints>
<properties>
<labelFor value="7bf4e"/>
- <text value="&amp;Value Pattern:"/>
+ <text value="&amp;Value pattern:"/>
<toolTipText value="&lt;html&gt;Enter a regular expression that selects the parts of the tag's or attribute's value the language should be injected into.&lt;br&gt;The pattern should contain exactly one capturing group.&lt;/html&gt;"/>
</properties>
</component>
@@ -43,7 +43,7 @@
</constraints>
<properties>
<labelFor value="a6f2"/>
- <text value="&amp;XPath Condition:"/>
+ <text value="&amp;XPath condition:"/>
<toolTipText value="&lt;html&gt;Enter an XPath expression that the tag/attribute must match additionally to the name-condition specified above.&lt;br&gt;This requires the XPathView plugin to be installed&lt;/html&gt;"/>
</properties>
</component>
@@ -60,11 +60,16 @@
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
- <text value="&amp;Single File"/>
+ <text value="Single &amp;file"/>
</properties>
</component>
</children>
</grid>
+ <vspacer id="5c79c">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
</children>
</grid>
</form>
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/TagPanel.form b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/TagPanel.form
index bcbe680d8e0d..70051cbf3730 100644
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/TagPanel.form
+++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/TagPanel.form
@@ -8,7 +8,7 @@
<properties/>
<border type="none"/>
<children>
- <grid id="7e115" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="49b27" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -19,25 +19,25 @@
</clientProperties>
<border type="none" title="XML Tag"/>
<children>
- <component id="edc9a" class="javax.swing.JLabel">
+ <component id="9c78e" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
- <labelFor value="16487"/>
- <text value="&amp;Local Name:"/>
+ <labelFor value="8f17"/>
+ <text value="&amp;Local name:"/>
</properties>
</component>
- <component id="1068d" class="javax.swing.JLabel">
+ <component id="7d32d" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
- <labelFor value="eeee3"/>
+ <labelFor value="3d65f"/>
<text value="&amp;Namespace:"/>
</properties>
</component>
- <component id="16487" class="com.intellij.ui.EditorTextField" binding="myLocalName" custom-create="true">
+ <component id="8f17" class="com.intellij.ui.EditorTextField" binding="myLocalName" custom-create="true">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
@@ -45,24 +45,29 @@
</constraints>
<properties/>
</component>
- <component id="eeee3" class="com.intellij.openapi.ui.ComboBox" binding="myNamespace" custom-create="true">
+ <component id="3d65f" class="com.intellij.openapi.ui.ComboBox" binding="myNamespace" custom-create="true">
<constraints>
- <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+ <grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="7" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<editable value="true"/>
</properties>
</component>
+ <component id="3ed2c" class="javax.swing.JCheckBox" binding="myWithSubtags">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Sub-&amp;tags"/>
+ </properties>
+ </component>
</children>
</grid>
- <component id="bc807" class="javax.swing.JCheckBox" binding="myApplyRecursivelyCheckBox">
+ <vspacer id="bdf19">
<constraints>
- <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
- <properties>
- <text value="Apply to all text fragments &amp;recursively"/>
- </properties>
- </component>
+ </vspacer>
</children>
</grid>
</form>
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/TagPanel.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/TagPanel.java
index 42db562728ff..2b224a1be58d 100644
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/TagPanel.java
+++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/TagPanel.java
@@ -28,7 +28,6 @@ import com.intellij.ui.LanguageTextField;
import org.intellij.lang.regexp.RegExpLanguage;
import org.intellij.plugins.intelliLang.inject.config.AbstractTagInjection;
import org.intellij.plugins.intelliLang.inject.config.JspSupportProxy;
-import org.intellij.plugins.intelliLang.inject.config.XmlTagInjection;
import javax.swing.*;
import java.util.ArrayList;
@@ -43,14 +42,13 @@ public class TagPanel extends AbstractInjectionPanel<AbstractTagInjection> {
private EditorTextField myLocalName;
private ComboBox myNamespace;
- private JCheckBox myApplyRecursivelyCheckBox;
+ private JCheckBox myWithSubtags;
public TagPanel(Project project, AbstractTagInjection injection) {
super(injection, project);
$$$setupUI$$$();
myNamespace.setModel(createNamespaceUriModel(myProject));
- myLocalName.getDocument().addDocumentListener(new TreeUpdateListener());
}
public static ComboBoxModel createNamespaceUriModel(Project project) {
@@ -95,19 +93,13 @@ public class TagPanel extends AbstractInjectionPanel<AbstractTagInjection> {
protected void resetImpl() {
myLocalName.setText(myOrigInjection.getTagName());
myNamespace.getEditor().setItem(myOrigInjection.getTagNamespace());
- final boolean isXmlTag = myOrigInjection instanceof XmlTagInjection;
- myApplyRecursivelyCheckBox.setVisible(isXmlTag);
- if (isXmlTag) {
- myApplyRecursivelyCheckBox.setSelected(((XmlTagInjection)myOrigInjection).isApplyToSubTagTexts());
- }
+ myWithSubtags.setSelected(myOrigInjection.isApplyToSubTags());
}
- protected void apply(AbstractTagInjection i) {
- i.setTagName(myLocalName.getText());
- i.setTagNamespace(getNamespace());
- if (i instanceof XmlTagInjection) {
- ((XmlTagInjection)i).setApplyToSubTagTexts(myApplyRecursivelyCheckBox.isSelected());
- }
+ protected void apply(AbstractTagInjection other) {
+ other.setTagName(myLocalName.getText());
+ other.setTagNamespace(getNamespace());
+ other.setApplyToSubTags(myWithSubtags.isSelected());
}
private String getNamespace() {
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlAttributePanel.form b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlAttributePanel.form
index 1dce7a917205..a9d67f3f938d 100644
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlAttributePanel.form
+++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlAttributePanel.form
@@ -1,22 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.intellij.plugins.intelliLang.inject.config.ui.XmlAttributePanel">
- <grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="5" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="6" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <xy x="20" y="20" width="500" height="479"/>
+ <xy x="20" y="20" width="500" height="551"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<nested-form id="260fa" form-file="org/intellij/plugins/intelliLang/inject/config/ui/TagPanel.form" binding="myTagPanel" custom-create="true">
<constraints>
- <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ <grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</nested-form>
<grid id="ea19" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="3" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<clientProperties>
@@ -30,7 +30,7 @@
</constraints>
<properties>
<labelFor value="cca5"/>
- <text value="L&amp;ocal Name:"/>
+ <text value="L&amp;ocal name:"/>
<toolTipText value="Regular expression to match the attribute name, e.g. &quot;on.*&quot;"/>
</properties>
</component>
@@ -65,19 +65,46 @@
</grid>
<vspacer id="f7910">
<constraints>
- <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ <grid row="5" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<nested-form id="8cfe8" form-file="org/intellij/plugins/intelliLang/inject/config/ui/LanguagePanel.form" binding="myLanguagePanel" custom-create="true">
<constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ <grid row="1" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</nested-form>
<nested-form id="b6e0b" form-file="org/intellij/plugins/intelliLang/inject/config/ui/AdvancedXmlPanel.form" binding="myAdvancedPanel" custom-create="true">
<constraints>
- <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ <grid row="4" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</nested-form>
+ <grid id="2032c" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="e174b" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <labelFor value="80ca6"/>
+ <text value="&amp;Name:"/>
+ </properties>
+ </component>
+ <component id="80ca6" class="javax.swing.JTextField" binding="myNameTextField">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ </children>
+ </grid>
</children>
</grid>
</form>
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlAttributePanel.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlAttributePanel.java
index 9e8e935c39e8..79f451dd31f9 100644
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlAttributePanel.java
+++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlAttributePanel.java
@@ -17,6 +17,8 @@ package org.intellij.plugins.intelliLang.inject.config.ui;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.LanguageTextField;
import org.intellij.lang.regexp.RegExpLanguage;
@@ -35,6 +37,9 @@ public class XmlAttributePanel extends AbstractInjectionPanel<XmlAttributeInject
private EditorTextField myLocalName;
private ComboBox myNamespace;
+ private JTextField myNameTextField;
+
+ private boolean myUseGeneratedName;
public XmlAttributePanel(XmlAttributeInjection injection, Project project) {
super(injection, project);
@@ -43,9 +48,6 @@ public class XmlAttributePanel extends AbstractInjectionPanel<XmlAttributeInject
myNamespace.setModel(TagPanel.createNamespaceUriModel(project));
init(injection.copy());
-
- // be sure to add the listener after initializing the textfield's value
- myLocalName.getDocument().addDocumentListener(new TreeUpdateListener());
}
public JPanel getComponent() {
@@ -53,13 +55,21 @@ public class XmlAttributePanel extends AbstractInjectionPanel<XmlAttributeInject
}
protected void resetImpl() {
+ myNameTextField.setText(myOrigInjection.getDisplayName());
myLocalName.setText(myOrigInjection.getAttributeName());
myNamespace.getEditor().setItem(myOrigInjection.getAttributeNamespace());
+
+ myUseGeneratedName = Comparing.equal(myOrigInjection.getDisplayName(), myOrigInjection.getGeneratedName());
}
- protected void apply(XmlAttributeInjection i) {
- i.setAttributeName(myLocalName.getText());
- i.setAttributeNamespace(getNamespace());
+ protected void apply(XmlAttributeInjection other) {
+ other.setAttributeName(myLocalName.getText());
+ other.setAttributeNamespace(getNamespace());
+
+ String name = myNameTextField.getText();
+ boolean useGenerated = myUseGeneratedName && Comparing.equal(myOrigInjection.getDisplayName(), name);
+ String newName = useGenerated || StringUtil.isEmptyOrSpaces(name) ? other.getGeneratedName() : name;
+ other.setDisplayName(newName);
}
private String getNamespace() {
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlTagPanel.form b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlTagPanel.form
index d19d8571c038..36585ab8a020 100644
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlTagPanel.form
+++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlTagPanel.form
@@ -1,33 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.intellij.plugins.intelliLang.inject.config.ui.XmlTagPanel">
- <grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="5" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <xy x="20" y="20" width="500" height="400"/>
+ <xy x="20" y="20" width="500" height="437"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<nested-form id="4c744" form-file="org/intellij/plugins/intelliLang/inject/config/ui/TagPanel.form" binding="myPanel" custom-create="true">
<constraints>
- <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</nested-form>
<vspacer id="12f92">
<constraints>
- <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<nested-form id="4e64b" form-file="org/intellij/plugins/intelliLang/inject/config/ui/LanguagePanel.form" binding="myLanguagePanel" custom-create="true">
<constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</nested-form>
<nested-form id="fa14a" form-file="org/intellij/plugins/intelliLang/inject/config/ui/AdvancedXmlPanel.form" binding="myAdvancedPanel" custom-create="true">
<constraints>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</nested-form>
+ <grid id="d9c54" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="d2267" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <labelFor value="6c531"/>
+ <text value="&amp;Name:"/>
+ </properties>
+ </component>
+ <component id="6c531" class="javax.swing.JTextField" binding="myNameTextField">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ </children>
+ </grid>
</children>
</grid>
</form>
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlTagPanel.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlTagPanel.java
index ffc92143ba0c..342cfd61cbe7 100644
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlTagPanel.java
+++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/XmlTagPanel.java
@@ -16,6 +16,8 @@
package org.intellij.plugins.intelliLang.inject.config.ui;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.text.StringUtil;
import org.intellij.plugins.intelliLang.inject.config.XmlTagInjection;
import javax.swing.*;
@@ -28,6 +30,9 @@ public class XmlTagPanel extends AbstractInjectionPanel<XmlTagInjection> {
AdvancedXmlPanel myAdvancedPanel;
private JPanel myRoot;
+ private JTextField myNameTextField;
+
+ private boolean myUseGeneratedName;
public XmlTagPanel(XmlTagInjection injection, Project project) {
super(injection, project);
@@ -37,11 +42,16 @@ public class XmlTagPanel extends AbstractInjectionPanel<XmlTagInjection> {
}
protected void apply(XmlTagInjection other) {
- // nothing to do, TagPanel.apply() already does this
+ String name = myNameTextField.getText();
+ boolean useGenerated = myUseGeneratedName && Comparing.equal(myOrigInjection.getDisplayName(), name);
+ String newName = useGenerated || StringUtil.isEmptyOrSpaces(name) ? other.getGeneratedName() : name;
+ other.setDisplayName(newName);
}
protected void resetImpl() {
- // same here^
+ myNameTextField.setText(myOrigInjection.getDisplayName());
+
+ myUseGeneratedName = Comparing.equal(myOrigInjection.getDisplayName(), myOrigInjection.getGeneratedName());
}
public JPanel getComponent() {
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/configurables/XmlAttributeInjectionConfigurable.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/configurables/XmlAttributeInjectionConfigurable.java
deleted file mode 100644
index a0898e0e8664..000000000000
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/configurables/XmlAttributeInjectionConfigurable.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2006 Sascha Weinreuter
- *
- * 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 org.intellij.plugins.intelliLang.inject.config.ui.configurables;
-
-import com.intellij.openapi.project.Project;
-import org.intellij.plugins.intelliLang.inject.config.XmlAttributeInjection;
-import org.intellij.plugins.intelliLang.inject.config.ui.XmlAttributePanel;
-
-public class XmlAttributeInjectionConfigurable extends InjectionConfigurable<XmlAttributeInjection, XmlAttributePanel> {
- public XmlAttributeInjectionConfigurable(XmlAttributeInjection injection, Runnable treeUpdater, Project project) {
- super(injection, treeUpdater, project);
- }
-
- protected XmlAttributePanel createOptionsPanelImpl() {
- return new XmlAttributePanel(myInjection, myProject);
- }
-
- public String getBannerSlogan() {
- return "Edit XML Attribute Injection";
- }
-}
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/configurables/XmlTagInjectionConfigurable.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/configurables/XmlTagInjectionConfigurable.java
deleted file mode 100644
index 655590b2f4cf..000000000000
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/ui/configurables/XmlTagInjectionConfigurable.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2006 Sascha Weinreuter
- *
- * 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 org.intellij.plugins.intelliLang.inject.config.ui.configurables;
-
-import com.intellij.openapi.project.Project;
-import org.intellij.plugins.intelliLang.inject.config.XmlTagInjection;
-import org.intellij.plugins.intelliLang.inject.config.ui.XmlTagPanel;
-
-public class XmlTagInjectionConfigurable extends InjectionConfigurable<XmlTagInjection, XmlTagPanel> {
- public XmlTagInjectionConfigurable(XmlTagInjection injection, Runnable treeUpdater, Project project) {
- super(injection, treeUpdater, project);
- }
-
- public String getBannerSlogan() {
- return "Edit XML Text Injection";
- }
-
- protected XmlTagPanel createOptionsPanelImpl() {
- return new XmlTagPanel(myInjection, myProject);
- }
-}
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java
index 6c84a879b1a6..abe3349a9c15 100644
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java
+++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjectionSupport.java
@@ -43,8 +43,6 @@ import org.intellij.plugins.intelliLang.inject.config.*;
import org.intellij.plugins.intelliLang.inject.config.ui.AbstractInjectionPanel;
import org.intellij.plugins.intelliLang.inject.config.ui.XmlAttributePanel;
import org.intellij.plugins.intelliLang.inject.config.ui.XmlTagPanel;
-import org.intellij.plugins.intelliLang.inject.config.ui.configurables.XmlAttributeInjectionConfigurable;
-import org.intellij.plugins.intelliLang.inject.config.ui.configurables.XmlTagInjectionConfigurable;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -66,7 +64,7 @@ public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSuppor
final PsiElement p = host.getParent();
if (p instanceof XmlAttribute) {
final String s = ((XmlAttribute)p).getName();
- return !(s.equals("xmlns") || s.startsWith("xmlns:"));
+ return !("xmlns".equals(s) || s.startsWith("xmlns:"));
}
}
else if (host instanceof XmlText) {
@@ -177,7 +175,7 @@ public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSuppor
}
});
if (builder.show() == DialogWrapper.OK_EXIT_CODE) {
- return new AbstractTagInjection().copyFrom(xmlInjection);
+ return xmlInjection.copy();
}
return null;
}
@@ -219,12 +217,15 @@ public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSuppor
result.setTagNamespace(value);
}
}
- else if (result instanceof XmlAttributeInjection &&
- "inside".equals(condition.getDebugMethodName()) && condition instanceof PatternConditionPlus) {
- final ElementPattern<?> insidePattern = ((PatternConditionPlus)condition).getValuePattern();
+ else if (result instanceof XmlAttributeInjection && condition instanceof PatternConditionPlus) {
+ boolean strict = "withParent".equals(condition.getDebugMethodName());
+ if (!strict && !"inside".equals(condition.getDebugMethodName())) return null;
+
+ result.setApplyToSubTags(!strict);
+ ElementPattern<?> insidePattern = ((PatternConditionPlus)condition).getValuePattern();
if (!XmlTag.class.equals(insidePattern.getCondition().getInitialCondition().getAcceptedClass())) return null;
for (PatternCondition<?> insideCondition : insidePattern.getCondition().getConditions()) {
- final String tagValue = extractValue(insideCondition);
+ String tagValue = extractValue(insideCondition);
if (tagValue == null) return null;
if ("withLocalName".equals(insideCondition.getDebugMethodName())) {
result.setTagName(tagValue);
@@ -232,10 +233,11 @@ public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSuppor
else if ("withNamespace".equals(insideCondition.getDebugMethodName())) {
result.setTagNamespace(tagValue);
}
-
}
}
- else return null;
+ else {
+ return null;
+ }
}
result.generatePlaces();
return result;
@@ -265,14 +267,17 @@ public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSuppor
return null;
}
- public BaseInjection createInjection(final Element element) {
- if (element.getName().equals(XmlAttributeInjection.class.getSimpleName())) {
+ public BaseInjection createInjection(Element element) {
+ String place = StringUtil.notNullize(element.getChildText("place"), "");
+ if (place.startsWith("xmlAttribute")) {
return new XmlAttributeInjection();
}
- else if (element.getName().equals(XmlTagInjection.class.getSimpleName())) {
+ else if (place.startsWith("xmlTag")) {
return new XmlTagInjection();
}
- return new AbstractTagInjection();
+ else {
+ return new BaseInjection(XML_SUPPORT_ID);
+ }
}
public Configurable[] createSettings(final Project project, final Configuration configuration) {
@@ -298,12 +303,10 @@ public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSuppor
final AbstractTagInjection originalInjection = (AbstractTagInjection)configuration.findExistingInjection(template);
final XmlTagInjection newInjection = originalInjection == null? template : new XmlTagInjection().copyFrom(originalInjection);
- if (InjectLanguageAction.doEditConfigurable(project, new XmlTagInjectionConfigurable(newInjection, null, project))) {
- configuration.replaceInjectionsWithUndo(
- project, Collections.singletonList(newInjection),
- ContainerUtil.createMaybeSingletonList(originalInjection),
- Collections.<PsiElement>emptyList());
- }
+ configuration.replaceInjectionsWithUndo(
+ project, Collections.singletonList(newInjection),
+ ContainerUtil.createMaybeSingletonList(originalInjection),
+ Collections.<PsiElement>emptyList());
}
private static boolean doInjectInAttributeValue(final XmlAttributeValue host, final String languageId) {
@@ -327,12 +330,10 @@ public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSuppor
final Configuration configuration = InjectorUtils.getEditableInstance(project);
final BaseInjection originalInjection = configuration.findExistingInjection(template);
final BaseInjection newInjection = originalInjection == null ? template : originalInjection.copy();
- if (InjectLanguageAction.doEditConfigurable(project, new XmlAttributeInjectionConfigurable((XmlAttributeInjection)newInjection, null, project))) {
- configuration.replaceInjectionsWithUndo(
- project, Collections.singletonList(newInjection),
- ContainerUtil.createMaybeSingletonList(originalInjection),
- Collections.<PsiElement>emptyList());
- }
+ configuration.replaceInjectionsWithUndo(
+ project, Collections.singletonList(newInjection),
+ ContainerUtil.createMaybeSingletonList(originalInjection),
+ Collections.<PsiElement>emptyList());
}
private static ArrayList<BaseInjection> collectInjections(final PsiElement host,
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java
index f8026edb4f11..c7808b0c1c40 100644
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java
+++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java
@@ -32,6 +32,7 @@ import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.xml.*;
import com.intellij.util.PairProcessor;
import com.intellij.util.PatternValuesIndex;
+import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import org.intellij.plugins.intelliLang.Configuration;
import org.intellij.plugins.intelliLang.inject.InjectedLanguage;
@@ -113,8 +114,7 @@ public final class XmlLanguageInjector implements MultiHostInjector {
if (language == null) continue;
final boolean separateFiles = !injection.isSingleFile() && StringUtil.isNotEmpty(injection.getValuePattern());
- final List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> result =
- new ArrayList<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>>();
+ final List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> result = ContainerUtil.newArrayList();
xmlTag.acceptChildren(new PsiElementVisitor() {
@Override
@@ -130,7 +130,7 @@ public final class XmlLanguageInjector implements MultiHostInjector {
}
else if (element instanceof XmlTag) {
if (!separateFiles) unparsableRef.set(Boolean.TRUE);
- if (injection instanceof AbstractTagInjection && ((AbstractTagInjection)injection).isApplyToSubTagTexts()) {
+ if (injection instanceof AbstractTagInjection && ((AbstractTagInjection)injection).isApplyToSubTags()) {
element.acceptChildren(this);
}
}
diff --git a/plugins/git4idea/src/git4idea/log/GitLogProvider.java b/plugins/git4idea/src/git4idea/log/GitLogProvider.java
index 0a8bc3723d3f..672e4eb8dead 100644
--- a/plugins/git4idea/src/git4idea/log/GitLogProvider.java
+++ b/plugins/git4idea/src/git4idea/log/GitLogProvider.java
@@ -29,12 +29,7 @@ import com.intellij.util.ExceptionUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.*;
-import com.intellij.vcs.log.data.VcsLogBranchFilter;
-import com.intellij.vcs.log.data.VcsLogDateFilter;
-import com.intellij.vcs.log.data.VcsLogStructureFilter;
-import com.intellij.vcs.log.data.VcsLogUserFilter;
import com.intellij.vcs.log.impl.HashImpl;
-import com.intellij.vcs.log.ui.filter.VcsLogTextFilter;
import git4idea.GitLocalBranch;
import git4idea.GitRemoteBranch;
import git4idea.GitVcs;
@@ -189,7 +184,11 @@ public class GitLogProvider implements VcsLogProvider {
@NotNull
@Override
public List<? extends VcsFullCommitDetails> getFilteredDetails(@NotNull final VirtualFile root,
- @NotNull Collection<VcsLogFilter> filters,
+ @NotNull Collection<VcsLogBranchFilter> branchFilters,
+ @NotNull Collection<VcsLogUserFilter> userFilters,
+ @NotNull Collection<VcsLogDateFilter> dateFilters,
+ @NotNull Collection<VcsLogTextFilter> textFilters,
+ @NotNull Collection<VcsLogStructureFilter> structureFilters,
int maxCount) throws VcsException {
if (!isRepositoryReady(root)) {
return Collections.emptyList();
@@ -197,21 +196,19 @@ public class GitLogProvider implements VcsLogProvider {
List<String> filterParameters = ContainerUtil.newArrayList();
- List<VcsLogBranchFilter> branchFilters = ContainerUtil.findAll(filters, VcsLogBranchFilter.class);
if (!branchFilters.isEmpty()) {
// git doesn't support filtering by several branches very well (--branches parameter give a weak pattern capabilities)
// => by now assuming there is only one branch filter.
if (branchFilters.size() > 1) {
LOG.warn("More than one branch filter was passed. Using only the first one.");
}
- VcsLogBranchFilter branchFilter = branchFilters.get(0);
+ VcsLogBranchFilter branchFilter = branchFilters.iterator().next();
filterParameters.add(branchFilter.getBranchName());
}
else {
filterParameters.addAll(GitHistoryUtils.LOG_ALL);
}
- List<VcsLogUserFilter> userFilters = ContainerUtil.findAll(filters, VcsLogUserFilter.class);
if (!userFilters.isEmpty()) {
String authorFilter = joinFilters(userFilters, new Function<VcsLogUserFilter, String>() {
@Override
@@ -222,7 +219,6 @@ public class GitLogProvider implements VcsLogProvider {
filterParameters.add(prepareParameter("author", authorFilter));
}
- List<VcsLogDateFilter> dateFilters = ContainerUtil.findAll(filters, VcsLogDateFilter.class);
if (!dateFilters.isEmpty()) {
// assuming there is only one date filter, until filter expressions are defined
VcsLogDateFilter filter = dateFilters.iterator().next();
@@ -234,7 +230,6 @@ public class GitLogProvider implements VcsLogProvider {
}
}
- List<VcsLogTextFilter> textFilters = ContainerUtil.findAll(filters, VcsLogTextFilter.class);
if (textFilters.size() > 1) {
LOG.warn("Expected only one text filter: " + textFilters);
}
@@ -249,8 +244,7 @@ public class GitLogProvider implements VcsLogProvider {
}
filterParameters.add("--date-order");
- // note: this filter must be the last parameter, because it uses "--" which separates parameters from paths
- List<VcsLogStructureFilter> structureFilters = ContainerUtil.findAll(filters, VcsLogStructureFilter.class);
+ // note: structure filter must be the last parameter, because it uses "--" which separates parameters from paths
if (!structureFilters.isEmpty()) {
filterParameters.add("--");
for (VcsLogStructureFilter filter : structureFilters) {
@@ -281,7 +275,7 @@ public class GitLogProvider implements VcsLogProvider {
return "--" + paramName + "=" + value; // no value escaping needed, because the parameter itself will be quoted by GeneralCommandLine
}
- private static <T> String joinFilters(List<T> filters, Function<T, String> toString) {
+ private static <T> String joinFilters(Collection<T> filters, Function<T, String> toString) {
return StringUtil.join(filters, toString, "\\|");
}
diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml
index fc7d25465569..034ef355421d 100644
--- a/plugins/gradle/src/META-INF/plugin.xml
+++ b/plugins/gradle/src/META-INF/plugin.xml
@@ -67,12 +67,14 @@
<externalSystemConfigLocator implementation="org.jetbrains.plugins.gradle.service.settings.GradleConfigLocator"/>
<externalSystemManager implementation="org.jetbrains.plugins.gradle.GradleManager"/>
+ <externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.BuildClasspathModuleGradleDataService"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.service.GradleInstallationManager"/>
<projectService serviceImplementation="org.jetbrains.plugins.gradle.settings.GradleSettings"/>
<projectService serviceImplementation="org.jetbrains.plugins.gradle.settings.GradleLocalSettings"/>
<projectService serviceImplementation="org.jetbrains.plugins.gradle.service.project.GradleNotification"/>
+ <projectService serviceImplementation="org.jetbrains.plugins.gradle.service.GradleBuildClasspathManager"/>
<configurationProducer implementation="org.jetbrains.plugins.gradle.service.execution.GradleRuntimeConfigurationProducer"/>
diff --git a/plugins/gradle/src/META-INF/services/org.jetbrains.plugins.gradle.model.ModelBuilderService b/plugins/gradle/src/META-INF/services/org.jetbrains.plugins.gradle.model.ModelBuilderService
index 3989c7cb0610..430ac6f37ba0 100644
--- a/plugins/gradle/src/META-INF/services/org.jetbrains.plugins.gradle.model.ModelBuilderService
+++ b/plugins/gradle/src/META-INF/services/org.jetbrains.plugins.gradle.model.ModelBuilderService
@@ -16,3 +16,4 @@
org.jetbrains.plugins.gradle.model.builder.WarModelBuilderImpl
org.jetbrains.plugins.gradle.model.builder.ModelDependenciesBuilderImpl
org.jetbrains.plugins.gradle.model.builder.ModuleExtendedModelBuilderImpl
+org.jetbrains.plugins.gradle.model.builder.ModelBuildScriptClasspathBuilderImpl
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleClassFinder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleClassFinder.java
index f85c75acce16..d1fa23ad150e 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleClassFinder.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleClassFinder.java
@@ -16,13 +16,15 @@
package org.jetbrains.plugins.gradle.config;
+import com.intellij.openapi.externalSystem.psi.search.ExternalModuleBuildGlobalSearchScope;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.NonClasspathClassFinder;
+import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.service.GradleInstallationManager;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.service.GradleBuildClasspathManager;
-import java.util.Collections;
import java.util.List;
/**
@@ -30,19 +32,31 @@ import java.util.List;
*/
public class GradleClassFinder extends NonClasspathClassFinder {
- @NotNull private final GradleInstallationManager myLibraryManager;
+ @NotNull private final GradleBuildClasspathManager myBuildClasspathManager;
- public GradleClassFinder(Project project, @NotNull GradleInstallationManager manager) {
- super(project, true, true);
- myLibraryManager = manager;
+ public GradleClassFinder(Project project, @NotNull GradleBuildClasspathManager buildClasspathManager) {
+ super(project, true);
+ myBuildClasspathManager = buildClasspathManager;
}
@Override
protected List<VirtualFile> calcClassRoots() {
- final List<VirtualFile> roots = myLibraryManager.getClassRoots(myProject);
- if (roots != null) {
- return roots;
+ // do not use default NonClasspathClassFinder caching strategy based on PSI change
+ // the caching performed in GradleBuildClasspathManager
+ throw new AssertionError();
+ }
+
+ @Override
+ protected List<VirtualFile> getClassRoots() {
+ return myBuildClasspathManager.getAllClasspathEntries();
+ }
+
+ @Override
+ protected List<VirtualFile> getClassRoots(@Nullable GlobalSearchScope scope) {
+ if (scope instanceof ExternalModuleBuildGlobalSearchScope) {
+ ExternalModuleBuildGlobalSearchScope externalModuleBuildGlobalSearchScope = (ExternalModuleBuildGlobalSearchScope)scope;
+ return myBuildClasspathManager.getModuleClasspathEntries(externalModuleBuildGlobalSearchScope.getExternalModulePath());
}
- return Collections.emptyList();
+ return myBuildClasspathManager.getAllClasspathEntries();
}
} \ No newline at end of file
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
index b7ecd351d58d..d5984903fe90 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
@@ -21,12 +21,18 @@ import com.intellij.execution.*;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.externalSystem.psi.search.ExternalModuleBuildGlobalSearchScope;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.JdkOrderEntry;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.OrderEnumerator;
+import com.intellij.openapi.roots.impl.LibraryScopeCache;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
@@ -40,8 +46,10 @@ import icons.GradleIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.execution.GradleTaskLocation;
-import org.jetbrains.plugins.gradle.util.GradleConstants;
+import org.jetbrains.plugins.gradle.service.GradleBuildClasspathManager;
import org.jetbrains.plugins.gradle.service.GradleInstallationManager;
+import org.jetbrains.plugins.gradle.service.resolve.GradleResolverUtil;
+import org.jetbrains.plugins.gradle.util.GradleConstants;
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
import org.jetbrains.plugins.groovy.extensions.GroovyScriptType;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
@@ -72,9 +80,9 @@ public class GradleScriptType extends GroovyScriptType {
private static final Pattern MAIN_CLASS_NAME_PATTERN = Pattern.compile("\nSTARTER_MAIN_CLASS=(.*)\n");
public static final GroovyScriptType INSTANCE = new GradleScriptType();
-
+
private GradleScriptType() {
- super(GradleConstants.EXTENSION);
+ super(GradleConstants.EXTENSION);
}
@NotNull
@@ -89,7 +97,7 @@ public class GradleScriptType extends GroovyScriptType {
if (params == null) {
return false;
}
-
+
final List<String> tasks = getTasksTarget(location);
if (tasks == null) {
return false;
@@ -218,7 +226,9 @@ public class GradleScriptType extends GroovyScriptType {
throw new CantRunException(String.format("Module '%s' is not backed by gradle", module.getName()));
}
final VirtualFile gradleHome = libraryManager.getGradleHome(module, project, rootProjectPath);
- assert gradleHome != null;
+ if(gradleHome == null) {
+ throw new CantRunException("Gradle home can not be found");
+ }
params.setMainClass(findMainClass(gradleHome, script, project));
@@ -249,11 +259,11 @@ public class GradleScriptType extends GroovyScriptType {
params.getVMParametersList().add("-Dgradle.home=" + FileUtil.toSystemDependentName(gradleHome.getPath()));
setToolsJar(params);
-
+
final String scriptPath = configuration.getScriptPath();
if (scriptPath == null) {
throw new CantRunException("Target script is undefined");
- }
+ }
params.getProgramParametersList().add("--build-file");
params.getProgramParametersList().add(FileUtil.toSystemDependentName(scriptPath));
params.getProgramParametersList().addParametersString(configuration.getProgramParameters());
@@ -298,22 +308,28 @@ public class GradleScriptType extends GroovyScriptType {
@Override
public GlobalSearchScope patchResolveScope(@NotNull GroovyFile file, @NotNull GlobalSearchScope baseScope) {
+ if (!FileUtilRt.extensionEquals(file.getName(), GradleConstants.EXTENSION)) return baseScope;
+
+ final Collection<VirtualFile> files;
+ GlobalSearchScope result = GlobalSearchScope.EMPTY_SCOPE;
final Module module = ModuleUtilCore.findModuleForPsiElement(file);
- final GradleInstallationManager libraryManager = ServiceManager.getService(GradleInstallationManager.class);
if (module != null) {
- if (libraryManager.getGradleHome(module) != null) {
- return baseScope;
+ for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) {
+ if (entry instanceof JdkOrderEntry) {
+ GlobalSearchScope scopeForSdk = LibraryScopeCache.getInstance(module.getProject()).getScopeForSdk((JdkOrderEntry)entry);
+ result = result.uniteWith(scopeForSdk);
+ }
}
- }
- final Collection<VirtualFile> files = libraryManager.getClassRoots(file.getProject());
- if (files == null || files.isEmpty()) {
- return baseScope;
- }
+ String modulePath = module.getOptionValue(ExternalSystemConstants.LINKED_PROJECT_PATH_KEY);
+ if(modulePath == null) return result;
+
+ files = GradleBuildClasspathManager.getInstance(file.getProject()).getModuleClasspathEntries(modulePath);
- GlobalSearchScope result = baseScope;
- for (final VirtualFile root : files) {
- result = result.uniteWith(new NonClasspathDirectoryScope(root));
+ for (final VirtualFile root : files) {
+ result = result.uniteWith(new NonClasspathDirectoryScope(root));
+ }
+ result = new ExternalModuleBuildGlobalSearchScope(result, modulePath);
}
return result;
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java
index f34748e44487..d14125e85122 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.plugins.gradle.integrations.maven;
+import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
@@ -97,9 +98,9 @@ public class ImportMavenRepositoriesTask implements Runnable {
final PsiFile[] psiFiles = ArrayUtil.toObjectArray(psiFileList, PsiFile.class);
- final Set<MavenRemoteRepository> mavenRemoteRepositories = new WriteCommandAction<Set<MavenRemoteRepository>>(myProject, psiFiles) {
+ final Set<MavenRemoteRepository> mavenRemoteRepositories = new ReadAction<Set<MavenRemoteRepository>>() {
@Override
- protected void run(Result<Set<MavenRemoteRepository>> result) throws Throwable {
+ protected void run(@NotNull Result<Set<MavenRemoteRepository>> result) throws Throwable {
Set<MavenRemoteRepository> myRemoteRepositories = ContainerUtil.newHashSet();
for (PsiFile psiFile : psiFiles) {
List<GrClosableBlock> repositoriesBlocks = ContainerUtil.newArrayList();
@@ -118,7 +119,7 @@ public class ImportMavenRepositoriesTask implements Runnable {
}
}.execute().getResultObject();
- if (mavenRemoteRepositories.isEmpty()) return;
+ if (mavenRemoteRepositories == null || mavenRemoteRepositories.isEmpty()) return;
MavenRepositoriesHolder.getInstance(myProject).update(mavenRemoteRepositories);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/BuildScriptClasspathModel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/BuildScriptClasspathModel.java
new file mode 100644
index 000000000000..6854655609ca
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/BuildScriptClasspathModel.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.model;
+
+import org.gradle.tooling.model.DomainObjectSet;
+
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/20/13
+ */
+public interface BuildScriptClasspathModel extends Serializable {
+ DomainObjectSet<? extends ClasspathEntryModel> getClasspath();
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/ClasspathEntryModel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/ClasspathEntryModel.java
new file mode 100644
index 000000000000..09120caccacf
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/ClasspathEntryModel.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/20/13
+ */
+public interface ClasspathEntryModel {
+ @NotNull
+ File getClassesFile();
+
+ @Nullable
+ File getSourcesFile();
+
+ @Nullable
+ File getJavadocFile();
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/GradleDependencyScope.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/GradleDependencyScope.java
index 7186312c24b4..78caa4d9f4d5 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/GradleDependencyScope.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/GradleDependencyScope.java
@@ -22,11 +22,6 @@ import org.jetbrains.annotations.Nullable;
* @since 11/25/13
*/
public enum GradleDependencyScope {
- // Implicit scopes
- PROVIDED("provided", "provided", true, true, true, true),
- OPTIONAL("optional", "compile", true, true, true, true),
-
-
// Java Plugin Scopes
/**
* Compile time dependencies
@@ -74,7 +69,11 @@ public enum GradleDependencyScope {
/**
* Compiles test Scala source files.
*/
- COMPILE_TEST_SCALA("compileTestScala", "test", false, false, true, true);
+ COMPILE_TEST_SCALA("compileTestScala", "test", false, false, true, true),
+
+ // Implicit scopes
+ PROVIDED("provided", "provided", true, true, true, true),
+ OPTIONAL("optional", "compile", true, true, true, true),;
private final String myGradleName;
private final String myIdeaMappingName;
@@ -124,7 +123,7 @@ public enum GradleDependencyScope {
@Nullable
public static GradleDependencyScope fromIdeaMappingName(final String ideaMappingName) {
for (GradleDependencyScope scope : values()) {
- if (scope.myIdeaMappingName.equals(ideaMappingName.toLowerCase())) return scope;
+ if (scope.myIdeaMappingName.equals(ideaMappingName)) return scope;
}
return null;
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelBuildScriptClasspathBuilderImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelBuildScriptClasspathBuilderImpl.java
new file mode 100644
index 000000000000..875d9cc26bc6
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelBuildScriptClasspathBuilderImpl.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.model.builder;
+
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.plugins.ide.idea.IdeaPlugin;
+import org.gradle.plugins.ide.idea.model.IdeaModel;
+import org.gradle.plugins.ide.internal.IdeDependenciesExtractor;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel;
+import org.jetbrains.plugins.gradle.model.ModelBuilderService;
+import org.jetbrains.plugins.gradle.model.internal.BuildScriptClasspathModelImpl;
+import org.jetbrains.plugins.gradle.model.internal.ClasspathEntryModelImpl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/20/13
+ */
+public class ModelBuildScriptClasspathBuilderImpl implements ModelBuilderService {
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return BuildScriptClasspathModel.class.getName().equals(modelName);
+ }
+
+ @Nullable
+ @Override
+ public Object buildAll(final String modelName, final Project project) {
+ boolean offline = false;
+ boolean downloadJavadoc = false;
+ boolean downloadSources = true;
+
+ final IdeaPlugin ideaPlugin = project.getPlugins().getPlugin(IdeaPlugin.class);
+
+ if (ideaPlugin != null) {
+ IdeaModel ideaModel = ideaPlugin.getModel();
+ if (ideaModel != null && ideaModel.getModule() != null) {
+ offline = ideaModel.getModule().isOffline();
+ downloadJavadoc = ideaModel.getModule().isDownloadJavadoc();
+ downloadSources = ideaModel.getModule().isDownloadSources();
+ }
+ }
+
+ final IdeDependenciesExtractor dependenciesExtractor = new IdeDependenciesExtractor();
+
+ final Configuration configuration = project.getBuildscript().getConfigurations().findByName("classpath");
+ Collection<Configuration> plusConfigurations = Collections.singletonList(configuration);
+
+ BuildScriptClasspathModelImpl buildScriptClasspath = new BuildScriptClasspathModelImpl();
+
+ if (!offline) {
+ // download sources and/or javadoc
+ List<IdeDependenciesExtractor.IdeRepoFileDependency> repoFileDependencies = dependenciesExtractor.extractRepoFileDependencies(
+ project.getConfigurations(), plusConfigurations, new ArrayList<Configuration>(), downloadSources, downloadJavadoc);
+
+ for (IdeDependenciesExtractor.IdeRepoFileDependency dependency : repoFileDependencies) {
+ if (dependency.getFile() == null) continue;
+
+ buildScriptClasspath.add(
+ new ClasspathEntryModelImpl(dependency.getFile(), dependency.getSourceFile(), dependency.getJavadocFile()));
+ }
+ }
+
+ final List<IdeDependenciesExtractor.IdeLocalFileDependency> localFileDependencies =
+ dependenciesExtractor.extractLocalFileDependencies(plusConfigurations, new ArrayList<Configuration>());
+
+ for (IdeDependenciesExtractor.IdeLocalFileDependency dependency : localFileDependencies) {
+ if (dependency.getFile() == null) continue;
+ buildScriptClasspath.add(new ClasspathEntryModelImpl(dependency.getFile(), null, null));
+ }
+
+ return buildScriptClasspath;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImpl.java
index 05864829e6ed..4c0e3914185e 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImpl.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImpl.java
@@ -24,6 +24,7 @@ import org.gradle.plugins.ide.idea.IdeaPlugin;
import org.gradle.plugins.ide.idea.model.IdeaModel;
import org.gradle.plugins.ide.internal.IdeDependenciesExtractor;
import org.gradle.tooling.model.idea.IdeaDependency;
+import org.gradle.util.GradleVersion;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
import org.jetbrains.plugins.gradle.model.ModelBuilderService;
@@ -54,7 +55,7 @@ public class ModelDependenciesBuilderImpl implements ModelBuilderService {
public Object buildAll(final String modelName, final Project project) {
final List<IdeaDependency> dependencies = new ArrayList<IdeaDependency>();
- final Map<DependencyVersionId, Scopes> scopesMap = new HashMap<DependencyVersionId, Scopes>();
+ final Map<DependencyVersionId, Scopes> scopesMap = new LinkedHashMap<DependencyVersionId, Scopes>();
final IdeDependenciesExtractor dependenciesExtractor = new IdeDependenciesExtractor();
boolean offline = false;
@@ -148,6 +149,7 @@ public class ModelDependenciesBuilderImpl implements ModelBuilderService {
versionId.getClassifier()
);
libraryDependency.setFile(fileDependency.getFile());
+ attachGradleSdkSources(libraryDependency, fileDependency);
dependencies.add(libraryDependency);
}
}
@@ -156,6 +158,32 @@ public class ModelDependenciesBuilderImpl implements ModelBuilderService {
return new ProjectDependenciesModelImpl(project.getPath(), dependencies);
}
+ private static void attachGradleSdkSources(IdeaSingleEntryLibraryDependencyImpl libraryDependency,
+ IdeDependenciesExtractor.IdeLocalFileDependency localFileDependency) {
+ final String libName = localFileDependency.getFile().getName();
+ if (localFileDependency.getFile() == null || !libName.startsWith("gradle-")) return;
+
+ File libOrPluginsFile = localFileDependency.getFile().getParentFile();
+ if (libOrPluginsFile != null && ("plugins".equals(libOrPluginsFile.getName()))) {
+ libOrPluginsFile = libOrPluginsFile.getParentFile();
+ }
+
+ if (libOrPluginsFile != null && "lib".equals(libOrPluginsFile.getName()) && libOrPluginsFile.getParentFile() != null) {
+ File srcDir = new File(libOrPluginsFile.getParentFile(), "src");
+ if (GradleVersion.current().compareTo(GradleVersion.version("1.9")) >= 0) {
+ int endIndex = libName.indexOf(GradleVersion.current().getVersion() + ".jar");
+ if (endIndex != -1) {
+ String srcDirChild = libName.substring("gradle-".length(), endIndex - 1);
+ srcDir = new File(srcDir, srcDirChild);
+ }
+ }
+
+ if (srcDir.isDirectory()) {
+ libraryDependency.setSource(srcDir);
+ }
+ }
+ }
+
@Nullable
private static String findDeDuplicatedModuleName(Project project) {
if (project.hasProperty(MODULE_PROPERTY)) {
@@ -261,15 +289,13 @@ public class ModelDependenciesBuilderImpl implements ModelBuilderService {
private static GradleDependencyScope deduceScope(String configurationName,
Map<String, Map<String, Collection<Configuration>>> userScopes) {
GradleDependencyScope scope = GradleDependencyScope.fromName(configurationName);
- if (scope == null) {
- for (Map.Entry<String, Map<String, Collection<Configuration>>> entry : userScopes.entrySet()) {
- Collection<Configuration> plusConfigurations = entry.getValue().get("plus");
- if (plusConfigurations == null) continue;
-
- for (Configuration plus : plusConfigurations) {
- if (plus.getName().equals(configurationName)) {
- return GradleDependencyScope.fromIdeaMappingName(entry.getKey());
- }
+ for (Map.Entry<String, Map<String, Collection<Configuration>>> entry : userScopes.entrySet()) {
+ Collection<Configuration> plusConfigurations = entry.getValue().get("plus");
+ if (plusConfigurations == null) continue;
+
+ for (Configuration plus : plusConfigurations) {
+ if (plus.getName().equals(configurationName)) {
+ return GradleDependencyScope.fromIdeaMappingName(entry.getKey().toLowerCase());
}
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImpl.java
index 3dc854020c6c..44eb6cfe328b 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImpl.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImpl.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.plugins.gradle.model.builder;
+import groovy.lang.GroovyObject;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.tasks.SourceSet;
@@ -69,10 +70,17 @@ public class ModuleExtendedModelBuilderImpl implements ModelBuilderService {
moduleVersionModel.setArtifacts(artifacts);
+ final Set<String> sourceDirectories = new HashSet<String>();
final Set<String> testDirectories = new HashSet<String>();
+ final Set<String> resourceDirectories = new HashSet<String>();
+ final Set<String> testResourceDirectories = new HashSet<String>();
+
+ final List<File> testClassesDirs = new ArrayList<File>();
for (Task task : project.getTasks()) {
if (task instanceof Test) {
Test test = (Test)task;
+ testClassesDirs.add(test.getTestClassesDir());
+
if (test.hasProperty(TEST_SRC_DIRS_PROPERTY)) {
Object testSrcDirs = test.property(TEST_SRC_DIRS_PROPERTY);
if (testSrcDirs instanceof Iterable) {
@@ -84,40 +92,58 @@ public class ModuleExtendedModelBuilderImpl implements ModelBuilderService {
}
}
- final Set<String> javaDirectories = new HashSet<String>();
- final Set<String> resourceDirectories = new HashSet<String>();
-
if (project.hasProperty(SOURCE_SETS_PROPERTY)) {
Object sourceSets = project.property(SOURCE_SETS_PROPERTY);
if (sourceSets instanceof SourceSetContainer) {
SourceSetContainer sourceSetContainer = (SourceSetContainer)sourceSets;
for (SourceSet sourceSet : sourceSetContainer) {
- for (File javaSrcDir : sourceSet.getAllJava().getSrcDirs()) {
- addFilePath(javaDirectories, javaSrcDir);
+ for (File javaSrcDir : sourceSet.getJava().getSrcDirs()) {
+ boolean isTestDir = isTestDir(sourceSet, testClassesDirs);
+ addFilePath(isTestDir ? testDirectories : sourceDirectories, javaSrcDir);
}
for (File resourcesSrcDir : sourceSet.getResources().getSrcDirs()) {
- addFilePath(resourceDirectories, resourcesSrcDir);
+ boolean isTestDir = isTestDir(sourceSet, testClassesDirs);
+ addFilePath(isTestDir ? testResourceDirectories : resourceDirectories, resourcesSrcDir);
}
}
}
}
-
File projectDir = project.getProjectDir();
IdeaContentRootImpl contentRoot = new IdeaContentRootImpl(projectDir);
- enrichDataFromIdeaPlugin(project, contentRoot, javaDirectories, testDirectories);
+ final Set<String> ideaSourceDirectories = new HashSet<String>();
+ final Set<String> ideaTestDirectories = new HashSet<String>();
+ final Set<String> ideaExtResourceDirectories = new HashSet<String>();
+ final Set<String> ideaExtTestResourceDirectories = new HashSet<String>();
+ final Set<File> excludeDirectories = new HashSet<File>();
+
+ enrichDataFromIdeaPlugin(project, excludeDirectories, ideaSourceDirectories, ideaTestDirectories,
+ ideaExtResourceDirectories, ideaExtTestResourceDirectories);
- javaDirectories.removeAll(testDirectories);
- javaDirectories.removeAll(resourceDirectories);
+ if (ideaSourceDirectories.isEmpty()) {
+ sourceDirectories.clear();
+ resourceDirectories.clear();
+ }
+ if (ideaTestDirectories.isEmpty()) {
+ testDirectories.clear();
+ testResourceDirectories.clear();
+ }
- final Set<String> testResourceDirectories = new HashSet<String>(resourceDirectories);
- testResourceDirectories.retainAll(testDirectories);
+ ideaSourceDirectories.removeAll(resourceDirectories);
+ sourceDirectories.addAll(ideaSourceDirectories);
+ ideaTestDirectories.removeAll(testResourceDirectories);
+ testDirectories.addAll(ideaTestDirectories);
- testDirectories.removeAll(resourceDirectories);
- resourceDirectories.removeAll(testResourceDirectories);
+ resourceDirectories.addAll(ideaExtResourceDirectories);
+ testResourceDirectories.addAll(ideaExtTestResourceDirectories);
- for (String javaDir : javaDirectories) {
+ // ensure disjoint directories with different type
+ resourceDirectories.removeAll(sourceDirectories);
+ testDirectories.removeAll(sourceDirectories);
+ testResourceDirectories.removeAll(testDirectories);
+
+ for (String javaDir : sourceDirectories) {
contentRoot.addSourceDirectory(new IdeaSourceDirectoryImpl(new File(javaDir)));
}
for (String testDir : testDirectories) {
@@ -129,11 +155,29 @@ public class ModuleExtendedModelBuilderImpl implements ModelBuilderService {
for (String testResourceDir : testResourceDirectories) {
contentRoot.addTestResourceDirectory(new IdeaSourceDirectoryImpl(new File(testResourceDir)));
}
+ for (File excludeDir : excludeDirectories) {
+ contentRoot.addExcludeDirectory(excludeDir);
+ }
moduleVersionModel.setContentRoots(Collections.<ExtIdeaContentRoot>singleton(contentRoot));
return moduleVersionModel;
}
+ private static boolean isTestDir(SourceSet sourceSet, List<File> testClassesDirs) {
+ if (SourceSet.TEST_SOURCE_SET_NAME.equals(sourceSet.getName())) return true;
+ if (SourceSet.MAIN_SOURCE_SET_NAME.equals(sourceSet.getName())) return false;
+
+ File sourceSetClassesDir = sourceSet.getOutput().getClassesDir();
+ for (File testClassesDir : testClassesDirs) {
+ do {
+ if (sourceSetClassesDir.getPath().equals(testClassesDir.getPath())) return true;
+ }
+ while ((testClassesDir = testClassesDir.getParentFile()) != null);
+ }
+
+ return false;
+ }
+
private static void addFilePath(Set<String> filePathSet, Object file) {
if (file instanceof File) {
try {
@@ -145,9 +189,11 @@ public class ModuleExtendedModelBuilderImpl implements ModelBuilderService {
}
private static void enrichDataFromIdeaPlugin(Project project,
- IdeaContentRootImpl contentRoot,
+ Set<File> excludeDirectories,
Set<String> javaDirectories,
- Set<String> testDirectories) {
+ Set<String> testDirectories,
+ Set<String> ideaExtResourceDirectories,
+ Set<String> ideaExtTestResourceDirectories) {
IdeaPlugin ideaPlugin = project.getPlugins().getPlugin(IdeaPlugin.class);
if (ideaPlugin == null) return;
@@ -156,7 +202,7 @@ public class ModuleExtendedModelBuilderImpl implements ModelBuilderService {
if (ideaModel == null || ideaModel.getModule() == null) return;
for (File excludeDir : ideaModel.getModule().getExcludeDirs()) {
- contentRoot.addExcludeDirectory(excludeDir);
+ excludeDirectories.add(excludeDir);
}
for (File file : ideaModel.getModule().getSourceDirs()) {
javaDirectories.add(file.getPath());
@@ -164,5 +210,25 @@ public class ModuleExtendedModelBuilderImpl implements ModelBuilderService {
for (File file : ideaModel.getModule().getTestSourceDirs()) {
testDirectories.add(file.getPath());
}
+
+ ideaExtResourceDirectories.addAll(getExtDirs("resourceDirs", ideaModel.getModule()));
+ ideaExtTestResourceDirectories.addAll(getExtDirs("testResourceDirs", ideaModel.getModule()));
+ }
+
+ private static List<String> getExtDirs(String propertyName, GroovyObject ideaModule) {
+ List<String> directories = new ArrayList<String>();
+ Object resourceDirs = ideaModule.getProperty(propertyName);
+ if (resourceDirs instanceof Iterable) {
+ for (Object o : Iterable.class.cast(resourceDirs)) {
+ if (o instanceof File) {
+ directories.add(File.class.cast(o).getPath());
+ }
+ else if (o instanceof String) {
+ directories.add((String)o);
+ }
+ }
+ }
+
+ return directories;
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/BuildScriptClasspathData.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/BuildScriptClasspathData.java
new file mode 100644
index 000000000000..cc252a9750a0
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/BuildScriptClasspathData.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.model.data;
+
+import com.intellij.openapi.externalSystem.model.Key;
+import com.intellij.openapi.externalSystem.model.ProjectKeys;
+import com.intellij.openapi.externalSystem.model.ProjectSystemId;
+import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/20/13
+ */
+public class BuildScriptClasspathData extends AbstractExternalEntityData {
+ private static final long serialVersionUID = 1L;
+ @NotNull
+ public static final Key<BuildScriptClasspathData> KEY =
+ Key.create(BuildScriptClasspathData.class, ProjectKeys.LIBRARY_DEPENDENCY.getProcessingWeight() + 1);
+
+ @NotNull
+ private final List<ClasspathEntry> myClasspathEntries;
+
+
+ public BuildScriptClasspathData(@NotNull ProjectSystemId owner, @NotNull List<ClasspathEntry> classpathEntries) {
+ super(owner);
+ myClasspathEntries = classpathEntries;
+ }
+
+ @NotNull
+ public List<ClasspathEntry> getClasspathEntries() {
+ return myClasspathEntries;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/ClasspathEntry.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/ClasspathEntry.java
new file mode 100644
index 000000000000..fa0959ff74ad
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/ClasspathEntry.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.model.data;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/23/13
+ */
+public class ClasspathEntry implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @NotNull
+ private final File myClassesFile;
+
+ @Nullable
+ private final File mySourcesFile;
+
+ @Nullable
+ private final File myJavadocFile;
+
+ public ClasspathEntry(@NotNull File classesFile, @Nullable File sourcesFile, @Nullable File javadocFile) {
+ myClassesFile = classesFile;
+ mySourcesFile = sourcesFile;
+ myJavadocFile = javadocFile;
+ }
+
+ @NotNull
+ public File getClassesFile() {
+ return myClassesFile;
+ }
+
+ @Nullable
+ public File getSourcesFile() {
+ return mySourcesFile;
+ }
+
+ @Nullable
+ public File getJavadocFile() {
+ return myJavadocFile;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ClasspathEntry)) return false;
+
+ ClasspathEntry entry = (ClasspathEntry)o;
+
+ if (!FileUtil.filesEqual(myClassesFile, entry.myClassesFile)) return false;
+ if (!FileUtil.filesEqual(myJavadocFile, entry.myJavadocFile)) return false;
+ if (!FileUtil.filesEqual(mySourcesFile, entry.mySourcesFile)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = FileUtil.fileHashCode(myClassesFile);
+ result = 31 * result + FileUtil.fileHashCode(mySourcesFile);
+ result = 31 * result + FileUtil.fileHashCode(myJavadocFile);
+ return result;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/BuildScriptClasspathModelImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/BuildScriptClasspathModelImpl.java
new file mode 100644
index 000000000000..b59241181110
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/BuildScriptClasspathModelImpl.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.model.internal;
+
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel;
+import org.jetbrains.plugins.gradle.model.ClasspathEntryModel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/20/13
+ */
+public class BuildScriptClasspathModelImpl implements BuildScriptClasspathModel {
+
+ private final List<ClasspathEntryModel> myClasspathEntries;
+
+ public BuildScriptClasspathModelImpl() {
+ myClasspathEntries = new ArrayList<ClasspathEntryModel>();
+ }
+
+ @Override
+ public DomainObjectSet<? extends ClasspathEntryModel> getClasspath() {
+ return ImmutableDomainObjectSet.of(myClasspathEntries);
+ }
+
+ public void add(@NotNull ClasspathEntryModel classpathEntryModel) {
+ myClasspathEntries.add(classpathEntryModel);
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ClasspathEntryModelImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ClasspathEntryModelImpl.java
new file mode 100644
index 000000000000..06188100d4ab
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ClasspathEntryModelImpl.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.model.internal;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.ClasspathEntryModel;
+
+import java.io.File;
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/20/13
+ */
+public class ClasspathEntryModelImpl implements ClasspathEntryModel, Serializable {
+ @NotNull
+ private final File classesFile;
+ @Nullable
+ private final File sourcesFile;
+ @Nullable
+ private final File javadocFile;
+
+ public ClasspathEntryModelImpl(@NotNull File classesFile, @Nullable File sourcesFile, @Nullable File javadocFile) {
+ this.classesFile = classesFile;
+ this.sourcesFile = sourcesFile;
+ this.javadocFile = javadocFile;
+ }
+
+ @NotNull
+ @Override
+ public File getClassesFile() {
+ return classesFile;
+ }
+
+ @Nullable
+ @Override
+ public File getSourcesFile() {
+ return sourcesFile;
+ }
+
+ @Nullable
+ @Override
+ public File getJavadocFile() {
+ return javadocFile;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/buildSrcInit.gradle b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/buildSrcInit.gradle
new file mode 100644
index 000000000000..91140f2fcec6
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/buildSrcInit.gradle
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+allprojects { project ->
+ if(project.name == 'buildSrc') {
+ apply plugin: 'groovy'
+ dependencies {
+ compile gradleApi()
+ compile localGroovy()
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/init.gradle b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/init.gradle
index a788cb85d83d..4f382fd42590 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/init.gradle
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/init.gradle
@@ -34,6 +34,10 @@ try {
URLClassLoader classLoader = new URLClassLoader(urls, getClass().classLoader)
Class modelClass = classLoader.loadClass('org.jetbrains.plugins.gradle.model.internal.ExtraModelBuilder')
allprojects {
+ apply plugin: 'idea'
+ idea.module.ext.set('resourceDirs', [])
+ idea.module.ext.set('testResourceDirs', [])
+
ext.jetExtraModelBuilderClass = modelClass
apply plugin: JetGradlePlugin
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleBuildClasspathManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleBuildClasspathManager.java
new file mode 100644
index 000000000000..512bd70ecfe0
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleBuildClasspathManager.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.service;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.externalSystem.ExternalSystemManager;
+import com.intellij.openapi.externalSystem.model.project.ExternalModuleBuildClasspathPojo;
+import com.intellij.openapi.externalSystem.model.project.ExternalProjectBuildClasspathPojo;
+import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemLocalSettings;
+import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.JarFileSystem;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.util.GradleConstants;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/27/13
+ */
+public class GradleBuildClasspathManager {
+ @NotNull
+ private final Project myProject;
+
+ @NotNull
+ private volatile List<VirtualFile> allFilesCache;
+
+ @NotNull
+ private final AtomicReference<Map<String/*module path*/, List<VirtualFile> /*module build classpath*/>> myClasspathMap
+ = new AtomicReference<Map<String, List<VirtualFile>>>(new HashMap<String, List<VirtualFile>>());
+
+ public GradleBuildClasspathManager(@NotNull Project project) {
+ myProject = project;
+ reload();
+ }
+
+ @NotNull
+ public static GradleBuildClasspathManager getInstance(@NotNull Project project) {
+ return ServiceManager.getService(project, GradleBuildClasspathManager.class);
+ }
+
+ public void reload() {
+ ExternalSystemManager<?, ?, ?, ?, ?> manager = ExternalSystemApiUtil.getManager(GradleConstants.SYSTEM_ID);
+ assert manager != null;
+ AbstractExternalSystemLocalSettings localSettings = manager.getLocalSettingsProvider().fun(myProject);
+
+ Map<String/*module path*/, List<VirtualFile> /*module build classpath*/> map = ContainerUtil.newHashMap();
+
+ final LocalFileSystem localFileSystem = LocalFileSystem.getInstance();
+ final JarFileSystem jarFileSystem = JarFileSystem.getInstance();
+ for (ExternalProjectBuildClasspathPojo projectBuildClasspathPojo : localSettings.getProjectBuildClasspath().values()) {
+ List<VirtualFile> projectBuildClasspath = ContainerUtil.newArrayList();
+ for (String path : projectBuildClasspathPojo.getProjectBuildClasspath()) {
+ final VirtualFile virtualFile = localFileSystem.refreshAndFindFileByPath(path);
+ if (virtualFile != null) {
+ ContainerUtil.addIfNotNull(
+ projectBuildClasspath, virtualFile.isDirectory() ? virtualFile : jarFileSystem.getJarRootForLocalFile(virtualFile));
+ }
+ }
+
+ for (ExternalModuleBuildClasspathPojo moduleBuildClasspathPojo : projectBuildClasspathPojo.getModulesBuildClasspath().values()) {
+ List<VirtualFile> moduleBuildClasspath = ContainerUtil.newArrayList(projectBuildClasspath);
+ for (String path : moduleBuildClasspathPojo.getEntries()) {
+ final VirtualFile virtualFile = localFileSystem.refreshAndFindFileByPath(path);
+ if (virtualFile != null) {
+ ContainerUtil.addIfNotNull(moduleBuildClasspath, jarFileSystem.getJarRootForLocalFile(virtualFile));
+ }
+ }
+
+ map.put(moduleBuildClasspathPojo.getPath(), moduleBuildClasspath);
+ }
+ }
+
+ myClasspathMap.set(map);
+
+ Set<VirtualFile> set = new LinkedHashSet<VirtualFile>();
+ for (List<VirtualFile> virtualFiles : myClasspathMap.get().values()) {
+ set.addAll(virtualFiles);
+ }
+ allFilesCache = ContainerUtil.newArrayList(set);
+ }
+
+ @NotNull
+ public List<VirtualFile> getAllClasspathEntries() {
+ return allFilesCache;
+ }
+
+ @NotNull
+ public List<VirtualFile> getModuleClasspathEntries(@NotNull String externalModulePath) {
+ List<VirtualFile> virtualFiles = myClasspathMap.get().get(externalModulePath);
+ return virtualFiles == null ? Collections.<VirtualFile>emptyList() : virtualFiles;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleInstallationManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleInstallationManager.java
index 715db5a94015..95fdb0a7f244 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleInstallationManager.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleInstallationManager.java
@@ -10,6 +10,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import org.gradle.StartParameter;
@@ -49,6 +50,9 @@ public class GradleInstallationManager {
public static final Pattern GRADLE_JAR_FILE_PATTERN;
public static final Pattern ANY_GRADLE_JAR_FILE_PATTERN;
+ public static final Pattern ANT_JAR_PATTERN = Pattern.compile("ant(-(.*))?\\.jar");
+ public static final Pattern IVY_JAR_PATTERN = Pattern.compile("ivy(-(.*))?\\.jar");
+
private static final String[] GRADLE_START_FILE_NAMES;
@NonNls private static final String GRADLE_ENV_PROPERTY_NAME;
@@ -375,57 +379,83 @@ public class GradleInstallationManager {
*/
@Nullable
public List<VirtualFile> getClassRoots(@Nullable Project project) {
+ List<File> files = getClassRoots(project, null);
+ if(files == null) return null;
+ final LocalFileSystem localFileSystem = LocalFileSystem.getInstance();
+ final JarFileSystem jarFileSystem = JarFileSystem.getInstance();
+ return ContainerUtil.mapNotNull(files, new Function<File, VirtualFile>() {
+ @Override
+ public VirtualFile fun(File file) {
+ final VirtualFile virtualFile = localFileSystem.refreshAndFindFileByIoFile(file);
+ return virtualFile != null ? jarFileSystem.getJarRootForLocalFile(virtualFile) : null;
+ }
+ });
+ }
+
+ @Nullable
+ public List<File> getClassRoots(@Nullable Project project, @Nullable String rootProjectPath) {
if (project == null) return null;
- for (Module module : myPlatformFacade.getModules(project)) {
- String rootProjectPath = module.getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY);
- if (StringUtil.isEmpty(rootProjectPath)) {
- continue;
+ if(rootProjectPath == null) {
+ for (Module module : myPlatformFacade.getModules(project)) {
+ rootProjectPath = module.getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY);
+ List<File> result = findGradleSdkClasspath(project, rootProjectPath);
+ if(!result.isEmpty()) return result;
}
- File gradleHome = getGradleHome(module.getProject(), rootProjectPath);
+ } else {
+ return findGradleSdkClasspath(project, rootProjectPath);
+ }
- if (gradleHome == null || !gradleHome.isDirectory()) {
- continue;
- }
+ return null;
+ }
- final Collection<File> libraries = getAllLibraries(gradleHome);
- if (libraries == null) {
- continue;
- }
- final LocalFileSystem localFileSystem = LocalFileSystem.getInstance();
- final JarFileSystem jarFileSystem = JarFileSystem.getInstance();
- List<VirtualFile> result = new ArrayList<VirtualFile>();
- for (File file : libraries) {
- if (ANY_GRADLE_JAR_FILE_PATTERN.matcher(file.getName()).matches() || GroovyConfigUtils.matchesGroovyAll(file.getName())) {
- final VirtualFile virtualFile = localFileSystem.refreshAndFindFileByIoFile(file);
- if (virtualFile != null) {
- ContainerUtil.addIfNotNull(result, jarFileSystem.getJarRootForLocalFile(virtualFile));
- }
- }
- }
+ private List<File> findGradleSdkClasspath(Project project, String rootProjectPath) {
+ List<File> result = new ArrayList<File>();
- File src = new File(gradleHome, "src");
- if (src.isDirectory()) {
- if(new File(src, "org").isDirectory()) {
- addRoots(localFileSystem, result, src);
- } else {
- addRoots(localFileSystem, result, src.listFiles());
- }
- }
+ if (StringUtil.isEmpty(rootProjectPath)) return result;
+
+ File gradleHome = getGradleHome(project, rootProjectPath);
+ if (gradleHome == null || !gradleHome.isDirectory()) {
return result;
}
- return null;
+
+ final Collection<File> libraries = getAllLibraries(gradleHome);
+ if (libraries == null) {
+ return result;
+ }
+
+ for (File file : libraries) {
+ if (isGradleBuildClasspathLibrary(file)) {
+ ContainerUtil.addIfNotNull(result, file);
+ }
+ }
+
+ File src = new File(gradleHome, "src");
+ if (src.isDirectory()) {
+ if(new File(src, "org").isDirectory()) {
+ addRoots(result, src);
+ } else {
+ addRoots(result, src.listFiles());
+ }
+ }
+
+ return result;
+ }
+
+ private boolean isGradleBuildClasspathLibrary(File file) {
+ String fileName = file.getName();
+ return ANY_GRADLE_JAR_FILE_PATTERN.matcher(fileName).matches()
+ || ANT_JAR_PATTERN.matcher(fileName).matches()
+ || IVY_JAR_PATTERN.matcher(fileName).matches()
+ || GroovyConfigUtils.matchesGroovyAll(fileName);
}
- private void addRoots(@NotNull LocalFileSystem localFileSystem, @NotNull List<VirtualFile> result, @Nullable File... files) {
- if(files == null) return;
+ private void addRoots(@NotNull List<File> result, @Nullable File... files) {
+ if (files == null) return;
for (File file : files) {
- if(file == null || !file.isDirectory()) continue;
- final VirtualFile virtualFile = localFileSystem.refreshAndFindFileByIoFile(file);
- if (virtualFile != null) {
- result.add(0, virtualFile);
- }
+ if (file == null || !file.isDirectory()) continue;
+ result.add(0, file);
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
index 0a28fccd3347..b2eb6a0e089e 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
@@ -35,8 +35,10 @@ import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.roots.DependencyScope;
import com.intellij.openapi.util.KeyValue;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.util.BooleanFunction;
+import com.intellij.util.Function;
import com.intellij.util.PathUtil;
import com.intellij.util.PathsList;
import com.intellij.util.containers.ContainerUtil;
@@ -51,9 +53,9 @@ import org.gradle.tooling.model.idea.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.gradle.model.ExtIdeaContentRoot;
-import org.jetbrains.plugins.gradle.model.ModuleExtendedModel;
-import org.jetbrains.plugins.gradle.model.ProjectDependenciesModel;
+import org.jetbrains.plugins.gradle.model.*;
+import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData;
+import org.jetbrains.plugins.gradle.model.data.ClasspathEntry;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import org.jetbrains.plugins.gradle.util.GradleUtil;
@@ -132,14 +134,16 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
"Creating module data ('%s') with the external config path: '%s'", gradleModule.getGradleProject().getPath(), moduleConfigPath
));
}
- ModuleData moduleData = new ModuleData(gradleModule.getGradleProject().getPath(),
+
+ final String path = gradleModule.getGradleProject().getPath();
+ final ModuleData moduleData = new ModuleData(StringUtil.isEmpty(path) || ":".equals(path) ? moduleName : path,
GradleConstants.SYSTEM_ID,
StdModuleTypes.JAVA.getId(),
moduleName,
moduleConfigPath,
moduleConfigPath);
- ModuleExtendedModel moduleExtendedModel = resolverCtx.getExtraProject(gradleModule, ModuleExtendedModel.class);
+ final ModuleExtendedModel moduleExtendedModel = resolverCtx.getExtraProject(gradleModule, ModuleExtendedModel.class);
if (moduleExtendedModel != null) {
moduleData.setGroup(moduleExtendedModel.getGroup());
moduleData.setVersion(moduleExtendedModel.getVersion());
@@ -150,6 +154,19 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
@Override
public void populateModuleExtraModels(@NotNull IdeaModule gradleModule, @NotNull DataNode<ModuleData> ideModule) {
+ BuildScriptClasspathModel buildScriptClasspathModel = resolverCtx.getExtraProject(gradleModule, BuildScriptClasspathModel.class);
+ if (buildScriptClasspathModel != null) {
+ List<ClasspathEntry> classpathEntries =
+ ContainerUtil.map(buildScriptClasspathModel.getClasspath(), new Function<ClasspathEntryModel, ClasspathEntry>() {
+ @Override
+ public ClasspathEntry fun(ClasspathEntryModel model) {
+ return new ClasspathEntry(model.getClassesFile(), model.getSourcesFile(), model.getJavadocFile());
+ }
+ });
+ BuildScriptClasspathData buildScriptClasspathData =
+ new BuildScriptClasspathData(GradleConstants.SYSTEM_ID, classpathEntries);
+ ideModule.createChild(BuildScriptClasspathData.KEY, buildScriptClasspathData);
+ }
}
@Override
@@ -289,7 +306,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
@NotNull
@Override
public Set<Class> getExtraProjectModelClasses() {
- return ContainerUtil.<Class>set(ModuleExtendedModel.class, ProjectDependenciesModel.class);
+ return ContainerUtil.<Class>set(ModuleExtendedModel.class, ProjectDependenciesModel.class, BuildScriptClasspathModel.class);
}
@NotNull
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java
index e4ae7b389306..39dfe9afdbe5 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java
@@ -355,22 +355,46 @@ public class GradleExecutionHelper {
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
- public static void setInitScript(LongRunningOperation longRunningOperation) {
+ public static boolean setInitScript(@NotNull LongRunningOperation longRunningOperation, boolean isBuildSrcProject) {
try {
InputStream stream = GradleProjectResolver.class.getResourceAsStream("/org/jetbrains/plugins/gradle/model/internal/init.gradle");
- if (stream == null) return;
+ if (stream == null) return isBuildSrcProject;
String jarPath = PathUtil.getCanonicalPath(PathUtil.getJarPathForClass(GradleProjectResolver.class));
String s = FileUtil.loadTextAndClose(stream).replace("${JAR_PATH}", jarPath);
+ if(isBuildSrcProject) {
+ String buildSrcDefaultInitScript = getBuildSrcDefaultInitScript();
+ if(buildSrcDefaultInitScript == null) return false;
+ s += buildSrcDefaultInitScript;
+ }
+
final File tempFile = FileUtil.createTempFile("ijinit", '.' + GradleConstants.EXTENSION, true);
FileUtil.writeToFile(tempFile, s);
String[] buildExecutorArgs = new String[]{"--init-script", tempFile.getAbsolutePath()};
longRunningOperation.withArguments(buildExecutorArgs);
+
+ return true;
+ }
+ catch (Exception e) {
+ LOG.warn("Can't use IJ gradle init script", e);
+ return false;
+ }
+ }
+
+ @Nullable
+ @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
+ public static String getBuildSrcDefaultInitScript() {
+ try {
+ InputStream stream = GradleProjectResolver.class.getResourceAsStream("/org/jetbrains/plugins/gradle/model/internal/buildSrcInit.gradle");
+ if (stream == null) return null;
+
+ return FileUtil.loadTextAndClose(stream);
}
catch (Exception e) {
LOG.warn("Can't use IJ gradle init script", e);
+ return null;
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
index 1b1997b048a2..29a27ba94c0f 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
@@ -32,6 +32,7 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemDebugEnvironment;
import com.intellij.openapi.util.KeyValue;
import com.intellij.openapi.util.Pair;
+import com.intellij.util.BooleanFunction;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
@@ -52,6 +53,7 @@ import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import org.jetbrains.plugins.gradle.util.GradleEnvironment;
+import java.io.File;
import java.util.*;
/**
@@ -110,19 +112,19 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
projectResolverChain = new BaseGradleProjectResolverExtension();
}
- return myHelper.execute(projectPath, settings, new Function<ProjectConnection, DataNode<ProjectData>>() {
- @Override
- public DataNode<ProjectData> fun(ProjectConnection connection) {
- try {
- return doResolveProjectInfo(
- new ProjectResolverContext(id, projectPath, settings, connection, listener, isPreviewMode), projectResolverChain);
- }
- catch (RuntimeException e) {
- LOG.info("Gradle project resolve error", e);
- throw projectResolverChain.getUserFriendlyError(e, projectPath, null);
- }
- }
- });
+ final DataNode<ProjectData> resultProjectDataNode = myHelper.execute(
+ projectPath, settings,
+ new ProjectConnectionDataNodeFunction(
+ id, projectPath, settings, listener, isPreviewMode, projectResolverChain, false)
+ );
+
+ // auto-discover buildSrc project if needed
+ final String buildSrcProjectPath = projectPath + "/buildSrc";
+ handleBuildSrcProject(
+ resultProjectDataNode,
+ new ProjectConnectionDataNodeFunction(id, buildSrcProjectPath, settings, listener, isPreviewMode, projectResolverChain, true)
+ );
+ return resultProjectDataNode;
}
@Override
@@ -133,7 +135,8 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
@NotNull
private DataNode<ProjectData> doResolveProjectInfo(@NotNull final ProjectResolverContext resolverCtx,
- @NotNull final GradleProjectResolverExtension projectResolverChain)
+ @NotNull final GradleProjectResolverExtension projectResolverChain,
+ boolean isBuildSrcProject)
throws IllegalArgumentException, IllegalStateException {
final ProjectImportAction projectImportAction = new ProjectImportAction(resolverCtx.isPreviewMode());
@@ -162,7 +165,7 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
// TODO [vlad] remove the check
if (!GradleEnvironment.DISABLE_ENHANCED_TOOLING_API) {
- GradleExecutionHelper.setInitScript(buildActionExecutor);
+ GradleExecutionHelper.setInitScript(buildActionExecutor, isBuildSrcProject);
}
ProjectImportAction.AllModels allModels;
@@ -242,8 +245,10 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
projectResolverChain.populateModuleContentRoots(ideaModule, moduleDataNode);
projectResolverChain.populateModuleCompileOutputSettings(ideaModule, moduleDataNode);
projectResolverChain.populateModuleDependencies(ideaModule, moduleDataNode, projectDataNode);
- final Collection<TaskData> moduleTasks = projectResolverChain.populateModuleTasks(ideaModule, moduleDataNode, projectDataNode);
- allTasks.addAll(moduleTasks);
+ if(!isBuildSrcProject) {
+ final Collection<TaskData> moduleTasks = projectResolverChain.populateModuleTasks(ideaModule, moduleDataNode, projectDataNode);
+ allTasks.addAll(moduleTasks);
+ }
}
// populate root project tasks
@@ -275,4 +280,78 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
return null;
}
}
+
+ private void handleBuildSrcProject(@NotNull final DataNode<ProjectData> resultProjectDataNode,
+ @NotNull final ProjectConnectionDataNodeFunction projectConnectionDataNodeFunction) {
+
+ if (projectConnectionDataNodeFunction.myIsPreviewMode || GradleEnvironment.DISABLE_ENHANCED_TOOLING_API ||
+ !new File(projectConnectionDataNodeFunction.myProjectPath).isDirectory()) return;
+
+ final DataNode<ModuleData> buildSrcModuleDataNode =
+ ExternalSystemApiUtil.find(resultProjectDataNode, ProjectKeys.MODULE, new BooleanFunction<DataNode<ModuleData>>() {
+ @Override
+ public boolean fun(DataNode<ModuleData> node) {
+ return projectConnectionDataNodeFunction.myProjectPath.equals(node.getData().getLinkedExternalProjectPath());
+ }
+ });
+
+ // check if buildSrc project was already exposed in settings.gradle file
+ if (buildSrcModuleDataNode != null) return;
+
+ final DataNode<ProjectData> buildSrcProjectDataDataNode = myHelper.execute(
+ projectConnectionDataNodeFunction.myProjectPath, projectConnectionDataNodeFunction.mySettings, projectConnectionDataNodeFunction);
+
+ if (buildSrcProjectDataDataNode != null) {
+ final DataNode<ModuleData> moduleDataNode = ExternalSystemApiUtil.find(buildSrcProjectDataDataNode, ProjectKeys.MODULE);
+ if (moduleDataNode != null) {
+ for (DataNode<LibraryData> libraryDataNode : ExternalSystemApiUtil.findAll(buildSrcProjectDataDataNode, ProjectKeys.LIBRARY)) {
+ resultProjectDataNode.createChild(libraryDataNode.getKey(), libraryDataNode.getData());
+ }
+
+ final DataNode<ModuleData> newModuleDataNode = resultProjectDataNode.createChild(ProjectKeys.MODULE, moduleDataNode.getData());
+ for (DataNode node : moduleDataNode.getChildren()) {
+ newModuleDataNode.createChild(node.getKey(), node.getData());
+ }
+ }
+ }
+ }
+
+ private class ProjectConnectionDataNodeFunction implements Function<ProjectConnection, DataNode<ProjectData>> {
+ @NotNull private final ExternalSystemTaskId myId;
+ @NotNull private final String myProjectPath;
+ @Nullable private final GradleExecutionSettings mySettings;
+ @NotNull private final ExternalSystemTaskNotificationListener myListener;
+ private final boolean myIsPreviewMode;
+ @NotNull private final GradleProjectResolverExtension myProjectResolverChain;
+ private final boolean myIsBuildSrcProject;
+
+ public ProjectConnectionDataNodeFunction(@NotNull ExternalSystemTaskId id,
+ @NotNull String projectPath,
+ @Nullable GradleExecutionSettings settings,
+ @NotNull ExternalSystemTaskNotificationListener listener,
+ boolean isPreviewMode,
+ @NotNull GradleProjectResolverExtension projectResolverChain,
+ boolean isBuildSrcProject) {
+ myId = id;
+ myProjectPath = projectPath;
+ mySettings = settings;
+ myListener = listener;
+ myIsPreviewMode = isPreviewMode;
+ myProjectResolverChain = projectResolverChain;
+ myIsBuildSrcProject = isBuildSrcProject;
+ }
+
+ @Override
+ public DataNode<ProjectData> fun(ProjectConnection connection) {
+ try {
+ return doResolveProjectInfo(
+ new ProjectResolverContext(myId, myProjectPath, mySettings, connection, myListener, myIsPreviewMode),
+ myProjectResolverChain, myIsBuildSrcProject);
+ }
+ catch (RuntimeException e) {
+ LOG.info("Gradle project resolve error", e);
+ throw myProjectResolverChain.getUserFriendlyError(e, myProjectPath, null);
+ }
+ }
+ }
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java
index 623a79736028..fc4805e81058 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java
@@ -30,6 +30,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.service.GradleBuildClasspathManager;
import org.jetbrains.plugins.gradle.service.project.wizard.GradleProjectImportBuilder;
import org.jetbrains.plugins.gradle.service.project.wizard.GradleProjectImportProvider;
import org.jetbrains.plugins.gradle.settings.GradleSettings;
@@ -52,9 +53,14 @@ public class GradleStartupActivity implements StartupActivity {
@Override
public void runActivity(@NotNull Project project) {
+ configureBuildClasspath(project);
showNotificationForUnlinkedGradleProject(project);
}
+ private static void configureBuildClasspath(@NotNull final Project project) {
+ GradleBuildClasspathManager.getInstance(project).reload();
+ }
+
private static void showNotificationForUnlinkedGradleProject(@NotNull final Project project) {
if (!PropertiesComponent.getInstance(project).getBoolean(SHOW_UNLINKED_GRADLE_POPUP, true)
|| !GradleSettings.getInstance(project).getLinkedProjectsSettings().isEmpty()
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/BuildClasspathModuleGradleDataService.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/BuildClasspathModuleGradleDataService.java
new file mode 100644
index 000000000000..907f2903ef09
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/BuildClasspathModuleGradleDataService.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.service.project.data;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.externalSystem.ExternalSystemManager;
+import com.intellij.openapi.externalSystem.model.DataNode;
+import com.intellij.openapi.externalSystem.model.Key;
+import com.intellij.openapi.externalSystem.model.ProjectKeys;
+import com.intellij.openapi.externalSystem.model.project.ExternalModuleBuildClasspathPojo;
+import com.intellij.openapi.externalSystem.model.project.ExternalProjectBuildClasspathPojo;
+import com.intellij.openapi.externalSystem.model.project.ModuleData;
+import com.intellij.openapi.externalSystem.model.project.ProjectData;
+import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataService;
+import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemLocalSettings;
+import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
+import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
+import com.intellij.openapi.externalSystem.util.Order;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.FactoryMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData;
+import org.jetbrains.plugins.gradle.model.data.ClasspathEntry;
+import org.jetbrains.plugins.gradle.service.GradleBuildClasspathManager;
+import org.jetbrains.plugins.gradle.service.GradleInstallationManager;
+import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
+import org.jetbrains.plugins.gradle.settings.GradleSettings;
+import org.jetbrains.plugins.gradle.util.GradleConstants;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 8/27/13
+ */
+@Order(ExternalSystemConstants.UNORDERED)
+public class BuildClasspathModuleGradleDataService implements ProjectDataService<BuildScriptClasspathData, Module> {
+
+ @NotNull
+ @Override
+ public Key<BuildScriptClasspathData> getTargetDataKey() {
+ return BuildScriptClasspathData.KEY;
+ }
+
+ @Override
+ public void importData(@NotNull final Collection<DataNode<BuildScriptClasspathData>> toImport,
+ @NotNull final Project project,
+ boolean synchronous) {
+ if (toImport.isEmpty()) {
+ return;
+ }
+ if (!project.isInitialized()) {
+ return;
+ }
+
+ final GradleInstallationManager gradleInstallationManager = ServiceManager.getService(GradleInstallationManager.class);
+
+ ExternalSystemManager<?, ?, ?, ?, ?> manager = ExternalSystemApiUtil.getManager(GradleConstants.SYSTEM_ID);
+ assert manager != null;
+ AbstractExternalSystemLocalSettings localSettings = manager.getLocalSettingsProvider().fun(project);
+
+ //noinspection MismatchedQueryAndUpdateOfCollection
+ Map<String/* externalProjectPath */, Set<String>> externalProjectGradleSdkLibs = new FactoryMap<String, Set<String>>() {
+ @Nullable
+ @Override
+ protected Set<String> create(String externalProjectPath) {
+ GradleProjectSettings settings = GradleSettings.getInstance(project).getLinkedProjectSettings(externalProjectPath);
+ if (settings == null || settings.getDistributionType() == null) return null;
+
+ final Set<String> gradleSdkLibraries = ContainerUtil.newHashSet();
+ File gradleHome =
+ gradleInstallationManager.getGradleHome(settings.getDistributionType(), externalProjectPath, settings.getGradleHome());
+ if (gradleHome != null && gradleHome.isDirectory()) {
+
+ final Collection<File> libraries = gradleInstallationManager.getClassRoots(project, externalProjectPath);
+ if (libraries != null) {
+ for (File library : libraries) {
+ gradleSdkLibraries.add(FileUtil.toCanonicalPath(library.getPath()));
+ }
+ }
+ }
+ return gradleSdkLibraries;
+ }
+ };
+
+ for (final DataNode<BuildScriptClasspathData> node : toImport) {
+ if (GradleConstants.SYSTEM_ID.equals(node.getData().getOwner())) {
+
+
+ DataNode<ProjectData> projectDataNode = ExternalSystemApiUtil.findParent(node, ProjectKeys.PROJECT);
+ assert projectDataNode != null;
+
+ String linkedExternalProjectPath = projectDataNode.getData().getLinkedExternalProjectPath();
+ DataNode<ModuleData> moduleDataNode = ExternalSystemApiUtil.findParent(node, ProjectKeys.MODULE);
+ if (moduleDataNode == null) continue;
+
+ String externalModulePath = moduleDataNode.getData().getLinkedExternalProjectPath();
+ GradleProjectSettings settings = GradleSettings.getInstance(project).getLinkedProjectSettings(linkedExternalProjectPath);
+ if (settings == null || settings.getDistributionType() == null) continue;
+
+ final Set<String> buildClasspath = ContainerUtil.newHashSet();
+ BuildScriptClasspathData buildScriptClasspathData = node.getData();
+ for (ClasspathEntry classpathEntry : buildScriptClasspathData.getClasspathEntries()) {
+ if (classpathEntry.getSourcesFile() != null) {
+ buildClasspath.add(FileUtil.toCanonicalPath(classpathEntry.getSourcesFile().getPath()));
+ }
+ else {
+ buildClasspath.add(FileUtil.toCanonicalPath(classpathEntry.getClassesFile().getPath()));
+ }
+ }
+
+ ExternalProjectBuildClasspathPojo projectBuildClasspathPojo =
+ localSettings.getProjectBuildClasspath().get(linkedExternalProjectPath);
+ if (projectBuildClasspathPojo == null) {
+ projectBuildClasspathPojo = new ExternalProjectBuildClasspathPojo(
+ moduleDataNode.getData().getExternalName(),
+ ContainerUtil.<String>newArrayList(),
+ ContainerUtil.<String, ExternalModuleBuildClasspathPojo>newHashMap());
+ localSettings.getProjectBuildClasspath().put(linkedExternalProjectPath, projectBuildClasspathPojo);
+ }
+
+ List<String> projectBuildClasspath = ContainerUtil.newArrayList(externalProjectGradleSdkLibs.get(linkedExternalProjectPath));
+ // add main java root of buildSrc project
+ projectBuildClasspath.add(linkedExternalProjectPath + "/buildSrc/src/main/java");
+ // add main groovy root of buildSrc project
+ projectBuildClasspath.add(linkedExternalProjectPath + "/buildSrc/src/main/groovy");
+
+ projectBuildClasspathPojo.setProjectBuildClasspath(projectBuildClasspath);
+ projectBuildClasspathPojo.getModulesBuildClasspath().put(
+ externalModulePath, new ExternalModuleBuildClasspathPojo(externalModulePath, ContainerUtil.newArrayList(buildClasspath)));
+ }
+ }
+
+ GradleBuildClasspathManager.getInstance(project).reload();
+ }
+
+ @Override
+ public void removeData(@NotNull Collection<? extends Module> toRemove, @NotNull Project project, boolean synchronous) {
+ }
+}
diff --git a/plugins/gradle/testData/testAddMavenDependencyInEmptyFile.gradle b/plugins/gradle/testData/testAddMavenDependencyInEmptyFile.gradle
index f90814d636ed..e69de29bb2d1 100644
--- a/plugins/gradle/testData/testAddMavenDependencyInEmptyFile.gradle
+++ b/plugins/gradle/testData/testAddMavenDependencyInEmptyFile.gradle
@@ -1 +0,0 @@
-//empty file \ No newline at end of file
diff --git a/plugins/gradle/testData/testAddMavenDependencyInEmptyFile_after.gradle b/plugins/gradle/testData/testAddMavenDependencyInEmptyFile_after.gradle
index aa2892d73dc4..54c09742fd5c 100644
--- a/plugins/gradle/testData/testAddMavenDependencyInEmptyFile_after.gradle
+++ b/plugins/gradle/testData/testAddMavenDependencyInEmptyFile_after.gradle
@@ -1,4 +1,3 @@
-//empty file
dependencies{
compile 'testGroupId:testArtifactId:1.0'
} \ No newline at end of file
diff --git a/plugins/gradle/testData/testDefaultDependenciesModel/build.gradle b/plugins/gradle/testData/testDefaultDependenciesModel/build.gradle
index 849b1b486dd2..a6c9dde56871 100644
--- a/plugins/gradle/testData/testDefaultDependenciesModel/build.gradle
+++ b/plugins/gradle/testData/testDefaultDependenciesModel/build.gradle
@@ -4,8 +4,8 @@ allprojects{
apply plugin: 'java'
}
-project(":group2:subgroup11:project") {
+project("dependentProject") {
dependencies {
- compile project(":project")
+ compile project(":dependencyProject")
}
} \ No newline at end of file
diff --git a/plugins/gradle/testData/testDefaultDependenciesModel/settings.gradle b/plugins/gradle/testData/testDefaultDependenciesModel/settings.gradle
index cf870fe6d6d1..ef853f062e1c 100644
--- a/plugins/gradle/testData/testDefaultDependenciesModel/settings.gradle
+++ b/plugins/gradle/testData/testDefaultDependenciesModel/settings.gradle
@@ -1,5 +1,4 @@
//noinspection GrPackage
-include 'group1:subgroup11:project'
-include 'group2:subgroup11:project'
-include 'project' \ No newline at end of file
+include 'dependencyProject'
+include 'dependentProject' \ No newline at end of file
diff --git a/plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/build.gradle b/plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/build.gradle
index 6f9afa4b8d09..73cb6a15b5cd 100644
--- a/plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/build.gradle
+++ b/plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/build.gradle
@@ -27,7 +27,7 @@ allprojects {
project(":service") {
dependencies {
- compile (project(':api'))
+ compile(project(':api'))
}
}
@@ -35,4 +35,21 @@ project(":api") {
dependencies {
provided(project(':lib'))
}
-} \ No newline at end of file
+}
+
+project(":withIdeaModelCustomisations") {
+ dependencies {
+ //compile 'org.slf4j:slf4j-api:1.7.5'
+ //testCompile 'junit:junit:4.11'
+
+ compile files("lib/someDep.jar")
+ testCompile files("lib/someTestDep.jar")
+ }
+
+ idea {
+ module {
+ scopes.COMPILE.plus += scopes.TEST.plus
+ scopes.TEST.plus = []
+ }
+ }
+}
diff --git a/plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/settings.gradle b/plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/settings.gradle
index 271f7343d37b..26ee835a9fb1 100644
--- a/plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/settings.gradle
+++ b/plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/settings.gradle
@@ -1,4 +1,5 @@
//noinspection GrPackage
include "lib"
include "api"
-include "service" \ No newline at end of file
+include "service"
+include "withIdeaModelCustomisations" \ No newline at end of file
diff --git a/plugins/gradle/testData/testGradleSourcesSetsInterpretation/build.gradle b/plugins/gradle/testData/testGradleSourcesSetsInterpretation/build.gradle
new file mode 100644
index 000000000000..8c7584942858
--- /dev/null
+++ b/plugins/gradle/testData/testGradleSourcesSetsInterpretation/build.gradle
@@ -0,0 +1,74 @@
+//noinspection GrPackage
+
+project("defaultJavaModule") {
+ apply plugin: "java"
+}
+
+project("moduleWithSourceSetDirBothAsResourceAndJava") {
+ apply plugin: "java"
+
+ sourceSets.main.resources.srcDir 'src/main/java'
+ sourceSets.test.resources.srcDir 'src/test/java'
+}
+
+project("moduleWithCustomSourceSet") {
+ apply plugin: "java"
+
+ sourceSets {
+ custom
+ }
+
+ sourceSets.custom.java.srcDir 'src/custom/java'
+}
+
+project("withIntegrationTests") {
+ apply plugin: 'java'
+
+ sourceSets {
+ integrationTest {
+ java.srcDir file('src/integration-test/java')
+ resources.srcDir file('src/integration-test/resources')
+ }
+ }
+
+ dependencies {
+ integrationTestCompile sourceSets.main.output
+ integrationTestCompile configurations.testCompile
+ integrationTestCompile sourceSets.test.output
+ integrationTestRuntime configurations.testRuntime
+ }
+
+ //noinspection GrUnresolvedAccess
+ task integrationTest(type: Test, dependsOn: jar) {
+ testClassesDir = sourceSets.integrationTest.output.classesDir
+ classpath = sourceSets.integrationTest.runtimeClasspath
+ }
+
+ check.dependsOn integrationTest
+}
+
+project("withIdeaPluginCustomization1") {
+ apply plugin: 'java'
+
+ idea {
+ module {
+ testSourceDirs += file('src/intTest/java')
+ testSourceDirs += file('src/intTest/resources')
+ excludeDirs += file('some-extra-exclude-folder')
+ }
+ }
+}
+
+// see http://youtrack.jetbrains.com/issue/IDEA-119365
+project("withIdeaPluginCustomization2") {
+ apply plugin: 'java'
+
+ idea {
+ module {
+ sourceDirs += testSourceDirs
+ testSourceDirs = []
+ ext.resourceDirs += file('some-extra-resource-folder')
+ ext.testResourceDirs += file('some-extra-test-resource-folder')
+ }
+ }
+}
diff --git a/plugins/gradle/testData/testGradleSourcesSetsInterpretation/settings.gradle b/plugins/gradle/testData/testGradleSourcesSetsInterpretation/settings.gradle
new file mode 100644
index 000000000000..4f7ab785f8fd
--- /dev/null
+++ b/plugins/gradle/testData/testGradleSourcesSetsInterpretation/settings.gradle
@@ -0,0 +1,8 @@
+//noinspection GrPackage
+
+include 'defaultJavaModule'
+include 'moduleWithSourceSetDirBothAsResourceAndJava'
+include 'moduleWithCustomSourceSet'
+include 'withIntegrationTests'
+include 'withIdeaPluginCustomization1'
+include 'withIdeaPluginCustomization2' \ No newline at end of file
diff --git a/plugins/gradle/testData/testModelBuildScriptClasspathBuilder/build.gradle b/plugins/gradle/testData/testModelBuildScriptClasspathBuilder/build.gradle
new file mode 100644
index 000000000000..5b09fca15f4d
--- /dev/null
+++ b/plugins/gradle/testData/testModelBuildScriptClasspathBuilder/build.gradle
@@ -0,0 +1,9 @@
+//noinspection GrPackage
+
+project("moduleWithAdditionalClasspath") {
+ buildscript {
+ dependencies {
+ classpath files("lib/someDep.jar")
+ }
+ }
+}
diff --git a/plugins/gradle/testData/testModelBuildScriptClasspathBuilder/settings.gradle b/plugins/gradle/testData/testModelBuildScriptClasspathBuilder/settings.gradle
new file mode 100644
index 000000000000..02978875f494
--- /dev/null
+++ b/plugins/gradle/testData/testModelBuildScriptClasspathBuilder/settings.gradle
@@ -0,0 +1,4 @@
+//noinspection GrPackage
+
+include 'moduleWithoutAdditionalClasspath'
+include 'moduleWithAdditionalClasspath'
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/AbstractModelBuilderTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/AbstractModelBuilderTest.java
index 835d7305bd1b..0cdd2f032b78 100644
--- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/AbstractModelBuilderTest.java
+++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/AbstractModelBuilderTest.java
@@ -73,7 +73,7 @@ public abstract class AbstractModelBuilderTest {
final ProjectImportAction projectImportAction = new ProjectImportAction(true);
projectImportAction.addExtraProjectModelClasses(getModels());
BuildActionExecuter<ProjectImportAction.AllModels> buildActionExecutor = connection.action(projectImportAction);
- GradleExecutionHelper.setInitScript(buildActionExecutor);
+ GradleExecutionHelper.setInitScript(buildActionExecutor, false);
allModels = buildActionExecutor.run();
assertNotNull(allModels);
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelBuildScriptClasspathBuilderImplTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelBuildScriptClasspathBuilderImplTest.java
new file mode 100644
index 000000000000..d812d8df6a68
--- /dev/null
+++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelBuildScriptClasspathBuilderImplTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.model.builder;
+
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.idea.IdeaModule;
+import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel;
+import org.jetbrains.plugins.gradle.model.ClasspathEntryModel;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Set;
+
+import static junit.framework.Assert.*;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/16/14
+ */
+public class ModelBuildScriptClasspathBuilderImplTest extends AbstractModelBuilderTest {
+
+ @Test
+ public void testModelBuildScriptClasspathBuilder() throws Exception {
+ ModelBuildScriptClasspathBuilderImpl buildScriptClasspathBuilder = new ModelBuildScriptClasspathBuilderImpl();
+ assertTrue(buildScriptClasspathBuilder.canBuild("org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel"));
+
+ DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
+
+ List<BuildScriptClasspathModel> ideaModule =
+ ContainerUtil.mapNotNull(ideaModules, new Function<IdeaModule, BuildScriptClasspathModel>() {
+ @Override
+ public BuildScriptClasspathModel fun(IdeaModule module) {
+ BuildScriptClasspathModel classpathModel = allModels.getExtraProject(module, BuildScriptClasspathModel.class);
+
+ if (module.getName().equals("moduleWithAdditionalClasspath")) {
+ assertNotNull(classpathModel);
+ assertEquals(1, classpathModel.getClasspath().size());
+
+ ClasspathEntryModel classpathEntry = classpathModel.getClasspath().getAt(0);
+ assertEquals("someDep.jar", classpathEntry.getClassesFile().getName());
+ }
+ else if (module.getName().equals("moduleWithoutAdditionalClasspath") ||
+ module.getName().equals("testModelBuildScriptClasspathBuilder")) {
+ assertNotNull(classpathModel);
+ assertTrue(classpathModel.getClasspath().isEmpty());
+ }
+ else {
+ fail();
+ }
+
+ return classpathModel;
+ }
+ });
+
+ assertEquals(3, ideaModule.size());
+ }
+
+ @Override
+ protected Set<Class> getModels() {
+ return ContainerUtil.<Class>set(BuildScriptClasspathModel.class);
+ }
+}
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImplTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImplTest.java
index 6bb9b6f5eb9c..8cf50ef62af5 100644
--- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImplTest.java
+++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImplTest.java
@@ -15,19 +15,26 @@
*/
package org.jetbrains.plugins.gradle.model.builder;
-import com.intellij.openapi.util.Condition;
+import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.gradle.tooling.model.DomainObjectSet;
import org.gradle.tooling.model.idea.IdeaDependency;
import org.gradle.tooling.model.idea.IdeaModule;
import org.gradle.tooling.model.idea.IdeaModuleDependency;
+import org.gradle.tooling.model.idea.IdeaSingleEntryLibraryDependency;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
import org.jetbrains.plugins.gradle.model.ProjectDependenciesModel;
+import org.junit.Assert;
import org.junit.Test;
+import java.util.List;
import java.util.Set;
-import static org.junit.Assert.*;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* @author Vladislav.Soroka
@@ -42,17 +49,29 @@ public class ModelDependenciesBuilderImplTest extends AbstractModelBuilderTest {
DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
- IdeaModule ideaModule = ContainerUtil.find(ideaModules, new Condition<IdeaModule>() {
- @Override
- public boolean value(IdeaModule module) {
- return module.getName().equals("group2-subgroup11-project");
- }
- });
-
- assertNotNull(ideaModule);
+ final int modulesSize = 3;
+ assertEquals(modulesSize, ideaModules.size());
- DomainObjectSet<? extends IdeaDependency> dependencies = ideaModule.getDependencies();
- assertEquals(1, dependencies.size());
+ for (IdeaModule ideaModule : ideaModules) {
+ if (ideaModule.getName().equals("dependencyProject") ||
+ ideaModule.getName().equals("testDefaultDependenciesModel")) {
+ DomainObjectSet<? extends IdeaDependency> dependencies = ideaModule.getDependencies();
+ assertTrue((dependencies.isEmpty()));
+ }
+ else if (ideaModule.getName().equals("dependentProject")) {
+ DomainObjectSet<? extends IdeaDependency> dependencies = ideaModule.getDependencies();
+ assertEquals(1, dependencies.size());
+ assertTrue(dependencies.getAt(0) instanceof IdeaModuleDependency);
+ IdeaModuleDependency moduleDependency = (IdeaModuleDependency)dependencies.getAt(0);
+
+ assertEquals("dependencyProject", moduleDependency.getDependencyModule().getName());
+ assertEquals("COMPILE", moduleDependency.getScope().getScope());
+ assertTrue(moduleDependency.getExported());
+ }
+ else {
+ fail();
+ }
+ }
}
@Test
@@ -62,44 +81,71 @@ public class ModelDependenciesBuilderImplTest extends AbstractModelBuilderTest {
DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
- // test api module dependencies
- IdeaModule apiModule = ContainerUtil.find(ideaModules, new Condition<IdeaModule>() {
- @Override
- public boolean value(IdeaModule module) {
- return module.getName().equals("api");
+ final int modulesSize = 5;
+ assertEquals(modulesSize, ideaModules.size());
+
+ for (IdeaModule ideaModule : ideaModules) {
+ DomainObjectSet<? extends IdeaDependency> dependencies = ideaModule.getDependencies();
+ if (ideaModule.getName().equals("lib") ||
+ ideaModule.getName().equals("testGradleIdeaPluginPlusScopesDependenciesModel")) {
+ assertTrue((dependencies.isEmpty()));
}
- });
- assertNotNull(apiModule);
+ else if (ideaModule.getName().equals("api")) {
+ assertEquals(1, dependencies.size());
+ IdeaDependency libDependency = dependencies.getAt(0);
+ assertEquals(GradleDependencyScope.PROVIDED.getIdeaMappingName(), libDependency.getScope().getScope().toLowerCase());
+ assertTrue(libDependency instanceof IdeaModuleDependency);
+
+ IdeaModuleDependency libModuleDependency = (IdeaModuleDependency)libDependency;
+ assertNotNull(libModuleDependency.getDependencyModule());
+ assertEquals("lib", libModuleDependency.getDependencyModule().getName());
+ }
+ else if (ideaModule.getName().equals("service")) {
+ assertEquals(1, dependencies.size());
+ IdeaDependency apiDependency = dependencies.getAt(0);
+ assertEquals(GradleDependencyScope.COMPILE.getIdeaMappingName(), apiDependency.getScope().getScope().toLowerCase());
+ assertTrue(apiDependency instanceof IdeaModuleDependency);
+
+ IdeaModuleDependency apiModuleDependency = (IdeaModuleDependency)apiDependency;
+ assertNotNull(apiModuleDependency.getDependencyModule());
+ assertEquals("api", apiModuleDependency.getDependencyModule().getName());
+ }
+ else if (ideaModule.getName().equals("withIdeaModelCustomisations")) {
+
+ assertTrue(findLocalLibraries(dependencies, GradleDependencyScope.TEST_COMPILE.getIdeaMappingName()).isEmpty());
- DomainObjectSet<? extends IdeaDependency> dependencies = apiModule.getDependencies();
- assertEquals(1, dependencies.size());
- IdeaDependency libDependency = dependencies.getAt(0);
- assertEquals(GradleDependencyScope.PROVIDED.name(), libDependency.getScope().getScope());
- assertTrue(libDependency instanceof IdeaModuleDependency);
+ List<IdeaSingleEntryLibraryDependency> libraryDependencies =
+ findLocalLibraries(dependencies, GradleDependencyScope.COMPILE.getIdeaMappingName());
+ assertEquals(2, libraryDependencies.size());
- IdeaModuleDependency libModuleDependency = (IdeaModuleDependency)libDependency;
- assertNotNull(libModuleDependency.getDependencyModule());
- assertEquals("lib", libModuleDependency.getDependencyModule().getName());
+ IdeaSingleEntryLibraryDependency someDep = libraryDependencies.get(0);
+ assertEquals(GradleDependencyScope.COMPILE.getIdeaMappingName(), someDep.getScope().getScope().toLowerCase());
+ assertEquals("someDep.jar", someDep.getFile().getName());
+ IdeaSingleEntryLibraryDependency someTestDep = libraryDependencies.get(1);
+ assertEquals(GradleDependencyScope.COMPILE.getIdeaMappingName(), someTestDep.getScope().getScope().toLowerCase());
+ assertEquals("someTestDep.jar", someTestDep.getFile().getName());
+ }
+ else {
+ fail();
+ }
+ }
+ }
- // test service module dependencies
- IdeaModule serviceModule = ContainerUtil.find(ideaModules, new Condition<IdeaModule>() {
- @Override
- public boolean value(IdeaModule module) {
- return module.getName().equals("service");
+ @NotNull
+ private static List<IdeaSingleEntryLibraryDependency> findLocalLibraries(
+ @NotNull final DomainObjectSet<? extends IdeaDependency> dependencies, @NotNull final String scope) {
+ return ContainerUtil.mapNotNull(
+ dependencies,
+ new Function<IdeaDependency, IdeaSingleEntryLibraryDependency>() {
+ @Override
+ public IdeaSingleEntryLibraryDependency fun(IdeaDependency dependency) {
+ return dependency instanceof IdeaSingleEntryLibraryDependency && scope.equals(dependency.getScope().getScope().toLowerCase())
+ ? (IdeaSingleEntryLibraryDependency)dependency
+ : null;
+ }
}
- });
- assertNotNull(serviceModule);
-
- DomainObjectSet<? extends IdeaDependency> serviceModuleDependencies = serviceModule.getDependencies();
- assertEquals(1, serviceModuleDependencies.size());
- IdeaDependency apiDependency = serviceModuleDependencies.getAt(0);
- assertEquals(GradleDependencyScope.COMPILE.name(), apiDependency.getScope().getScope());
- assertTrue(apiDependency instanceof IdeaModuleDependency);
-
- IdeaModuleDependency apiModuleDependency = (IdeaModuleDependency)apiDependency;
- assertNotNull(apiModuleDependency.getDependencyModule());
- assertEquals("api", apiModuleDependency.getDependencyModule().getName());
+ );
}
@Override
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImplTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImplTest.java
new file mode 100644
index 000000000000..9694c9d37345
--- /dev/null
+++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImplTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.model.builder;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.idea.IdeaModule;
+import org.gradle.tooling.model.idea.IdeaSourceDirectory;
+import org.jetbrains.plugins.gradle.model.ExtIdeaContentRoot;
+import org.jetbrains.plugins.gradle.model.ModuleExtendedModel;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/16/14
+ */
+public class ModuleExtendedModelBuilderImplTest extends AbstractModelBuilderTest {
+
+ @Test
+ public void testGradleSourcesSetsInterpretation() throws Exception {
+ final int modulesSize = 7;
+
+ ModuleExtendedModelBuilderImpl moduleExtendedModelBuilder = new ModuleExtendedModelBuilderImpl();
+ assertTrue(moduleExtendedModelBuilder.canBuild("org.jetbrains.plugins.gradle.model.ModuleExtendedModel"));
+
+ DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
+
+ List<ModuleExtendedModel> models =
+ ContainerUtil.mapNotNull(ideaModules, new Function<IdeaModule, ModuleExtendedModel>() {
+ @Override
+ public ModuleExtendedModel fun(IdeaModule module) {
+ ModuleExtendedModel moduleExtendedModel = allModels.getExtraProject(module, ModuleExtendedModel.class);
+
+ assertNotNull(moduleExtendedModel);
+
+ List<String> sourceDirectories = ContainerUtil.newArrayList();
+ List<String> resourceDirectories = ContainerUtil.newArrayList();
+ List<String> testResourceDirectories = ContainerUtil.newArrayList();
+ List<String> testDirectories = ContainerUtil.newArrayList();
+ List<String> excludeDirectories = ContainerUtil.newArrayList();
+
+ fillDirectories(moduleExtendedModel,
+ sourceDirectories, resourceDirectories,
+ testDirectories, testResourceDirectories,
+ excludeDirectories);
+
+ if (module.getName().equals("defaultJavaModule") || module.getName().equals("moduleWithSourceSetDirBothAsResourceAndJava")) {
+ assertEquals(ContainerUtil.newArrayList("src/main/java"), sourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/main/resources"), resourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/test/java"), testDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/test/resources"), testResourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
+ }
+ else if (module.getName().equals("moduleWithCustomSourceSet")) {
+ assertEquals(ContainerUtil.newArrayList("src/custom/java", "src/main/java"), sourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/custom/resources", "src/main/resources"), resourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/test/java"), testDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/test/resources"), testResourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
+ }
+ else if (module.getName().equals("withIntegrationTests")) {
+ assertEquals(ContainerUtil.newArrayList("src/main/java"), sourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/main/resources"), resourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(
+ "src/integration-test/java", "src/integrationTest/java", "src/test/java"), testDirectories);
+ assertEquals(ContainerUtil.newArrayList(
+ "src/integration-test/resources",
+ "src/integrationTest/resources",
+ "src/test/resources"), testResourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
+ }
+ else if (module.getName().equals("testGradleSourcesSetsInterpretation")) {
+ assertTrue(sourceDirectories.isEmpty());
+ assertTrue(resourceDirectories.isEmpty());
+ assertTrue(testDirectories.isEmpty());
+ assertTrue(testResourceDirectories.isEmpty());
+ assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
+ }
+ else if (module.getName().equals("withIdeaPluginCustomization1")) {
+ assertEquals(ContainerUtil.newArrayList("src/main/java"), sourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/main/resources"), resourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/intTest/java", "src/intTest/resources", "src/test/java"), testDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/test/resources"), testResourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(".gradle", "build", "some-extra-exclude-folder"), excludeDirectories);
+ }
+ else if (module.getName().equals("withIdeaPluginCustomization2")) {
+ assertEquals(ContainerUtil.newArrayList("src/main/java", "src/test/java", "src/test/resources"), sourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("some-extra-resource-folder", "src/main/resources"), resourceDirectories);
+ assertTrue(testDirectories.isEmpty());
+ assertEquals(ContainerUtil.newArrayList("some-extra-test-resource-folder"), testResourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
+ }
+ else {
+ fail();
+ }
+
+ return moduleExtendedModel;
+ }
+ });
+
+ assertEquals(modulesSize, models.size());
+ }
+
+ private void fillDirectories(final ModuleExtendedModel model,
+ List<String> sourceDirectories, List<String> resourceDirectories,
+ List<String> testDirectories, List<String> resourceTestDirectories,
+ List<String> excludeDirectories) {
+ for (ExtIdeaContentRoot contentRoot : model.getContentRoots()) {
+ sourceDirectories.addAll(getAllPaths(contentRoot.getSourceDirectories(), model.getName()));
+ resourceDirectories.addAll(getAllPaths(contentRoot.getResourceDirectories(), model.getName()));
+ testDirectories.addAll(getAllPaths(contentRoot.getTestDirectories(), model.getName()));
+ resourceTestDirectories.addAll(getAllPaths(contentRoot.getTestResourceDirectories(), model.getName()));
+ excludeDirectories.addAll(getAllPaths(contentRoot.getExcludeDirectories(), model.getName()));
+ }
+ }
+
+ private Collection<? extends String> getAllPaths(Collection<? extends File> directories, final String moduleName) {
+ List<String> list = ContainerUtil.map2List(directories, new Function<File, String>() {
+ @Override
+ public String fun(File sourceDirectory) {
+ String path =
+ FileUtil.toCanonicalPath(FileUtil.getRelativePath(new File(testDir, moduleName), sourceDirectory));
+ Assert.assertNotNull(path);
+ return path.substring(path.indexOf("/") + 1);
+ }
+ });
+ Collections.sort(list);
+ return list;
+ }
+
+ private Collection<? extends String> getAllPaths(DomainObjectSet<? extends IdeaSourceDirectory> directories, final String moduleName) {
+ List<String> list = ContainerUtil.map2List(directories, new Function<IdeaSourceDirectory, String>() {
+ @Override
+ public String fun(IdeaSourceDirectory sourceDirectory) {
+ String path =
+ FileUtil.toCanonicalPath(FileUtil.getRelativePath(new File(testDir, moduleName), sourceDirectory.getDirectory()));
+ Assert.assertNotNull(path);
+ return path.substring(path.indexOf("/") + 1);
+ }
+ });
+ Collections.sort(list);
+ return list;
+ }
+
+ @Override
+ protected Set<Class> getModels() {
+ return ContainerUtil.<Class>set(ModuleExtendedModel.class);
+ }
+}
+
diff --git a/plugins/groovy/hotswap/agentSrc/org/groovy/debug/hotswap/ResetAgent.java b/plugins/groovy/hotswap/agentSrc/org/groovy/debug/hotswap/ResetAgent.java
index a3e7023cf8f7..35b3577e258b 100644
--- a/plugins/groovy/hotswap/agentSrc/org/groovy/debug/hotswap/ResetAgent.java
+++ b/plugins/groovy/hotswap/agentSrc/org/groovy/debug/hotswap/ResetAgent.java
@@ -2,6 +2,7 @@ package org.groovy.debug.hotswap;
import org.objectweb.asm.*;
+import java.lang.String;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
@@ -18,7 +19,15 @@ import java.security.ProtectionDomain;
*/
@SuppressWarnings({"UtilityClassWithoutPrivateConstructor", "UnusedDeclaration"})
public class ResetAgent {
- private static final String timStampFieldStart = "__timeStamp__239_neverHappen";
+ private static final String timeStampFieldStart = "__timeStamp__239_neverHappen";
+ private static final byte[] timeStampFieldStartBytes;
+
+ static {
+ timeStampFieldStartBytes = new byte[timeStampFieldStart.length()];
+ for (int i = 0; i < timeStampFieldStart.length(); i++) {
+ timeStampFieldStartBytes[i] = (byte)timeStampFieldStart.charAt(i);
+ }
+ }
private static boolean initialized;
@@ -44,18 +53,30 @@ public class ResetAgent {
});
}
- private static boolean hasTimestampField(byte[] buffer) {
- try {
- return new String(buffer, "ISO-8859-1").contains(timStampFieldStart);
- } catch (Throwable e) {
- return true;
+ private static boolean matches(byte[] array, byte[] subArray, int start) {
+ for (int i = 0; i < subArray.length; i++) {
+ if (array[start + i] != subArray[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean containsSubArray(byte[] array, byte[] subArray) {
+ int maxLength = array.length - subArray.length;
+ for (int i = 0; i < maxLength; i++) {
+ if (matches(array, subArray, i)) {
+ return true;
+ }
}
+ return false;
}
private static byte[] removeTimestampField(byte[] newBytes) {
- if (!hasTimestampField(newBytes)) {
+ if (!containsSubArray(newBytes, timeStampFieldStartBytes)) {
return null;
}
+
final boolean[] changed = new boolean[]{false};
final ClassWriter writer = new ClassWriter(0);
@@ -76,7 +97,7 @@ public class ResetAgent {
@Override
public FieldVisitor visitField(int i, String name, String s1, String s2, Object o) {
- if (name.startsWith(timStampFieldStart)) {
+ if (name.startsWith(timeStampFieldStart)) {
//remove the field
changed[0] = true;
return null;
@@ -92,7 +113,7 @@ public class ResetAgent {
return new MethodAdapter(mw) {
@Override
public void visitFieldInsn(int opCode, String s, String name, String desc) {
- if (name.startsWith(timStampFieldStart) && opCode == Opcodes.PUTSTATIC) {
+ if (name.startsWith(timeStampFieldStart) && opCode == Opcodes.PUTSTATIC) {
visitInsn(Type.LONG_TYPE.getDescriptor().equals(desc) ? Opcodes.POP2 : Opcodes.POP);
} else {
super.visitFieldInsn(opCode, s, name, desc);
diff --git a/plugins/groovy/hotswap/gragent.jar b/plugins/groovy/hotswap/gragent.jar
index 8794d675ad24..b0e17671dfaf 100644
--- a/plugins/groovy/hotswap/gragent.jar
+++ b/plugins/groovy/hotswap/gragent.jar
Binary files differ
diff --git a/plugins/groovy/resources/fileTemplates/code/Spock SetUp Method.groovy.ft b/plugins/groovy/resources/fileTemplates/code/Spock_SetUp_Method.groovy.ft
index 303209e1a46f..303209e1a46f 100644
--- a/plugins/groovy/resources/fileTemplates/code/Spock SetUp Method.groovy.ft
+++ b/plugins/groovy/resources/fileTemplates/code/Spock_SetUp_Method.groovy.ft
diff --git a/plugins/groovy/resources/fileTemplates/code/Spock SetUp Method.groovy.html b/plugins/groovy/resources/fileTemplates/code/Spock_SetUp_Method.groovy.html
index 379785f36c3f..379785f36c3f 100644
--- a/plugins/groovy/resources/fileTemplates/code/Spock SetUp Method.groovy.html
+++ b/plugins/groovy/resources/fileTemplates/code/Spock_SetUp_Method.groovy.html
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/navbar/GrNavBarModelExtension.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/navbar/GrNavBarModelExtension.java
index e5b5681fc4fa..9116dbe42fd2 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/navbar/GrNavBarModelExtension.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/navbar/GrNavBarModelExtension.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
@@ -32,6 +33,12 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefini
*/
public class GrNavBarModelExtension extends AbstractNavBarModelExtension {
+ @Nullable
+ @Override
+ public String getPresentableText(Object object) {
+ return null;
+ }
+
@Override
public PsiElement adjustElement(PsiElement psiElement) {
final ProjectFileIndex index = ProjectRootManager.getInstance(psiElement.getProject()).getFileIndex();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockTestFramework.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockTestFramework.java
index b7872dcc9730..9a36c8c83990 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockTestFramework.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockTestFramework.java
@@ -51,7 +51,7 @@ public class SpockTestFramework extends GroovyTestFramework {
@Override
public FileTemplateDescriptor getSetUpMethodFileTemplateDescriptor() {
- return new FileTemplateDescriptor("Spock SetUp Method.groovy");
+ return new FileTemplateDescriptor("Spock_SetUp_Method.groovy");
}
@Override
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
index 53cb43d9e457..9fc2b16aedaf 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
@@ -19,20 +19,14 @@ package org.zmlx.hg4idea.log;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.VcsKey;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
-import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.*;
-import com.intellij.vcs.log.data.VcsLogBranchFilter;
-import com.intellij.vcs.log.data.VcsLogDateFilter;
-import com.intellij.vcs.log.data.VcsLogStructureFilter;
-import com.intellij.vcs.log.data.VcsLogUserFilter;
-import com.intellij.vcs.log.ui.filter.VcsLogTextFilter;
+import com.intellij.vcs.log.VcsLogTextFilter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgNameWithHashInfo;
@@ -162,33 +156,28 @@ public class HgLogProvider implements VcsLogProvider {
@NotNull
@Override
public List<? extends VcsFullCommitDetails> getFilteredDetails(@NotNull final VirtualFile root,
- @NotNull Collection<VcsLogFilter> filters,
+ @NotNull Collection<VcsLogBranchFilter> branchFilters,
+ @NotNull Collection<VcsLogUserFilter> userFilters,
+ @NotNull Collection<VcsLogDateFilter> dateFilters,
+ @NotNull Collection<VcsLogTextFilter> textFilters,
+ @NotNull Collection<VcsLogStructureFilter> structureFilters,
int maxCount) throws VcsException {
List<String> filterParameters = ContainerUtil.newArrayList();
- List<VcsLogBranchFilter> branchFilters = ContainerUtil.findAll(filters, VcsLogBranchFilter.class);
+ // branch filter and user filter may be used several times without delimiter
+ // or -r options with appropriate revset arguments delimited by '|' or 'and'.
if (!branchFilters.isEmpty()) {
- String branchFilter = joinFilters(branchFilters, new Function<VcsLogBranchFilter, String>() {
- @Override
- public String fun(VcsLogBranchFilter filter) {
- return filter.getBranchName();
- }
- });
- filterParameters.add(prepareParameter("branch", branchFilter));
+ for (VcsLogBranchFilter branchFilter : branchFilters) {
+ filterParameters.add(prepareParameter("branch", branchFilter.getBranchName()));
+ }
}
- List<VcsLogUserFilter> userFilters = ContainerUtil.findAll(filters, VcsLogUserFilter.class);
if (!userFilters.isEmpty()) {
- String authorFilter = joinFilters(userFilters, new Function<VcsLogUserFilter, String>() {
- @Override
- public String fun(VcsLogUserFilter filter) {
- return filter.getUserName(root);
- }
- });
- filterParameters.add(prepareParameter("user", authorFilter));
+ for (VcsLogUserFilter authorFilter : userFilters) {
+ filterParameters.add(prepareParameter("user", authorFilter.getUserName(root)));
+ }
}
- List<VcsLogDateFilter> dateFilters = ContainerUtil.findAll(filters, VcsLogDateFilter.class);
if (!dateFilters.isEmpty()) {
StringBuilder args = new StringBuilder();
final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
@@ -208,7 +197,6 @@ public class HgLogProvider implements VcsLogProvider {
filterParameters.add(args.toString());
}
- List<VcsLogTextFilter> textFilters = ContainerUtil.findAll(filters, VcsLogTextFilter.class);
if (textFilters.size() > 1) {
LOG.warn("Expected only one text filter: " + textFilters);
}
@@ -217,7 +205,6 @@ public class HgLogProvider implements VcsLogProvider {
filterParameters.add(prepareParameter("keyword", textFilter));
}
- List<VcsLogStructureFilter> structureFilters = ContainerUtil.findAll(filters, VcsLogStructureFilter.class);
if (!structureFilters.isEmpty()) {
for (VcsLogStructureFilter filter : structureFilters) {
for (VirtualFile file : filter.getFiles(root)) {
@@ -249,8 +236,4 @@ public class HgLogProvider implements VcsLogProvider {
private static String prepareParameter(String paramName, String value) {
return "--" + paramName + "=" + value; // no value escaping needed, because the parameter itself will be quoted by GeneralCommandLine
}
-
- private static <T> String joinFilters(List<T> filters, Function<T, String> toString) {
- return StringUtil.join(filters, toString, "\\|");
- }
}
diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourcesBuilder.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourcesBuilder.java
index 8f9a7b85b9cc..13bf78686482 100644
--- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourcesBuilder.java
+++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourcesBuilder.java
@@ -1,6 +1,7 @@
package org.jetbrains.jps.maven.compiler;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.BuildOutputConsumer;
@@ -116,7 +117,13 @@ public class MavenResourcesBuilder extends TargetBuilder<MavenResourceRootDescri
private Pattern getDelimitersPattern() {
Pattern pattern = myDelimitersPattern;
if (pattern == null) {
- pattern = Pattern.compile(config.delimitersPattern);
+ if (StringUtil.isEmpty(config.escapeString)) {
+ pattern = Pattern.compile(config.delimitersPattern);
+ }
+ else {
+ String quotedEscapeString = Pattern.quote(config.escapeString);
+ pattern = Pattern.compile("(" + quotedEscapeString + quotedEscapeString + ")|(?:(" + quotedEscapeString + ")?(" + config.delimitersPattern + "))");
+ }
myDelimitersPattern = pattern;
}
return pattern;
@@ -168,28 +175,31 @@ public class MavenResourcesBuilder extends TargetBuilder<MavenResourceRootDescri
Map<String, String> resolvedProperties = resolvedPropertiesParam;
final Matcher matcher = delimitersPattern.matcher(text);
+
+ boolean hasEscapeString = !StringUtil.isEmpty(moduleConfig.escapeString);
+
final int groupCount = matcher.groupCount();
- final String escapeString = moduleConfig.escapeString;
+ int firstPropertyGroupIndex = hasEscapeString ? 3 : 0;
+
int last = 0;
while (matcher.find()) {
- if (escapeString != null) {
- int escapeStringStartIndex = matcher.start() - escapeString.length();
- if (escapeStringStartIndex >= last) {
- if (text.startsWith(escapeString, escapeStringStartIndex)) {
- out.append(text, last, escapeStringStartIndex);
- out.append(matcher.group());
- last = matcher.end();
- continue;
- }
- }
- }
-
out.append(text, last, matcher.start());
last = matcher.end();
+ if (hasEscapeString) {
+ if (matcher.group(1) != null) {
+ out.append(moduleConfig.escapeString).append(moduleConfig.escapeString); // double escape string
+ continue;
+ }
+ else if (matcher.group(2) != null) {
+ out.append(matcher.group(3)); // escaped value
+ continue;
+ }
+ }
+
String propertyName = null;
- for (int i = 0; i < groupCount; i++) {
+ for (int i = firstPropertyGroupIndex; i < groupCount; i++) {
propertyName = matcher.group(i + 1);
if (propertyName != null) {
break;
diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenModuleResourceConfiguration.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenModuleResourceConfiguration.java
index 3c4c47c18e56..86340adf0ea7 100644
--- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenModuleResourceConfiguration.java
+++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenModuleResourceConfiguration.java
@@ -58,7 +58,7 @@ public class MavenModuleResourceConfiguration {
public Set<String> filteringExclusions = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
@OptionTag
- public String escapeString = MavenProjectConfiguration.DEFAULT_ESCAPE_STRING;
+ public String escapeString = null;
@OptionTag
public boolean escapeWindowsPaths = true;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/compiler/MavenResourceCompiler.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/compiler/MavenResourceCompiler.java
index 209583b6f731..d5eb4a69d7f7 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/compiler/MavenResourceCompiler.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/compiler/MavenResourceCompiler.java
@@ -167,7 +167,7 @@ public class MavenResourceCompiler implements ClassPostProcessingCompiler {
Set<String> nonFilteredExtensions = collectNonFilteredExtensions(mavenProject);
String escapeString = MavenJDOMUtil.findChildValueByPath(mavenProject.getPluginConfiguration("org.apache.maven.plugins",
"maven-resources-plugin"),
- "escapeString", "\\");
+ "escapeString", null);
List<MyProcessingItem> moduleItemsToProcess = new ArrayList<MyProcessingItem>();
collectProcessingItems(eachModule, mavenProject, context, properties, propertiesHashCode,
@@ -245,7 +245,7 @@ public class MavenResourceCompiler implements ClassPostProcessingCompiler {
Properties properties,
long propertiesHashCode,
Set<String> nonFilteredExtensions,
- String escapeString,
+ @Nullable String escapeString,
boolean tests,
List<MyProcessingItem> result) {
String outputDir = CompilerPaths.getModuleOutputPath(module, tests);
@@ -305,7 +305,7 @@ public class MavenResourceCompiler implements ClassPostProcessingCompiler {
final Properties properties,
final long propertiesHashCode,
final Set<String> nonFilteredExtensions,
- final String escapeString,
+ @Nullable final String escapeString,
final List<MyProcessingItem> result,
final ProgressIndicator indicator) {
VfsUtilCore.visitChildrenRecursively(currentDir, new VirtualFileVisitor() {
@@ -476,7 +476,7 @@ public class MavenResourceCompiler implements ClassPostProcessingCompiler {
boolean isFiltered,
Properties properties,
long propertiesHashCode,
- String escapeString) {
+ @Nullable String escapeString) {
myModule = module;
mySourceFile = sourceFile;
myOutputPath = outputPath;
@@ -507,6 +507,7 @@ public class MavenResourceCompiler implements ClassPostProcessingCompiler {
return myProperties;
}
+ @Nullable
public String getEscapeString() {
return myEscapeString;
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java
index 979e182bad25..66875895f278 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java
@@ -47,7 +47,7 @@ public class MavenPropertyResolver {
public static void doFilterText(Module module,
String text,
Properties additionalProperties,
- String propertyEscapeString,
+ @Nullable String propertyEscapeString,
Appendable out) throws IOException {
MavenProjectsManager manager = MavenProjectsManager.getInstance(module.getProject());
MavenProject mavenProject = manager.findProject(module);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java
index 553175e5a07e..0d4b06b21cb0 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java
@@ -294,9 +294,7 @@ public class MavenModuleImporter {
if (file == null) continue;
if (libraryModel == null) {
- String libraryName = artifact.getLibraryName();
- assert libraryName.startsWith(MavenArtifact.MAVEN_LIB_PREFIX);
- libraryName = MavenArtifact.MAVEN_LIB_PREFIX + "ATTACHED-JAR: " + libraryName.substring(MavenArtifact.MAVEN_LIB_PREFIX.length());
+ String libraryName = getAttachedJarsLibName(artifact);
Library library = myModifiableModelsProvider.getLibraryByName(libraryName);
if (library == null) {
@@ -314,6 +312,14 @@ public class MavenModuleImporter {
}
@NotNull
+ public static String getAttachedJarsLibName(@NotNull MavenArtifact artifact) {
+ String libraryName = artifact.getLibraryName();
+ assert libraryName.startsWith(MavenArtifact.MAVEN_LIB_PREFIX);
+ libraryName = MavenArtifact.MAVEN_LIB_PREFIX + "ATTACHED-JAR: " + libraryName.substring(MavenArtifact.MAVEN_LIB_PREFIX.length());
+ return libraryName;
+ }
+
+ @NotNull
public static DependencyScope selectScope(String mavenScope) {
if (MavenConstants.SCOPE_RUNTIME.equals(mavenScope)) return DependencyScope.RUNTIME;
if (MavenConstants.SCOPE_TEST.equals(mavenScope)) return DependencyScope.TEST;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResourceCompilerConfigurationGenerator.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResourceCompilerConfigurationGenerator.java
index 523d5cbec958..c2b0aa9ba49b 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResourceCompilerConfigurationGenerator.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResourceCompilerConfigurationGenerator.java
@@ -129,7 +129,7 @@ public class MavenResourceCompilerConfigurationGenerator {
}
Element pluginConfiguration = mavenProject.getPluginConfiguration("org.apache.maven.plugins", "maven-resources-plugin");
- resourceConfig.escapeString = MavenJDOMUtil.findChildValueByPath(pluginConfiguration, "escapeString", "\\");
+ resourceConfig.escapeString = MavenJDOMUtil.findChildValueByPath(pluginConfiguration, "escapeString", null);
String escapeWindowsPaths = MavenJDOMUtil.findChildValueByPath(pluginConfiguration, "escapeWindowsPaths");
if (escapeWindowsPaths != null) {
resourceConfig.escapeWindowsPaths = Boolean.parseBoolean(escapeWindowsPaths);
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java
index 4c2c7815e5ff..80e738fa6a81 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java
@@ -868,10 +868,15 @@ public abstract class ResourceFilteringTest extends MavenImportingTestCase {
}
public void testEscapingFiltering() throws Exception {
+ if (!useJps()) return;
+
createProjectSubFile("filters/filter.properties", "xxx=value");
createProjectSubFile("resources/file.properties",
"value1=\\${xxx}\n" +
- "value2=${xxx}\n");
+ "value2=\\\\${xxx}\n" +
+ "value3=\\\\\\${xxx}\n" +
+ "value3=\\\\\\\\${xxx}\n" +
+ "value4=.\\.\\\\.\\\\\\.");
importProject("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
@@ -887,12 +892,24 @@ public abstract class ResourceFilteringTest extends MavenImportingTestCase {
" <filtering>true</filtering>" +
" </resource>" +
" </resources>" +
+ " <plugins>" +
+ " <plugin>" +
+ " <groupId>org.apache.maven.plugins</groupId>" +
+ " <artifactId>maven-resources-plugin</artifactId>" +
+ " <configuration>" +
+ " <escapeString>\\</escapeString>" +
+ " </configuration>" +
+ " </plugin>" +
+ " </plugins>" +
"</build>");
compileModules("project");
assertResult("target/classes/file.properties",
"value1=${xxx}\n" +
- "value2=value\n");
+ "value2=\\\\value\n" +
+ "value3=\\\\${xxx}\n" +
+ "value3=\\\\\\\\value\n" +
+ "value4=.\\.\\\\.\\\\\\.");
}
public void testPropertyPriority() throws Exception {
diff --git a/python/IntelliLang-python/src/pyInjections.xml b/python/IntelliLang-python/src/pyInjections.xml
index f561c1d33016..a75015e02441 100644
--- a/python/IntelliLang-python/src/pyInjections.xml
+++ b/python/IntelliLang-python/src/pyInjections.xml
@@ -9,6 +9,6 @@
</injection>
<injection language="SQL" injector-id="python">
<display-name>"SQL select/delete/insert/update/create"</display-name>
- <place><![CDATA[pyLiteralExpression().withText(string().matchesBrics("[UuRrBb\\\"\\' \t]*(((SELECT|DELETE) .*FROM)|((INSERT|REPLACE) .*INTO)|(UPDATE .* SET)|((CREATE|DROP|ALTER) +(TABLE|INDEX))) .*"))]]></place>
+ <place><![CDATA[pyLiteralExpression().withText(string().matchesBrics(".*(((SELECT|DELETE) .*FROM)|((INSERT|REPLACE) .*INTO)|(UPDATE .* SET)|((CREATE|DROP|ALTER) +(TABLE|INDEX))) .*"))]]></place>
</injection>
</component>
diff --git a/python/helpers/generator3.py b/python/helpers/generator3.py
index fe24620d374d..ca61efe13be4 100644
--- a/python/helpers/generator3.py
+++ b/python/helpers/generator3.py
@@ -1,41 +1,13 @@
# encoding: utf-8
-from pycharm_generator_utils.module_redeclarator import *
-from pycharm_generator_utils.util_methods import *
-from pycharm_generator_utils.constants import *
-import os
import atexit
import zipfile
-debug_mode = False
-
-
-def build_output_name(dirname, qualified_name):
- qualifiers = qualified_name.split(".")
- if dirname and not dirname.endswith("/") and not dirname.endswith("\\"):
- dirname += os.path.sep # "a -> a/"
- for pathindex in range(len(qualifiers) - 1): # create dirs for all qualifiers but last
- subdirname = dirname + os.path.sep.join(qualifiers[0: pathindex + 1])
- if not os.path.isdir(subdirname):
- action("creating subdir %r", subdirname)
- os.makedirs(subdirname)
- init_py = os.path.join(subdirname, "__init__.py")
- if os.path.isfile(subdirname + ".py"):
- os.rename(subdirname + ".py", init_py)
- elif not os.path.isfile(init_py):
- init = fopen(init_py, "w")
- init.close()
- target_name = dirname + os.path.sep.join(qualifiers)
- if os.path.isdir(target_name):
- fname = os.path.join(target_name, "__init__.py")
- else:
- fname = target_name + ".py"
-
- dirname = os.path.dirname(fname)
+from pycharm_generator_utils.module_redeclarator import *
+from pycharm_generator_utils.util_methods import *
+from pycharm_generator_utils.constants import *
- if not os.path.isdir(dirname):
- os.makedirs(dirname)
- return fname
+debug_mode = False
def redo_module(module_name, outfile, module_file_name, doing_builtins):
@@ -263,80 +235,67 @@ def process_one(name, mod_file_name, doing_builtins, subdir):
say(name)
sys.stdout.flush()
action("doing nothing")
- outfile = None
+
try:
- try:
- fname = build_output_name(subdir, name)
- action("opening %r", fname)
- outfile = fopen(fname, "w")
- old_modules = list(sys.modules.keys())
- imported_module_names = []
-
- class MyFinder:
- #noinspection PyMethodMayBeStatic
- def find_module(self, fullname, path=None):
- if fullname != name:
- imported_module_names.append(fullname)
- return None
-
- my_finder = None
- if hasattr(sys, 'meta_path'):
- my_finder = MyFinder()
- sys.meta_path.append(my_finder)
- else:
- imported_module_names = None
-
- action("importing")
- __import__(name) # sys.modules will fill up with what we want
-
- if my_finder:
- sys.meta_path.remove(my_finder)
- if imported_module_names is None:
- imported_module_names = [m for m in sys.modules.keys() if m not in old_modules]
-
- redo_module(name, outfile, mod_file_name, doing_builtins)
- # The C library may have called Py_InitModule() multiple times to define several modules (gtk._gtk and gtk.gdk);
- # restore all of them
- path = name.split(".")
- redo_imports = not ".".join(path[:-1]) in MODULES_INSPECT_DIR
- if imported_module_names and redo_imports:
- for m in sys.modules.keys():
- action("looking at possible submodule %r", m)
- # if module has __file__ defined, it has Python source code and doesn't need a skeleton
- if m not in old_modules and m not in imported_module_names and m != name and not hasattr(
- sys.modules[m], '__file__'):
- if not quiet:
- say(m)
- sys.stdout.flush()
- fname = build_output_name(subdir, m)
- action("opening %r", fname)
- subfile = fopen(fname, "w")
- try:
- redo_module(m, subfile, mod_file_name, doing_builtins)
- finally:
- action("closing %r", fname)
- subfile.close()
- except:
- exctype, value = sys.exc_info()[:2]
- msg = "Failed to process %r while %s: %s"
- args = name, CURRENT_ACTION, str(value)
- report(msg, *args)
- if outfile is not None and not outfile.closed:
- outfile.write("# encoding: %s\n" % OUT_ENCODING)
- outfile.write("# module %s\n" % name)
- outfile.write("# from %s\n" % mod_file_name)
- outfile.write("# by generator %s\n" % VERSION)
- outfile.write("\n\n")
- outfile.write("# Skeleton generation error:\n#\n# " + (msg % args) + "\n")
- if debug_mode:
- if sys.platform == 'cli':
- import traceback
- traceback.print_exc(file=sys.stderr)
- raise
- return False
- finally:
- if outfile is not None and not outfile.closed:
- outfile.close()
+ fname = build_output_name(subdir, name)
+ action("opening %r", fname)
+ old_modules = list(sys.modules.keys())
+ imported_module_names = []
+
+ class MyFinder:
+ #noinspection PyMethodMayBeStatic
+ def find_module(self, fullname, path=None):
+ if fullname != name:
+ imported_module_names.append(fullname)
+ return None
+
+ my_finder = None
+ if hasattr(sys, 'meta_path'):
+ my_finder = MyFinder()
+ sys.meta_path.append(my_finder)
+ else:
+ imported_module_names = None
+
+ action("importing")
+ __import__(name) # sys.modules will fill up with what we want
+
+ if my_finder:
+ sys.meta_path.remove(my_finder)
+ if imported_module_names is None:
+ imported_module_names = [m for m in sys.modules.keys() if m not in old_modules]
+
+ redo_module(name, fname, mod_file_name, doing_builtins)
+ # The C library may have called Py_InitModule() multiple times to define several modules (gtk._gtk and gtk.gdk);
+ # restore all of them
+ path = name.split(".")
+ redo_imports = not ".".join(path[:-1]) in MODULES_INSPECT_DIR
+ if imported_module_names and redo_imports:
+ for m in sys.modules.keys():
+ if m.startswith("pycharm_generator_utils"): continue
+ action("looking at possible submodule %r", m)
+ # if module has __file__ defined, it has Python source code and doesn't need a skeleton
+ if m not in old_modules and m not in imported_module_names and m != name and not hasattr(
+ sys.modules[m], '__file__'):
+ if not quiet:
+ say(m)
+ sys.stdout.flush()
+ fname = build_output_name(subdir, m)
+ action("opening %r", fname)
+ try:
+ redo_module(m, fname, mod_file_name, doing_builtins)
+ finally:
+ action("closing %r", fname)
+ except:
+ exctype, value = sys.exc_info()[:2]
+ msg = "Failed to process %r while %s: %s"
+ args = name, CURRENT_ACTION, str(value)
+ report(msg, *args)
+ if debug_mode:
+ if sys.platform == 'cli':
+ import traceback
+ traceback.print_exc(file=sys.stderr)
+ raise
+ return False
return True
diff --git a/python/helpers/pycharm/nose_utils.py b/python/helpers/pycharm/nose_utils.py
index bed318a50bf0..9a6d68251cb3 100644
--- a/python/helpers/pycharm/nose_utils.py
+++ b/python/helpers/pycharm/nose_utils.py
@@ -1,9 +1,13 @@
-from tcmessages import TeamcityServiceMessages
-import sys, traceback, datetime
+import sys
+import traceback
+import datetime
import unittest
+
+from tcmessages import TeamcityServiceMessages
from tcunittest import strclass
from tcunittest import TeamcityTestResult
+
try:
from nose.util import isclass # backwards compat
from nose.config import Config
@@ -59,7 +63,10 @@ class TeamcityPlugin(ErrorClassPlugin, TextTestResult, TeamcityTestResult):
def formatErr(self, err):
exctype, value, tb = err
if isinstance(value, str):
- value = exctype(value)
+ try:
+ value = exctype(value)
+ except TypeError:
+ pass
return ''.join(traceback.format_exception(exctype, value, tb))
def is_gen(self, test):
diff --git a/python/helpers/pycharm_generator_utils/constants.py b/python/helpers/pycharm_generator_utils/constants.py
index 6b77e73049b9..4ea8cf17309a 100644
--- a/python/helpers/pycharm_generator_utils/constants.py
+++ b/python/helpers/pycharm_generator_utils/constants.py
@@ -6,7 +6,7 @@ import string
import time
-VERSION = "1.131"
+VERSION = "1.133"
OUT_ENCODING = 'utf-8'
diff --git a/python/helpers/pycharm_generator_utils/module_redeclarator.py b/python/helpers/pycharm_generator_utils/module_redeclarator.py
index f56fb430e0c8..83778790a1c5 100644
--- a/python/helpers/pycharm_generator_utils/module_redeclarator.py
+++ b/python/helpers/pycharm_generator_utils/module_redeclarator.py
@@ -1,6 +1,7 @@
+import keyword
+
from pycharm_generator_utils.util_methods import *
from pycharm_generator_utils.constants import *
-import keyword, re
class emptylistdict(dict):
@@ -49,6 +50,11 @@ class Buf(object):
return len(self.data) == 0
+class ClassBuf(Buf):
+ def __init__(self, name, indenter):
+ super(ClassBuf, self).__init__(indenter)
+ self.name = name
+
#noinspection PyUnresolvedReferences,PyBroadException
class ModuleRedeclarator(object):
def __init__(self, module, outfile, mod_filename, indent_size=4, doing_builtins=False):
@@ -67,6 +73,7 @@ class ModuleRedeclarator(object):
self.imports_buf = Buf(self)
self.functions_buf = Buf(self)
self.classes_buf = Buf(self)
+ self.classes_buffs = list()
self.footer_buf = Buf(self)
self.indent_size = indent_size
self._indent_step = " " * self.indent_size
@@ -106,8 +113,43 @@ class ModuleRedeclarator(object):
return self._indent_step * level
def flush(self):
- for buf in (self.header_buf, self.imports_buf, self.functions_buf, self.classes_buf, self.footer_buf):
- buf.flush(self.outfile)
+ init = None
+ try:
+ if self.mod_filename and len(self.classes_buffs) >= 30:
+ mod_path = self.outfile.strip(".py")
+
+ fname = build_output_name(mod_path, "__init__")
+ init = fopen(fname, "w")
+ for buf in (self.header_buf, self.imports_buf, self.functions_buf, self.classes_buf):
+ buf.flush(init)
+
+ data = ""
+ for buf in self.classes_buffs:
+ fname = build_output_name(mod_path, buf.name)
+ dummy = fopen(fname, "w")
+ self.header_buf.flush(dummy)
+ buf.flush(dummy)
+ data += "from "
+ if version[0] >= 3:
+ data += "."
+ data += buf.name + " import " + buf.name + "\n"
+ dummy.close()
+
+ init.write(data)
+ self.footer_buf.flush(init)
+ else:
+ init = fopen(self.outfile, "w")
+ for buf in (self.header_buf, self.imports_buf, self.functions_buf, self.classes_buf):
+ buf.flush(init)
+
+ for buf in self.classes_buffs:
+ buf.flush(init)
+
+ self.footer_buf.flush(init)
+
+ finally:
+ if init is not None and not init.closed:
+ init.close()
# Some builtin classes effectively change __init__ signature without overriding it.
# This callable serves as a placeholder to be replaced via REDEFINED_BUILTIN_SIGS
@@ -150,7 +192,7 @@ class ModuleRedeclarator(object):
for initializer_type, r in self._initializers:
if initializer_type == a_type:
return r
- # NOTE: here we could handle things like defaultdict, sets, etc if we wanted
+ # NOTE: here we could handle things like defaultdict, sets, etc if we wanted
return "None"
@@ -224,7 +266,7 @@ class ModuleRedeclarator(object):
seen_values.append(value)
if isinstance(k, SIMPLEST_TYPES):
self.fmt_value(out, value, indent + 1, prefix=repr(k) + ": ", postfix=",",
- seen_values=seen_values)
+ seen_values=seen_values)
else:
# both key and value need fancy formatting
self.fmt_value(out, k, indent + 1, postfix=": ", seen_values=seen_values)
@@ -244,9 +286,15 @@ class ModuleRedeclarator(object):
if self._defined.get(found_name, False):
out(indent, prefix, found_name, postfix)
else:
- # a forward / circular declaration happens
+ # a forward / circular declaration happens
notice = ""
- real_value = cleanup(repr(p_value))
+ try:
+ representation = repr(p_value)
+ except Exception:
+ import traceback
+ traceback.print_exc(file=sys.stderr)
+ return
+ real_value = cleanup(representation)
if found_name:
if found_name == as_name:
notice = " # (!) real value is %r" % real_value
@@ -409,7 +457,7 @@ class ModuleRedeclarator(object):
def is_predefined_builtin(self, module_name, class_name, func_name):
return self.doing_builtins and module_name == BUILTIN_MOD_NAME and (
- class_name, func_name) in PREDEFINED_BUILTIN_SIGS
+ class_name, func_name) in PREDEFINED_BUILTIN_SIGS
def redo_function(self, out, p_func, p_name, indent, p_class=None, p_modname=None, classname=None, seen=None):
@@ -434,7 +482,7 @@ class ModuleRedeclarator(object):
return
else:
seen[id(p_func)] = p_name
- # real work
+ # real work
if classname is None:
classname = p_class and p_class.__name__ or None
if p_class and hasattr(p_class, '__mro__'):
@@ -492,7 +540,7 @@ class ModuleRedeclarator(object):
out(indent, "def ", p_name, sig, ": # known case of ", ofwhat)
out_doc_attr(out, p_func, indent + 1, p_class)
else:
- # __doc__ is our best source of arglist
+ # __doc__ is our best source of arglist
sig_note = "real signature unknown"
spec = ""
is_init = (p_name == "__init__" and p_class is not None)
@@ -508,17 +556,17 @@ class ModuleRedeclarator(object):
action("parsing doc of func %r of class %r", p_name, p_class)
if isinstance(funcdoc, STR_TYPES):
(spec, ret_literal, more_notes) = self.parse_func_doc(funcdoc, p_name, p_name, classname, deco,
- sip_generated)
+ sip_generated)
if spec is None and p_name == '__init__' and classname:
(spec, ret_literal, more_notes) = self.parse_func_doc(funcdoc, classname, p_name, classname, deco,
- sip_generated)
+ sip_generated)
sig_restored = spec is not None
if more_notes:
if sig_note:
sig_note += "; "
sig_note += more_notes
if not sig_restored:
- # use an allow-all declaration
+ # use an allow-all declaration
decl = []
if p_class:
first_param = propose_first_param(deco)
@@ -531,7 +579,7 @@ class ModuleRedeclarator(object):
# to reduce size of stubs, don't output same docstring twice for class and its __init__ method
if not is_init or funcdoc != p_class.__doc__:
out_docstring(out, funcdoc, indent + 1)
- # body
+ # body
if ret_literal and not is_init:
out(indent + 1, "return ", ret_literal)
else:
@@ -646,7 +694,7 @@ class ModuleRedeclarator(object):
self.redo_function(out, item, item_name, indent + 1, p_class, p_modname, classname=p_name, seen=seen_funcs)
except:
handle_error_func(item_name, out)
- #
+ #
known_props = KNOWN_PROPS.get(p_modname, {})
a_setter = "lambda self, v: None"
a_deleter = "lambda self: None"
@@ -782,7 +830,7 @@ class ModuleRedeclarator(object):
for item_name in module_dict:
note("looking at %s", item_name)
if item_name in (
- "__dict__", "__doc__", "__module__", "__file__", "__name__", "__builtins__", "__package__"):
+ "__dict__", "__doc__", "__module__", "__file__", "__name__", "__builtins__", "__package__"):
continue # handled otherwise
try:
item = getattr(self.module, item_name) # let getters do the magic
@@ -806,7 +854,7 @@ class ModuleRedeclarator(object):
mod_name = getattr(item, '__module__', None)
except:
pass
- # we assume that module foo.bar never imports foo; foo may import foo.bar. (see pygame and pygame.rect)
+ # we assume that module foo.bar never imports foo; foo may import foo.bar. (see pygame and pygame.rect)
maybe_import_mod_name = mod_name or ""
import_is_from_top = len(p_name) > len(maybe_import_mod_name) and p_name.startswith(maybe_import_mod_name)
note("mod_name = %s, prospective = %s, from top = %s", mod_name, maybe_import_mod_name, import_is_from_top)
@@ -906,9 +954,8 @@ class ModuleRedeclarator(object):
self.functions_buf.out(0, "# no functions")
#
if classes:
- out = self.functions_buf.out
- out(0, "# classes")
- out(0, "")
+ self.classes_buf.out(0, "# classes")
+ self.classes_buf.out(0, "")
seen_classes = {}
# sort classes so that inheritance order is preserved
cls_list = [] # items are (class_name, mro_tuple)
@@ -922,6 +969,9 @@ class ModuleRedeclarator(object):
break # ...and need not go fartehr than first known child
cls_list.insert(ins_index, (cls_name, get_mro(cls)))
for item_name in [cls_item[0] for cls_item in cls_list]:
+ buf = ClassBuf(item_name, self)
+ self.classes_buffs.append(buf)
+ out = buf.out
if item_name in omitted_names:
out(0, "# definition of ", item_name, " omitted")
continue
@@ -974,7 +1024,7 @@ class ModuleRedeclarator(object):
self.footer_buf.out(0, "# intermittent names")
for value in values_to_add:
self.footer_buf.out(0, value)
- # imports: last, because previous parts could alter used_imports or hidden_imports
+ # imports: last, because previous parts could alter used_imports or hidden_imports
self.output_import_froms()
if self.imports_buf.isEmpty():
self.imports_buf.out(0, "# no imports")
@@ -1009,7 +1059,7 @@ class ModuleRedeclarator(object):
names_pack.append(n)
names_pack.append(", ")
right_pos += (len_n + 2)
- # last line is...
+ # last line is...
if indent_level == 0: # one line
names_pack[0] = names_pack[0][:-1] # cut off lpar
names_pack[-1] = "" # cut last comma
diff --git a/python/helpers/pycharm_generator_utils/util_methods.py b/python/helpers/pycharm_generator_utils/util_methods.py
index 8d6d3568914e..2ddbc94f4a63 100644
--- a/python/helpers/pycharm_generator_utils/util_methods.py
+++ b/python/helpers/pycharm_generator_utils/util_methods.py
@@ -6,7 +6,7 @@ except ImportError:
inspect = None
def create_named_tuple(): #TODO: user-skeleton
- return """
+ return """
class __namedtuple(tuple):
'''A mock base class for named tuples.'''
@@ -38,12 +38,12 @@ class __namedtuple(tuple):
"""
def create_generator():
- # Fake <type 'generator'>
- if version[0] < 3:
- next_name = "next"
- else:
- next_name = "__next__"
- txt = """
+ # Fake <type 'generator'>
+ if version[0] < 3:
+ next_name = "next"
+ else:
+ next_name = "__next__"
+ txt = """
class __generator(object):
'''A mock class representing the generator function type.'''
def __init__(self):
@@ -59,8 +59,8 @@ class __generator(object):
'''Return the next item from the container.'''
pass
""" % (next_name,)
- if version[0] >= 3 or (version[0] == 2 and version[1] >= 5):
- txt += """
+ if version[0] >= 3 or (version[0] == 2 and version[1] >= 5):
+ txt += """
def close(self):
'''Raises new GeneratorExit exception inside the generator to terminate the iteration.'''
pass
@@ -73,10 +73,10 @@ class __generator(object):
'''Used to raise an exception inside the generator.'''
pass
"""
- return txt
+ return txt
def _searchbases(cls, accum):
-# logic copied from inspect.py
+ # logic copied from inspect.py
if cls not in accum:
accum.append(cls)
for x in cls.__bases__:
@@ -84,7 +84,7 @@ def _searchbases(cls, accum):
def get_mro(a_class):
-# logic copied from inspect.py
+ # logic copied from inspect.py
"""Returns a tuple of MRO classes."""
if hasattr(a_class, "__mro__"):
return a_class.__mro__
@@ -236,7 +236,7 @@ def transform_seq(results, toplevel=True):
if toplevel and not has_item_starting_with(ret, "*"):
ret.append("*more")
else:
- # we're in a "foo, (bar1, bar2, ...)"; make it "foo, bar_tuple"
+ # we're in a "foo, (bar1, bar2, ...)"; make it "foo, bar_tuple"
return extract_alpha_prefix(results[0][1]) + "_tuple"
else: # just name
ret.append(sanitize_ident(token_name, is_clr))
@@ -271,7 +271,7 @@ def transform_optional_seq(results):
if len(token) == 3: # name with value; little sense, but can happen in a deeply nested optional
ret.append(sanitize_ident(token_name, is_clr) + "=" + sanitize_value(token[2]))
elif token_name == '...':
- # we're in a "foo, [bar, ...]"; make it "foo, *bar"
+ # we're in a "foo, [bar, ...]"; make it "foo, *bar"
return ["*" + extract_alpha_prefix(
results[1][1])] # we must return a seq; [1] is first simple, [1][1] is its name
else: # just name
@@ -531,7 +531,7 @@ def restore_clr(p_name, p_class):
if not methods:
bases = p_class.__bases__
if len(bases) == 1 and p_name in dir(bases[0]):
- # skip inherited methods
+ # skip inherited methods
return None, None
return p_name + '(*args)', 'cannot find CLR method'
@@ -542,3 +542,31 @@ def restore_clr(p_name, p_class):
if not methods[0].IsStatic:
params = ['self'] + params
return build_signature(p_name, params), None
+
+def build_output_name(dirname, qualified_name):
+ qualifiers = qualified_name.split(".")
+ if dirname and not dirname.endswith("/") and not dirname.endswith("\\"):
+ dirname += os.path.sep # "a -> a/"
+ for pathindex in range(len(qualifiers) - 1): # create dirs for all qualifiers but last
+ subdirname = dirname + os.path.sep.join(qualifiers[0: pathindex + 1])
+ if not os.path.isdir(subdirname):
+ action("creating subdir %r", subdirname)
+ os.makedirs(subdirname)
+ init_py = os.path.join(subdirname, "__init__.py")
+ if os.path.isfile(subdirname + ".py"):
+ os.rename(subdirname + ".py", init_py)
+ elif not os.path.isfile(init_py):
+ init = fopen(init_py, "w")
+ init.close()
+ target_name = dirname + os.path.sep.join(qualifiers)
+ if os.path.isdir(target_name):
+ fname = os.path.join(target_name, "__init__.py")
+ else:
+ fname = target_name + ".py"
+
+ dirname = os.path.dirname(fname)
+
+ if not os.path.isdir(dirname):
+ os.makedirs(dirname)
+
+ return fname
diff --git a/python/helpers/tools/stdlib_packages.txt b/python/helpers/tools/stdlib_packages.txt
index 619651ebbec9..2ee4b5d22705 100644
--- a/python/helpers/tools/stdlib_packages.txt
+++ b/python/helpers/tools/stdlib_packages.txt
@@ -6,6 +6,7 @@ argparse
array
ast
asynchat
+asyncio
asyncore
atexit
audiodev
@@ -68,6 +69,8 @@ dummy_thread
dummy_threading
email
encodings
+ensurepip
+enum
errno
exceptions
fcntl
@@ -150,6 +153,7 @@ os
os2emxpath
ossaudiodev
parser
+pathlib
pdb
pickle
pickletools
@@ -194,6 +198,7 @@ robotparser
runpy
sched
select
+selectors
sets
sgmllib
sha
@@ -219,6 +224,7 @@ sre_parse
ssl
stat
statcache
+statistics
statvfs
string
StringIO
@@ -254,6 +260,7 @@ token
tokenize
trace
traceback
+tracemalloc
tty
turtle
turtledemo
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java
index e1084e826741..6bad8d10a6f8 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java
@@ -136,11 +136,13 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine
/**
* Finds a property with the specified name in the class or one of its ancestors.
*
+ *
* @param name of the property
+ * @param inherited
* @return descriptor of property accessors, or null if such property does not exist.
*/
@Nullable
- Property findProperty(@NotNull String name);
+ Property findProperty(@NotNull String name, boolean inherited);
/**
* Apply a processor to every method, looking at superclasses in method resolution order as needed.
diff --git a/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java b/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java
index 38a0ee670050..b4e5be8753d3 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java
@@ -30,7 +30,7 @@ public interface PyTypeProvider {
ExtensionPointName<PyTypeProvider> EP_NAME = ExtensionPointName.create("Pythonid.typeProvider");
@Nullable
- PyType getReferenceExpressionType(PyReferenceExpression referenceExpression, TypeEvalContext context);
+ PyType getReferenceExpressionType(@NotNull PyReferenceExpression referenceExpression, @NotNull TypeEvalContext context);
@Nullable
PyType getReferenceType(@NotNull PsiElement referenceTarget, TypeEvalContext context, @Nullable PsiElement anchor);
diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyOverridingAncestorsClassMembersProvider.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyOverridingAncestorsClassMembersProvider.java
new file mode 100644
index 000000000000..07b53091aba1
--- /dev/null
+++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyOverridingAncestorsClassMembersProvider.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.psi.types;
+
+/**
+ * @author vlan
+ */
+public interface PyOverridingAncestorsClassMembersProvider extends PyClassMembersProvider {
+}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java
index dc20bad8f36f..0792b5083542 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java
@@ -80,7 +80,7 @@ public class PyTypeProviderBase implements PyTypeProvider {
};
@Override
- public PyType getReferenceExpressionType(PyReferenceExpression referenceExpression, TypeEvalContext context) {
+ public PyType getReferenceExpressionType(@NotNull PyReferenceExpression referenceExpression, @NotNull TypeEvalContext context) {
return null;
}
diff --git a/python/src/META-INF/python-core.xml b/python/src/META-INF/python-core.xml
index f11f009b3a5c..708a686b6490 100644
--- a/python/src/META-INF/python-core.xml
+++ b/python/src/META-INF/python-core.xml
@@ -76,7 +76,7 @@
<applicationService serviceInterface="com.jetbrains.python.module.PyModuleService"
serviceImplementation="com.jetbrains.python.module.PyModuleServiceImpl"/>
- <typedHandler implementation="com.jetbrains.python.codeInsight.KeywordTypedHandler" id="pyCommaAfterKwd"/>
+ <typedHandler implementation="com.jetbrains.python.codeInsight.PyKeywordTypedHandler" id="pyCommaAfterKwd"/>
<typedHandler implementation="com.jetbrains.python.codeInsight.PyMethodNameTypedHandler" id="pyMethodNameTypedHandler"/>
<typedHandler implementation="com.jetbrains.python.editor.PythonSpaceHandler"/>
@@ -364,6 +364,8 @@
<applicationService serviceInterface="com.jetbrains.python.codeInsight.PyCodeInsightSettings"
serviceImplementation="com.jetbrains.python.codeInsight.PyCodeInsightSettings"/>
+ <applicationService serviceInterface="com.jetbrains.python.testing.PyTestFrameworkService"
+ serviceImplementation="com.jetbrains.python.testing.PyTestFrameworkService"/>
<autoImportOptionsProvider instance="com.jetbrains.python.codeInsight.imports.PyAutoImportOptions"/>
<defaultLiveTemplatesProvider implementation="com.jetbrains.python.codeInsight.liveTemplates.PyDefaultLiveTemplatesProvider"/>
diff --git a/python/src/com/jetbrains/python/codeInsight/KeywordTypedHandler.java b/python/src/com/jetbrains/python/codeInsight/PyKeywordTypedHandler.java
index 5e3e6ca68b1d..3bf094dcb2c8 100644
--- a/python/src/com/jetbrains/python/codeInsight/KeywordTypedHandler.java
+++ b/python/src/com/jetbrains/python/codeInsight/PyKeywordTypedHandler.java
@@ -30,7 +30,7 @@ import com.jetbrains.python.psi.PyStringLiteralExpression;
* User: dcheryasov
* Date: May 29, 2009 4:42:03 AM
*/
-public class KeywordTypedHandler extends TypedHandlerDelegate {
+public class PyKeywordTypedHandler extends TypedHandlerDelegate {
@Override
public Result beforeCharTyped(char character, Project project, Editor editor, PsiFile file, FileType fileType) {
if (!(fileType instanceof PythonFileType)) return Result.CONTINUE; // else we'd mess up with other file types!
@@ -51,7 +51,7 @@ public class KeywordTypedHandler extends TypedHandlerDelegate {
editor.getCaretModel().moveToOffset(offset + 1); // overtype, that is, jump over
return Result.STOP;
}
- UnindentingInsertHandler.unindentAsNeeded(project, editor, file);
+ PyUnindentingInsertHandler.unindentAsNeeded(project, editor, file);
}
return Result.CONTINUE; // the default
diff --git a/python/src/com/jetbrains/python/codeInsight/PyKeywords.java b/python/src/com/jetbrains/python/codeInsight/PyKeywords.java
new file mode 100644
index 000000000000..458715fbf6c4
--- /dev/null
+++ b/python/src/com/jetbrains/python/codeInsight/PyKeywords.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.codeInsight;
+
+/**
+ * @author traff
+ */
+public class PyKeywords {
+ public static final String DEF = "def";
+ public static final String CLASS = "class";
+
+ public static final String IF = "if";
+ public static final String ELSE = "else";
+ public static final String ELIF = "elif";
+
+ public static final String TRY = "try";
+ public static final String EXCEPT = "except";
+ public static final String FINALLY = "finally";
+
+ public static final String WHILE = "while";
+
+ public static final String FOR = "for";
+ public static final String WITH = "with";
+ public static final String AS = "as";
+
+ public static final String ASSERT = "assert";
+ public static final String DEL = "del";
+ public static final String EXEC = "exec";
+ public static final String FROM = "from";
+ public static final String IMPORT = "import";
+ public static final String RAISE = "raise";
+ public static final String PRINT = "print";
+ public static final String BREAK = "break";
+ public static final String CONTINUE = "continue";
+ public static final String GLOBAL = "global";
+ public static final String RETURN = "return";
+ public static final String YIELD = "yield";
+ public static final String NONLOCAL = "nonlocal";
+
+ public static final String AND = "and";
+ public static final String OR = "or";
+ public static final String IS = "is";
+ public static final String IN = "in";
+ public static final String NOT = "not";
+
+ public static final String LAMBDA = "lambda";
+
+ public static final String TRUE = "True";
+ public static final String FALSE = "False";
+ public static final String NONE = "None";
+}
diff --git a/python/src/com/jetbrains/python/codeInsight/UnindentingInsertHandler.java b/python/src/com/jetbrains/python/codeInsight/PyUnindentingInsertHandler.java
index cd2902666acb..c6a69d72e275 100644
--- a/python/src/com/jetbrains/python/codeInsight/UnindentingInsertHandler.java
+++ b/python/src/com/jetbrains/python/codeInsight/PyUnindentingInsertHandler.java
@@ -34,10 +34,10 @@ import com.jetbrains.python.psi.PyTryExceptStatement;
* User: dcheryasov
* Date: Mar 2, 2010 6:48:40 PM
*/
-public class UnindentingInsertHandler implements InsertHandler<PythonLookupElement> {
- public final static UnindentingInsertHandler INSTANCE = new UnindentingInsertHandler();
+public class PyUnindentingInsertHandler implements InsertHandler<PythonLookupElement> {
+ public final static PyUnindentingInsertHandler INSTANCE = new PyUnindentingInsertHandler();
- private UnindentingInsertHandler() {
+ private PyUnindentingInsertHandler() {
}
public void handleInsert(InsertionContext context, PythonLookupElement item) {
@@ -46,6 +46,7 @@ public class UnindentingInsertHandler implements InsertHandler<PythonLookupEleme
/**
* Unindent current line to be flush with a starting part, detecting the part if necessary.
+ *
* @param project
* @param editor
* @param file
@@ -56,7 +57,9 @@ public class UnindentingInsertHandler implements InsertHandler<PythonLookupEleme
final Document document = editor.getDocument();
int offset = editor.getCaretModel().getOffset();
CharSequence text = document.getCharsSequence();
- if (offset >= text.length()) offset = text.length() - 1;
+ if (offset >= text.length()) {
+ offset = text.length() - 1;
+ }
int line_start_offset = document.getLineStartOffset(document.getLineNumber(offset));
int nonspace_offset = findBeginning(line_start_offset, text);
@@ -64,26 +67,29 @@ public class UnindentingInsertHandler implements InsertHandler<PythonLookupEleme
Class<? extends PsiElement> parentClass = null;
- int last_offset = nonspace_offset + "finally".length(); // the longest of all
+ int last_offset = nonspace_offset + PyKeywords.FINALLY.length(); // the longest of all
if (last_offset > offset) last_offset = offset;
int local_length = last_offset - nonspace_offset + 1;
if (local_length > 0) {
- String piece = text.subSequence(nonspace_offset, last_offset+1).toString();
- final int else_len = "else".length();
+ String piece = text.subSequence(nonspace_offset, last_offset + 1).toString();
+ final int else_len = PyKeywords.ELSE.length();
if (local_length >= else_len) {
- if ((piece.startsWith("else") || piece.startsWith("elif")) && (else_len == piece.length() || piece.charAt(else_len) < 'a' || piece.charAt(else_len) > 'z')) {
+ if ((piece.startsWith(PyKeywords.ELSE) || piece.startsWith(PyKeywords.ELIF)) &&
+ (else_len == piece.length() || piece.charAt(else_len) < 'a' || piece.charAt(else_len) > 'z')) {
parentClass = PyStatementWithElse.class;
}
}
- final int except_len = "except".length();
+ final int except_len = PyKeywords.EXCEPT.length();
if (local_length >= except_len) {
- if (piece.startsWith("except") && (except_len == piece.length() || piece.charAt(except_len) < 'a' || piece.charAt(except_len) > 'z')) {
+ if (piece.startsWith(PyKeywords.EXCEPT) &&
+ (except_len == piece.length() || piece.charAt(except_len) < 'a' || piece.charAt(except_len) > 'z')) {
parentClass = PyTryExceptStatement.class;
}
}
- final int finally_len = "finally".length();
+ final int finally_len = PyKeywords.FINALLY.length();
if (local_length >= finally_len) {
- if (piece.startsWith("finally") && (finally_len == piece.length() || piece.charAt(finally_len) < 'a' || piece.charAt(finally_len) > 'z')) {
+ if (piece.startsWith(PyKeywords.FINALLY) &&
+ (finally_len == piece.length() || piece.charAt(finally_len) < 'a' || piece.charAt(finally_len) > 'z')) {
parentClass = PyTryExceptStatement.class;
}
}
@@ -94,14 +100,17 @@ public class UnindentingInsertHandler implements InsertHandler<PythonLookupEleme
PsiDocumentManager.getInstance(project).commitDocument(document); // reparse
- PsiElement token = file.findElementAt(offset-2); // -1 is our ':'; -2 is even safer.
+ PsiElement token = file.findElementAt(offset - 2); // -1 is our ':'; -2 is even safer.
PsiElement outer = PsiTreeUtil.getParentOfType(token, parentClass);
if (outer != null) {
int outer_offset = outer.getTextOffset();
int outer_indent = outer_offset - document.getLineStartOffset(document.getLineNumber(outer_offset));
assert outer_indent >= 0;
int current_indent = nonspace_offset - line_start_offset;
- EditorActionUtil.indentLine(project, editor, document.getLineNumber(offset), outer_indent - current_indent);
+ int indent = outer_indent - current_indent;
+ EditorActionUtil.indentLine(project, editor, document.getLineNumber(offset), editor.getSettings().isUseTabCharacter(project)
+ ? indent * editor.getSettings().getTabSize(project)
+ : indent);
return true;
}
return false;
diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java b/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java
index 44ef899aeff9..6d7202457e83 100644
--- a/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java
+++ b/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java
@@ -33,7 +33,8 @@ import com.intellij.util.ProcessingContext;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.PythonLanguage;
-import com.jetbrains.python.codeInsight.UnindentingInsertHandler;
+import com.jetbrains.python.codeInsight.PyKeywords;
+import com.jetbrains.python.codeInsight.PyUnindentingInsertHandler;
import com.jetbrains.python.documentation.doctest.PyDocstringFile;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NonNls;
@@ -286,9 +287,9 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
psiElement()
.inside(PyConditionalStatementPart.class)
.andOr(
- psiElement().afterLeaf(psiElement().withText("if")),
- psiElement().afterLeaf(psiElement().withText("elif")),
- psiElement().afterLeaf(psiElement().withText("while"))
+ psiElement().afterLeaf(psiElement().withText(PyKeywords.IF)),
+ psiElement().afterLeaf(psiElement().withText(PyKeywords.ELIF)),
+ psiElement().afterLeaf(psiElement().withText(PyKeywords.WHILE))
);
private static final PsiElementPattern.Capture<PsiElement> IN_IMPORT_STMT =
@@ -378,8 +379,8 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
protected void addCompletions(
@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result
) {
- putKeywords(result, TailType.NONE, "def", "class", "for", "if", "while", "with");
- putKeywords(result, TailType.CASE_COLON, "try");
+ putKeywords(result, TailType.NONE, PyKeywords.DEF, PyKeywords.CLASS, PyKeywords.FOR, PyKeywords.IF, PyKeywords.WHILE, PyKeywords.WITH);
+ putKeywords(result, TailType.CASE_COLON, PyKeywords.TRY);
}
}
);
@@ -402,13 +403,13 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
protected void addCompletions(
@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result
) {
- putKeywords(result, TailType.SPACE, "assert", "del", "exec", "from", "import", "raise");
+ putKeywords(result, TailType.SPACE, PyKeywords.ASSERT, PyKeywords.DEL, PyKeywords.EXEC, PyKeywords.FROM, PyKeywords.IMPORT, PyKeywords.RAISE);
putKeywords(result, TailType.NONE, PyNames.PASS);
}
}
);
- extend(CompletionType.BASIC, inStatement.andNot(PY3K), new PyKeywordCompletionProvider(TailType.SPACE, "print"));
+ extend(CompletionType.BASIC, inStatement.andNot(PY3K), new PyKeywordCompletionProvider(TailType.SPACE, PyKeywords.PRINT));
}
private void addBreak() {
@@ -421,7 +422,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.andNot(IN_ARG_LIST)
.and(IN_LOOP)
,
- new PyKeywordCompletionProvider(TailType.NONE, "break")
+ new PyKeywordCompletionProvider(TailType.NONE, PyKeywords.BREAK)
);
}
@@ -436,7 +437,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.andNot(IN_FINALLY_NO_LOOP)
.and(IN_LOOP)
,
- new PyKeywordCompletionProvider(TailType.NONE, "continue")
+ new PyKeywordCompletionProvider(TailType.NONE, PyKeywords.CONTINUE)
);
}
@@ -448,7 +449,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.and(IN_BEGIN_STMT)
.andNot(AFTER_QUALIFIER)
,
- new PyKeywordCompletionProvider("global", "return", "yield")
+ new PyKeywordCompletionProvider(PyKeywords.GLOBAL, PyKeywords.RETURN, PyKeywords.YIELD)
);
extend(
@@ -459,7 +460,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.and(PY3K)
.andNot(AFTER_QUALIFIER)
,
- new PyKeywordCompletionProvider("nonlocal")
+ new PyKeywordCompletionProvider(PyKeywords.NONLOCAL)
);
}
@@ -471,7 +472,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.andOr(IN_IF_BODY, AFTER_IF)
.andNot(AFTER_QUALIFIER).andNot(IN_STRING_LITERAL)
,
- new PyKeywordCompletionProvider(TailType.NONE, UnindentingInsertHandler.INSTANCE, "elif"));
+ new PyKeywordCompletionProvider(TailType.NONE, PyUnindentingInsertHandler.INSTANCE, PyKeywords.ELIF));
}
private void addWithinTry() {
@@ -487,8 +488,8 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
protected void addCompletions(
@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result
) {
- putKeyword("except", UnindentingInsertHandler.INSTANCE, TailType.NONE, result);
- putKeyword("finally", UnindentingInsertHandler.INSTANCE, TailType.CASE_COLON, result);
+ putKeyword(PyKeywords.EXCEPT, PyUnindentingInsertHandler.INSTANCE, TailType.NONE, result);
+ putKeyword(PyKeywords.FINALLY, PyUnindentingInsertHandler.INSTANCE, TailType.CASE_COLON, result);
}
}
);
@@ -502,7 +503,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.andOr(IN_COND_STMT, IN_EXCEPT_BODY, AFTER_COND_STMT_NO_ELSE, AFTER_LOOP_NO_ELSE, AFTER_EXCEPT)
.andNot(AFTER_QUALIFIER).andNot(IN_STRING_LITERAL)
,
- new PyKeywordCompletionProvider(TailType.CASE_COLON, UnindentingInsertHandler.INSTANCE, "else"));
+ new PyKeywordCompletionProvider(TailType.CASE_COLON, PyUnindentingInsertHandler.INSTANCE, PyKeywords.ELSE));
}
private void addInfixOperators() {
@@ -516,7 +517,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.andNot(AFTER_QUALIFIER).
andNot(IN_STRING_LITERAL).and(IN_BEGIN_STMT)
,
- new PyKeywordCompletionProvider("and", "or", "is", "in")
+ new PyKeywordCompletionProvider(PyKeywords.AND, PyKeywords.OR, PyKeywords.IS, PyKeywords.IN)
);
}
@@ -530,7 +531,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.andNot(IN_FUNCTION_HEADER)
.andNot(AFTER_QUALIFIER).andNot(IN_STRING_LITERAL)
,
- new PyKeywordCompletionProvider("not", "lambda")
+ new PyKeywordCompletionProvider(PyKeywords.NOT, PyKeywords.LAMBDA)
);
}
@@ -545,7 +546,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.andNot(AFTER_QUALIFIER)
.andNot(IN_FUNCTION_HEADER)
,
- new PyKeywordCompletionProvider(TailType.NONE, "True", "False", "None")
+ new PyKeywordCompletionProvider(TailType.NONE, PyKeywords.TRUE, PyKeywords.FALSE, PyKeywords.NONE)
);
}
@@ -556,7 +557,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.andOr(IN_IMPORT_AFTER_REF, IN_WITH_AFTER_REF, IN_EXCEPT_AFTER_REF)
.andNot(AFTER_QUALIFIER)
,
- new PyKeywordCompletionProvider("as")
+ new PyKeywordCompletionProvider(PyKeywords.AS)
);
}
@@ -567,7 +568,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.and(IN_FROM_IMPORT_AFTER_REF)
.andNot(AFTER_QUALIFIER)
,
- new PyKeywordCompletionProvider("import")
+ new PyKeywordCompletionProvider(PyKeywords.IMPORT)
);
}
@@ -603,9 +604,9 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.withLanguage(PythonLanguage.getInstance())
.afterLeafSkipping(psiElement().whitespace(),
psiElement().inside(psiElement(PyConditionalExpression.class))
- .and(psiElement().afterLeaf("if")))
+ .and(psiElement().afterLeaf(PyKeywords.IF)))
,
- new PyKeywordCompletionProvider(TailType.SPACE, "else"));
+ new PyKeywordCompletionProvider(TailType.SPACE, PyKeywords.ELSE));
}
private void addRaiseFrom() {
@@ -614,7 +615,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.withLanguage(PythonLanguage.getInstance())
.and(PY3K)
.afterLeaf(psiElement().inside(PyRaiseStatement.class)),
- new PyKeywordCompletionProvider("from"));
+ new PyKeywordCompletionProvider(PyKeywords.FROM));
}
private void addYieldFrom() {
@@ -623,7 +624,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.withLanguage(PythonLanguage.getInstance())
.and(PY3K)
.afterLeaf(psiElement().withElementType(PyTokenTypes.YIELD_KEYWORD)),
- new PyKeywordCompletionProvider("from"));
+ new PyKeywordCompletionProvider(PyKeywords.FROM));
}
public PyKeywordCompletionContributor() {
@@ -654,14 +655,14 @@ public class PyKeywordCompletionContributor extends CompletionContributor {
.withLanguage(PythonLanguage.getInstance())
.inside(psiElement(PySequenceExpression.class))
.andNot(psiElement().afterLeaf(or(psiElement(PyTokenTypes.LBRACE), psiElement(PyTokenTypes.LBRACKET), psiElement(PyTokenTypes.LPAR)))),
- new PyKeywordCompletionProvider("for"));
+ new PyKeywordCompletionProvider(PyKeywords.FOR));
}
private void addInToFor() {
extend(CompletionType.BASIC,
psiElement()
.withLanguage(PythonLanguage.getInstance())
- .and(psiElement()).afterLeaf(psiElement().afterLeaf("for")),
+ .and(psiElement()).afterLeaf(psiElement().afterLeaf(PyKeywords.FOR)),
new PyKeywordCompletionProvider("in"));
}
diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/ImportToggleAliasIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/ImportToggleAliasIntention.java
index f9f1ee19435a..6b79d2104f44 100644
--- a/python/src/com/jetbrains/python/codeInsight/intentions/ImportToggleAliasIntention.java
+++ b/python/src/com/jetbrains/python/codeInsight/intentions/ImportToggleAliasIntention.java
@@ -181,13 +181,16 @@ public class ImportToggleAliasIntention implements IntentionAction {
InjectedLanguageManager.getInstance(project).getInjectedPsiFiles(host);
if (files != null) {
for (Pair<PsiElement, TextRange> pair : files) {
- final ScopeOwner scopeOwner = (ScopeOwner)pair.getFirst();
- PsiTreeUtil.processElements(scopeOwner, new PsiElementProcessor() {
- public boolean execute(@NotNull PsiElement element) {
- getReferences(element);
- return true;
- }
- });
+ final PsiElement first = pair.getFirst();
+ if (first instanceof ScopeOwner) {
+ final ScopeOwner scopeOwner = (ScopeOwner)first;
+ PsiTreeUtil.processElements(scopeOwner, new PsiElementProcessor() {
+ public boolean execute(@NotNull PsiElement element) {
+ getReferences(element);
+ return true;
+ }
+ });
+ }
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
index cf6b9ef19301..9e2989e09650 100644
--- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
@@ -37,7 +37,8 @@ import java.util.Set;
* @author yole
*/
public class PyStdlibTypeProvider extends PyTypeProviderBase {
- private static final Set<String> OPEN_FUNCTIONS = ImmutableSet.of("__builtin__.open", "io.open", "os.fdopen");
+ private static final Set<String> OPEN_FUNCTIONS = ImmutableSet.of("__builtin__.open", "io.open", "os.fdopen",
+ "pathlib.Path.open");
private static final String BINARY_FILE_TYPE = "io.FileIO[bytes]";
private static final String TEXT_FILE_TYPE = "io.TextIOWrapper[unicode]";
@@ -134,7 +135,10 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
for (Map.Entry<PyExpression, PyNamedParameter> entry : arguments.entrySet()) {
final PyNamedParameter parameter = entry.getValue();
if ("mode".equals(parameter.getName())) {
- final PyExpression argument = entry.getKey();
+ PyExpression argument = entry.getKey();
+ if (argument instanceof PyKeywordArgument) {
+ argument = ((PyKeywordArgument)argument).getValueExpression();
+ }
if (argument instanceof PyStringLiteralExpression) {
mode = ((PyStringLiteralExpression)argument).getStringValue();
break;
diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java
index a35d8fd74444..5ac7fc10751c 100644
--- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java
@@ -22,6 +22,7 @@ import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyTargetExpression;
import com.jetbrains.python.psi.types.PyClassMembersProviderBase;
import com.jetbrains.python.psi.types.PyClassType;
+import com.jetbrains.python.psi.types.PyOverridingAncestorsClassMembersProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,7 +34,7 @@ import java.util.List;
/**
* @author vlan
*/
-public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderBase {
+public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderBase implements PyOverridingAncestorsClassMembersProvider {
@NotNull
@Override
public Collection<PyDynamicMember> getMembers(@NotNull PyClassType classType, PsiElement location) {
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
index 947b3c958e78..c7b9ceb88d2e 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
@@ -50,6 +50,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.encoding.EncodingManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.tree.FileElement;
@@ -61,16 +62,11 @@ import com.intellij.util.IJSwingUtilities;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.net.NetUtils;
import com.intellij.util.ui.UIUtil;
-import com.intellij.xdebugger.impl.frame.XStandaloneVariablesView;
import com.jetbrains.python.PythonHelpersLocator;
import com.jetbrains.python.console.completion.PydevConsoleElement;
import com.jetbrains.python.console.parsing.PythonConsoleData;
import com.jetbrains.python.console.pydev.ConsoleCommunication;
-import com.jetbrains.python.console.pydev.ConsoleCommunicationListener;
-import com.jetbrains.python.debugger.PyDebuggerEditorsProvider;
import com.jetbrains.python.debugger.PySourcePosition;
-import com.jetbrains.python.debugger.PyStackFrame;
-import com.jetbrains.python.debugger.PyStackFrameInfo;
import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
import com.jetbrains.python.run.ProcessRunner;
import com.jetbrains.python.run.PythonCommandLineState;
@@ -84,8 +80,8 @@ import org.jetbrains.annotations.Nullable;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
+import java.nio.charset.Charset;
import java.util.*;
-import java.util.List;
import static com.jetbrains.python.sdk.PythonEnvUtil.setPythonIOEncoding;
import static com.jetbrains.python.sdk.PythonEnvUtil.setPythonUnbuffered;
@@ -134,7 +130,11 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
}
public static Map<String, String> addDefaultEnvironments(Sdk sdk, Map<String, String> envs) {
- setPythonIOEncoding(setPythonUnbuffered(envs), "utf-8");
+ Charset defaultCharset = EncodingManager.getInstance().getDefaultCharset();
+
+ final String encoding = defaultCharset != null ? defaultCharset.name() : "utf-8";
+ setPythonIOEncoding(setPythonUnbuffered(envs), encoding);
+
PythonSdkFlavor.initPythonPath(envs, true, PythonCommandLineState.getAddedPaths(sdk));
return envs;
}
@@ -304,7 +304,8 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
PYDEV_PYDEVCONSOLE_PY)
.getPath(),
PySourcePosition.isWindowsPath(
- data.getInterpreterPath())));
+ data.getInterpreterPath())
+ ));
commandLine.getParametersList().set(2, "0");
commandLine.getParametersList().set(3, "0");
@@ -570,7 +571,7 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
new PydevConsoleExecuteActionHandler(getConsoleView(), getProcessHandler(), myPydevConsoleCommunication);
myConsoleExecuteActionHandler.setEnabled(false);
myHistoryController = new ConsoleHistoryController(myConsoleType.getTypeId(), "", getLanguageConsole(),
- myConsoleExecuteActionHandler.getConsoleHistoryModel());
+ myConsoleExecuteActionHandler.getConsoleHistoryModel());
myHistoryController.install();
return myConsoleExecuteActionHandler;
}
diff --git a/python/src/com/jetbrains/python/documentation/DocStringParameterReference.java b/python/src/com/jetbrains/python/documentation/DocStringParameterReference.java
index 9e4e63d8dcf4..5f7a2ee2bb0f 100644
--- a/python/src/com/jetbrains/python/documentation/DocStringParameterReference.java
+++ b/python/src/com/jetbrains/python/documentation/DocStringParameterReference.java
@@ -38,9 +38,9 @@ import java.util.Set;
* @author yole
*/
public class DocStringParameterReference extends PsiReferenceBase<PsiElement> implements PsiReferenceEx {
- private final String myType;
+ private final StructuredDocStringBase.ReferenceType myType;
- public DocStringParameterReference(PsiElement element, TextRange range, String refType) {
+ public DocStringParameterReference(PsiElement element, TextRange range, StructuredDocStringBase.ReferenceType refType) {
super(element, range);
myType = refType;
}
@@ -55,26 +55,42 @@ public class DocStringParameterReference extends PsiReferenceBase<PsiElement> im
final PyFunction init = ((PyClass)owner).findMethodByName(PyNames.INIT, false);
if (init != null) {
PsiElement element = resolveParameter(init);
- if (element == null)
- element = resolveClassVariable(owner);
+ if (element == null && (myType.equals(StructuredDocStringBase.ReferenceType.CLASS_VARIABLE) ||
+ myType.equals(StructuredDocStringBase.ReferenceType.PARAMETER_TYPE)))
+ element = resolveClassVariable((PyClass)owner);
+ if (element == null && (myType.equals(StructuredDocStringBase.ReferenceType.INSTANCE_VARIABLE) ||
+ myType.equals(StructuredDocStringBase.ReferenceType.PARAMETER_TYPE)))
+ element = resolveInstanceVariable((PyClass)owner);
return element;
}
else {
- return resolveClassVariable(owner);
+ if (myType.equals(StructuredDocStringBase.ReferenceType.CLASS_VARIABLE) ||
+ myType.equals(StructuredDocStringBase.ReferenceType.PARAMETER_TYPE))
+ return resolveClassVariable((PyClass)owner);
+ if (myType.equals(StructuredDocStringBase.ReferenceType.INSTANCE_VARIABLE) ||
+ myType.equals(StructuredDocStringBase.ReferenceType.PARAMETER_TYPE))
+ return resolveInstanceVariable((PyClass)owner);
}
}
return null;
}
@Nullable
- private PsiElement resolveClassVariable(final PyDocStringOwner owner) {
- final PyStatementList statementList = ((PyClass)owner).getStatementList();
- for (PsiElement element : statementList.getChildren()) {
- if (element instanceof PyAssignmentStatement) {
- final PyExpression[] targets = ((PyAssignmentStatement)element).getTargets();
- if (targets.length > 0 && targets[0].getText().equals(getCanonicalText()))
- return targets[0];
- }
+ private PsiElement resolveInstanceVariable(final PyClass owner) {
+ final List<PyTargetExpression> attributes = owner.getInstanceAttributes();
+ for (PyTargetExpression element : attributes) {
+ if (getCanonicalText().equals(element.getName()))
+ return element;
+ }
+ return null;
+ }
+
+ @Nullable
+ private PsiElement resolveClassVariable(@NotNull final PyClass owner) {
+ final List<PyTargetExpression> attributes = owner.getClassAttributes();
+ for (PyTargetExpression element : attributes) {
+ if (getCanonicalText().equals(element.getName()))
+ return element;
}
return null;
}
@@ -123,7 +139,7 @@ public class DocStringParameterReference extends PsiReferenceBase<PsiElement> im
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
- public String getType() {
+ public StructuredDocStringBase.ReferenceType getType() {
return myType;
}
diff --git a/python/src/com/jetbrains/python/documentation/DocStringReferenceProvider.java b/python/src/com/jetbrains/python/documentation/DocStringReferenceProvider.java
index 2891726d54cf..d1d8033b15b0 100644
--- a/python/src/com/jetbrains/python/documentation/DocStringReferenceProvider.java
+++ b/python/src/com/jetbrains/python/documentation/DocStringReferenceProvider.java
@@ -61,16 +61,22 @@ public class DocStringReferenceProvider extends PsiReferenceProvider {
if (docString != null) {
result.addAll(referencesFromNames(element, offset, docString,
docString.getTagArguments(StructuredDocStringBase.PARAM_TAGS),
- StructuredDocStringBase.PARAMETER));
+ StructuredDocStringBase.ReferenceType.PARAMETER));
result.addAll(referencesFromNames(element, offset, docString,
docString.getTagArguments(StructuredDocStringBase.PARAM_TYPE_TAGS),
- StructuredDocStringBase.PARAMETER_TYPE));
+ StructuredDocStringBase.ReferenceType.PARAMETER_TYPE));
result.addAll(referencesFromNames(element, offset, docString,
- docString.getKeywordArgumentSubstrings(), StructuredDocStringBase.KEYWORD));
+ docString.getKeywordArgumentSubstrings(), StructuredDocStringBase.ReferenceType.KEYWORD));
result.addAll(referencesFromNames(element, offset, docString,
- docString.getTagArguments(StructuredDocStringBase.VARIABLE_TAGS),
- StructuredDocStringBase.VARIABLE));
+ docString.getTagArguments("var"),
+ StructuredDocStringBase.ReferenceType.VARIABLE));
+ result.addAll(referencesFromNames(element, offset, docString,
+ docString.getTagArguments("cvar"),
+ StructuredDocStringBase.ReferenceType.CLASS_VARIABLE));
+ result.addAll(referencesFromNames(element, offset, docString,
+ docString.getTagArguments("ivar"),
+ StructuredDocStringBase.ReferenceType.INSTANCE_VARIABLE));
result.addAll(returnTypes(element, docString, offset));
}
return result.toArray(new PsiReference[result.size()]);
@@ -94,7 +100,7 @@ public class DocStringReferenceProvider extends PsiReferenceProvider {
int offset,
StructuredDocString docString,
List<Substring> paramNames,
- String refType) {
+ StructuredDocStringBase.ReferenceType refType) {
List<PsiReference> result = new ArrayList<PsiReference>();
for (Substring name : paramNames) {
final String s = name.toString();
@@ -102,7 +108,7 @@ public class DocStringReferenceProvider extends PsiReferenceProvider {
final TextRange range = name.getTextRange().shiftRight(offset);
result.add(new DocStringParameterReference(element, range, refType));
}
- if (refType.equals(StructuredDocStringBase.PARAMETER_TYPE)) {
+ if (refType.equals(StructuredDocStringBase.ReferenceType.PARAMETER_TYPE)) {
final Substring type = docString.getParamTypeSubstring(s);
if (type != null) {
result.addAll(parseTypeReferences(element, type, offset));
diff --git a/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java b/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java
index ec4becc5cc1f..4c3432c7e84a 100644
--- a/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java
+++ b/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java
@@ -95,7 +95,7 @@ class PyDocumentationBuilder {
PyType type = context.getType(qual);
if (type instanceof PyClassType) {
cls = ((PyClassType)type).getPyClass();
- Property property = cls.findProperty(elementName);
+ Property property = cls.findProperty(elementName, true);
if (property != null) {
is_property = true;
final AccessDirection dir = AccessDirection.of((PyElement)outer);
diff --git a/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java b/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java
index 0e3d9e35385e..9f6cecba7a84 100644
--- a/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java
+++ b/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java
@@ -50,11 +50,9 @@ public abstract class StructuredDocStringBase implements StructuredDocString {
public static String[] RAISES_TAGS = new String[] { "raises", "raise", "except", "exception" };
public static String[] RETURN_TAGS = new String[] { "return", "returns" };
- public static String PARAMETER = "parameter";
+ public enum ReferenceType {PARAMETER, PARAMETER_TYPE, KEYWORD, VARIABLE, CLASS_VARIABLE, INSTANCE_VARIABLE}
+
public static String TYPE = "type";
- public static String PARAMETER_TYPE = "parameter_type";
- public static String KEYWORD = "keyword";
- public static String VARIABLE = "variable";
protected StructuredDocStringBase(@NotNull String docStringText, String tagPrefix) {
final Substring docString = new Substring(docStringText);
diff --git a/python/src/com/jetbrains/python/formatter/PyBlock.java b/python/src/com/jetbrains/python/formatter/PyBlock.java
index 2a7343dda3ed..8afd35e009f2 100644
--- a/python/src/com/jetbrains/python/formatter/PyBlock.java
+++ b/python/src/com/jetbrains/python/formatter/PyBlock.java
@@ -153,7 +153,9 @@ public class PyBlock implements ASTBlock {
if (ourListElementTypes.contains(parentType)) {
// wrapping in non-parenthesized tuple expression is not allowed (PY-1792)
if ((parentType != PyElementTypes.TUPLE_EXPRESSION || grandparentType == PyElementTypes.PARENTHESIZED_EXPRESSION) &&
- !ourBrackets.contains(childType) && childType != PyTokenTypes.COMMA && !isSliceOperand(child) /*&& !isSubscriptionOperand(child)*/) {
+ !ourBrackets.contains(childType) &&
+ childType != PyTokenTypes.COMMA &&
+ !isSliceOperand(child) /*&& !isSubscriptionOperand(child)*/) {
wrap = Wrap.createWrap(WrapType.NORMAL, true);
}
if (needListAlignment(child) && !isEmptyList(_node.getPsi())) {
@@ -161,8 +163,9 @@ public class PyBlock implements ASTBlock {
}
}
else if (parentType == PyElementTypes.BINARY_EXPRESSION &&
- (PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens().contains(childType) || PyTokenTypes.OPERATIONS.contains(childType))) {
- if (isInControlStatement() ) {
+ (PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens().contains(childType) ||
+ PyTokenTypes.OPERATIONS.contains(childType))) {
+ if (isInControlStatement()) {
PyParenthesizedExpression parens = PsiTreeUtil.getParentOfType(_node.getPsi(), PyParenthesizedExpression.class, true,
PyStatementPart.class);
childIndent = parens != null ? Indent.getNormalIndent() : Indent.getContinuationIndent();
@@ -196,7 +199,7 @@ public class PyBlock implements ASTBlock {
}
}
else if (parentType == PyElementTypes.DICT_LITERAL_EXPRESSION || parentType == PyElementTypes.SET_LITERAL_EXPRESSION ||
- parentType == PyElementTypes.SET_COMP_EXPRESSION || parentType == PyElementTypes.DICT_COMP_EXPRESSION) {
+ parentType == PyElementTypes.SET_COMP_EXPRESSION || parentType == PyElementTypes.DICT_COMP_EXPRESSION) {
if (childType == PyTokenTypes.RBRACE || !hasLineBreaksBefore(child, 1)) {
childIndent = Indent.getNoneIndent();
}
@@ -210,18 +213,22 @@ public class PyBlock implements ASTBlock {
}
}
else if (parentType == PyElementTypes.FROM_IMPORT_STATEMENT) {
- if ((childType == PyElementTypes.IMPORT_ELEMENT || childType == PyTokenTypes.RPAR) &&
- _node.findChildByType(PyTokenTypes.LPAR) != null) {
- if (myContext.getPySettings().ALIGN_MULTILINE_IMPORTS) {
- childAlignment = getAlignmentForChildren();
+ if (_node.findChildByType(PyTokenTypes.LPAR) != null) {
+ if (childType == PyElementTypes.IMPORT_ELEMENT) {
+ if (myContext.getPySettings().ALIGN_MULTILINE_IMPORTS) {
+ childAlignment = getAlignmentForChildren();
+ }
+ else {
+ childIndent = Indent.getNormalIndent();
+ }
}
- else {
- childIndent = Indent.getNormalIndent();
+ if (childType == PyTokenTypes.RPAR) {
+ childIndent = Indent.getNoneIndent();
}
}
}
else if (parentType == PyElementTypes.KEY_VALUE_EXPRESSION) {
- PyKeyValueExpression keyValue = (PyKeyValueExpression) _node.getPsi();
+ PyKeyValueExpression keyValue = (PyKeyValueExpression)_node.getPsi();
if (keyValue != null && child.getPsi() == keyValue.getValue()) {
childIndent = Indent.getNormalIndent();
}
@@ -255,7 +262,7 @@ public class PyBlock implements ASTBlock {
while (prev != null && prev.getElementType() == TokenType.WHITE_SPACE) {
if (prev.getText().contains("\\") && !childIndent.equals(Indent.getContinuationIndent()) &&
!childIndent.equals(Indent.getContinuationIndent(true))) {
- childIndent = Indent.getNormalIndent();
+ childIndent = isIndentNext(child) ? Indent.getContinuationIndent() : Indent.getNormalIndent();
break;
}
prev = prev.getTreePrev();
@@ -264,9 +271,22 @@ public class PyBlock implements ASTBlock {
return new PyBlock(this, child, childAlignment, childIndent, wrap, myContext);
}
+ private static boolean isIndentNext(ASTNode child) {
+ PsiElement psi = PsiTreeUtil.getParentOfType(child.getPsi(), PyStatement.class);
+
+ return psi instanceof PyIfStatement ||
+ psi instanceof PyForStatement ||
+ psi instanceof PyWithStatement ||
+ psi instanceof PyClass ||
+ psi instanceof PyFunction ||
+ psi instanceof PyTryExceptStatement ||
+ psi instanceof PyElsePart ||
+ psi instanceof PyIfPart;
+ }
+
private static boolean isSubscriptionOperand(ASTNode child) {
return child.getTreeParent().getElementType() == PyElementTypes.SUBSCRIPTION_EXPRESSION &&
- child.getPsi() == ((PySubscriptionExpression) child.getTreeParent().getPsi()).getOperand();
+ child.getPsi() == ((PySubscriptionExpression)child.getTreeParent().getPsi()).getOperand();
}
private boolean isInControlStatement() {
@@ -285,10 +305,10 @@ public class PyBlock implements ASTBlock {
private static boolean isEmptyList(PsiElement psi) {
if (psi instanceof PyDictLiteralExpression) {
- return ((PyDictLiteralExpression) psi).getElements().length == 0;
+ return ((PyDictLiteralExpression)psi).getElements().length == 0;
}
if (psi instanceof PySequenceExpression) {
- return ((PySequenceExpression) psi).getElements().length == 0;
+ return ((PySequenceExpression)psi).getElements().length == 0;
}
return false;
}
@@ -322,7 +342,9 @@ public class PyBlock implements ASTBlock {
}
if (PyTokenTypes.CLOSE_BRACES.contains(childType)) {
ASTNode prevNonSpace = findPrevNonSpaceNode(child);
- if (prevNonSpace != null && prevNonSpace.getElementType() == PyTokenTypes.COMMA && myContext.getMode() == FormattingMode.ADJUST_INDENT) {
+ if (prevNonSpace != null &&
+ prevNonSpace.getElementType() == PyTokenTypes.COMMA &&
+ myContext.getMode() == FormattingMode.ADJUST_INDENT) {
return true;
}
return false;
@@ -358,7 +380,8 @@ public class PyBlock implements ASTBlock {
private static ASTNode findPrevNonSpaceNode(ASTNode node) {
do {
node = node.getTreePrev();
- } while(node != null && (node.getElementType() == TokenType.WHITE_SPACE || PyTokenTypes.WHITESPACE.contains(node.getElementType())));
+ }
+ while (node != null && (node.getElementType() == TokenType.WHITE_SPACE || PyTokenTypes.WHITESPACE.contains(node.getElementType())));
return node;
}
@@ -372,7 +395,7 @@ public class PyBlock implements ASTBlock {
if (node != null && node.getElementType() == TokenType.WHITE_SPACE) {
String prevNodeText = node.getText();
int count = 0;
- for(int i=0; i<prevNodeText.length(); i++) {
+ for (int i = 0; i < prevNodeText.length(); i++) {
if (prevNodeText.charAt(i) == '\n') {
count++;
if (count == minCount) {
@@ -429,10 +452,32 @@ public class PyBlock implements ASTBlock {
return Spacing.createSpacing(0, 0, 1, true, myContext.getSettings().KEEP_BLANK_LINES_IN_CODE);
}
}
+
+ if ((node1.getElementType() == PyElementTypes.FUNCTION_DECLARATION || node1.getElementType() == PyElementTypes.CLASS_DECLARATION)
+ && _node.getElementType() instanceof PyFileElementType) {
+
+ if (psi2 instanceof PsiComment) {
+ final PsiElement psi3 = PsiTreeUtil.getNextSiblingOfType(psi2, PyElement.class);
+
+ if (psi3 != null) {
+ IElementType type3 = psi3.getNode().getElementType();
+
+ if (type3 == PyElementTypes.CLASS_DECLARATION || type3 == PyElementTypes.FUNCTION_DECLARATION) {
+ return getBlankLinesForOption(myContext.getPySettings().BLANK_LINES_AROUND_TOP_LEVEL_CLASSES_FUNCTIONS);
+ }
+ }
+ }
+ }
}
return myContext.getSpacingBuilder().getSpacing(this, child1, child2);
}
+ private Spacing getBlankLinesForOption(final int option) {
+ int blankLines = option + 1;
+ return Spacing
+ .createSpacing(0, 0, blankLines, myContext.getSettings().KEEP_LINE_BREAKS, myContext.getSettings().KEEP_BLANK_LINES_IN_DECLARATIONS);
+ }
+
private boolean needLineBreakInStatement() {
PyStatement statement = PsiTreeUtil.getParentOfType(_node.getPsi(), PyStatement.class);
if (statement != null) {
@@ -614,7 +659,7 @@ public class PyBlock implements ASTBlock {
}
if (afterNode != null && afterNode.getElementType() == PyElementTypes.KEY_VALUE_EXPRESSION) {
- PyKeyValueExpression keyValue = (PyKeyValueExpression) afterNode.getPsi();
+ PyKeyValueExpression keyValue = (PyKeyValueExpression)afterNode.getPsi();
if (keyValue != null && keyValue.getValue() == null) { // incomplete
return Indent.getContinuationIndent();
}
diff --git a/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java b/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java
index 97a5a365f2ea..6faea31eabcb 100644
--- a/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java
@@ -68,32 +68,29 @@ public class PyArgumentListInspection extends PyInspection {
@Override
public void visitPyDecoratorList(final PyDecoratorList node) {
- PyDecorator[] decos = node.getDecorators();
- for (PyDecorator deco : decos) {
- if (! deco.hasArgumentList()) {
- // empty arglist; deco function must have a non-kwarg first arg
- PyCallExpression.PyMarkedCallee mkfunc = deco.resolveCallee(resolveWithoutImplicits());
- if (mkfunc != null && !mkfunc.isImplicitlyResolved()) {
- Callable callable = mkfunc.getCallable();
- int first_param_offset = mkfunc.getImplicitOffset();
- final List<PyParameter> params = PyUtil.getParameters(callable, myTypeEvalContext);
- final PyNamedParameter alleged_first_param = params.size() < first_param_offset ?
- null : params.get(first_param_offset-1).getAsNamed();
- if (alleged_first_param == null || alleged_first_param.isKeywordContainer()) {
- // no parameters left to pass function implicitly, or wrong param type
- registerProblem(deco, PyBundle.message("INSP.func.$0.lacks.first.arg", callable.getName())); // TODO: better names for anon lambdas
- }
- else {
- // possible unfilled params
- for (int i=first_param_offset; i < params.size(); i += 1) {
- PyNamedParameter par = params.get(i).getAsNamed();
- // param tuples, non-starred or non-default won't do
- if (par == null || (! par.isKeywordContainer() && ! par.isPositionalContainer() && !par.hasDefaultValue())) {
- String par_name;
- if (par != null) par_name = par.getName();
- else par_name = "(...)"; // can't be bothered to find the first non-tuple inside it
- registerProblem(deco, PyBundle.message("INSP.parameter.$0.unfilled", par_name));
- }
+ PyDecorator[] decorators = node.getDecorators();
+ for (PyDecorator deco : decorators) {
+ if (deco.hasArgumentList()) continue;
+ final PyCallExpression.PyMarkedCallee markedCallee = deco.resolveCallee(resolveWithoutImplicits());
+ if (markedCallee != null && !markedCallee.isImplicitlyResolved()) {
+ final Callable callable = markedCallee.getCallable();
+ int firstParamOffset = markedCallee.getImplicitOffset();
+ final List<PyParameter> params = PyUtil.getParameters(callable, myTypeEvalContext);
+ final PyNamedParameter allegedFirstParam = params.size() < firstParamOffset ?
+ null : params.get(firstParamOffset-1).getAsNamed();
+ if (allegedFirstParam == null || allegedFirstParam.isKeywordContainer()) {
+ // no parameters left to pass function implicitly, or wrong param type
+ registerProblem(deco, PyBundle.message("INSP.func.$0.lacks.first.arg", callable.getName())); // TODO: better names for anon lambdas
+ }
+ else { // possible unfilled params
+ for (int i = firstParamOffset; i < params.size(); i += 1) {
+ final PyParameter parameter = params.get(i);
+ if (parameter instanceof PySingleStarParameter) continue;
+ final PyNamedParameter par = parameter.getAsNamed();
+ // param tuples, non-starred or non-default won't do
+ if (par == null || (!par.isKeywordContainer() && !par.isPositionalContainer() &&!par.hasDefaultValue())) {
+ String parameterName = par != null ? par.getName() : "(...)";
+ registerProblem(deco, PyBundle.message("INSP.parameter.$0.unfilled", parameterName));
}
}
}
diff --git a/python/src/com/jetbrains/python/inspections/PyAttributeOutsideInitInspection.java b/python/src/com/jetbrains/python/inspections/PyAttributeOutsideInitInspection.java
index c94ab8daaafb..791a1b52d38b 100644
--- a/python/src/com/jetbrains/python/inspections/PyAttributeOutsideInitInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyAttributeOutsideInitInspection.java
@@ -100,7 +100,7 @@ public class PyAttributeOutsideInitInspection extends PyInspection {
for (Map.Entry<String, PyTargetExpression> attribute : attributes.entrySet()) {
String attributeName = attribute.getKey();
if (attributeName == null) continue;
- final Property property = containingClass.findProperty(attributeName);
+ final Property property = containingClass.findProperty(attributeName, true);
if (!attributesInInit.containsKey(attributeName) && property == null) {
registerProblem(attribute.getValue(), PyBundle.message("INSP.attribute.$0.outside.init", attributeName),
new PyMoveAttributeToInitQuickFix());
diff --git a/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java b/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java
index 425c58519486..8e48067578cb 100644
--- a/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java
@@ -86,7 +86,7 @@ public class PyPropertyAccessInspection extends PyInspection {
property = myPropertyCache.get(key);
}
else {
- property = cls.findProperty(name);
+ property = cls.findProperty(name, true);
}
myPropertyCache.put(key, property); // we store nulls, too, to know that a property does not exist
if (property != null) {
diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
index 4005b42dccdc..998530a016b3 100644
--- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
@@ -695,7 +695,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
if (overridesGetAttr(cls, myTypeEvalContext)) {
return true;
}
- if (cls.findProperty(name) != null) {
+ if (cls.findProperty(name, true) != null) {
return true;
}
if (PyUtil.hasUnresolvedAncestors(cls, myTypeEvalContext)) {
diff --git a/python/src/com/jetbrains/python/inspections/PyUnusedLocalInspectionVisitor.java b/python/src/com/jetbrains/python/inspections/PyUnusedLocalInspectionVisitor.java
index f770c5d11616..f7883535d2e6 100644
--- a/python/src/com/jetbrains/python/inspections/PyUnusedLocalInspectionVisitor.java
+++ b/python/src/com/jetbrains/python/inspections/PyUnusedLocalInspectionVisitor.java
@@ -207,7 +207,8 @@ public class PyUnusedLocalInspectionVisitor extends PyInspectionVisitor {
owner.acceptChildren(new PyRecursiveElementVisitor(){
@Override
public void visitPyCallExpression(final PyCallExpression node) {
- if ("locals".equals(node.getCallee().getName())){
+ final PyExpression callee = node.getCallee();
+ if (callee != null && "locals".equals(callee.getName())){
throw new DontPerformException();
}
node.acceptChildren(this); // look at call expr in arguments
@@ -290,7 +291,7 @@ public class PyUnusedLocalInspectionVisitor extends PyInspectionVisitor {
isEmpty = isEmptyFunction(func);
emptyFunctions.put(func, isEmpty);
}
- if (isEmpty) {
+ if (isEmpty && !mayBeField) {
continue;
}
}
diff --git a/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java
index e888add9acac..89de355bb87a 100644
--- a/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java
+++ b/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java
@@ -66,20 +66,18 @@ public class AddFieldQuickFix implements LocalQuickFix {
@Nullable
public static PsiElement appendToMethod(PyFunction init, Function<String, PyStatement> callback) {
// add this field as the last stmt of the constructor
- final PyStatementList stmt_list = init.getStatementList();
- PyStatement[] stmts = stmt_list.getStatements(); // NOTE: rather wasteful, consider iterable stmt list
- PyStatement last_stmt = null;
- if (stmts.length > 0) last_stmt = stmts[stmts.length-1];
+ final PyStatementList statementList = init.getStatementList();
+ assert statementList != null;
// name of 'self' may be different for fancier styles
PyParameter[] params = init.getParameterList().getParameters();
- String self_name = PyNames.CANONICAL_SELF;
+ String selfName = PyNames.CANONICAL_SELF;
if (params.length > 0) {
- self_name = params[0].getName();
+ selfName = params[0].getName();
}
- PyStatement new_stmt = callback.fun(self_name);
- if (!FileModificationService.getInstance().preparePsiElementForWrite(stmt_list)) return null;
- final PsiElement result = stmt_list.addAfter(new_stmt, last_stmt);
- PyPsiUtils.removeRedundantPass(stmt_list);
+ PyStatement newStmt = callback.fun(selfName);
+ if (!FileModificationService.getInstance().preparePsiElementForWrite(statementList)) return null;
+ final PsiElement result = PyUtil.addElementToStatementList(newStmt, statementList, true);
+ PyPsiUtils.removeRedundantPass(statementList);
return result;
}
diff --git a/python/src/com/jetbrains/python/inspections/quickfix/AddGlobalQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/AddGlobalQuickFix.java
index 349a9116466a..9bf3df0661b9 100644
--- a/python/src/com/jetbrains/python/inspections/quickfix/AddGlobalQuickFix.java
+++ b/python/src/com/jetbrains/python/inspections/quickfix/AddGlobalQuickFix.java
@@ -80,6 +80,7 @@ public class AddGlobalQuickFix implements LocalQuickFix {
statementList = ((PyFunction)owner).getStatementList();
if (((PyFunction)owner).getDocStringExpression() != null) hasDocString = true;
}
+ assert statementList != null;
PyStatement first = statementList.getStatements()[0];
if (hasDocString)
first = statementList.getStatements()[1];
diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java
index e939857703d2..0cd299422694 100644
--- a/python/src/com/jetbrains/python/psi/PyUtil.java
+++ b/python/src/com/jetbrains/python/psi/PyUtil.java
@@ -44,6 +44,7 @@ import com.intellij.psi.*;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.QualifiedName;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
@@ -60,7 +61,6 @@ import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
import com.jetbrains.python.codeInsight.stdlib.PyNamedTupleType;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.impl.PyPsiUtils;
-import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.QualifiedResolveResult;
import com.jetbrains.python.psi.types.*;
@@ -1313,13 +1313,31 @@ public class PyUtil {
final PyStatement[] statements = statementList.getStatements();
if (toTheBeginning && statements.length > 0) {
final PyDocStringOwner docStringOwner = PsiTreeUtil.getParentOfType(statementList, PyDocStringOwner.class);
- final PyStatement firstStatement = statements[0];
- if (docStringOwner != null && firstStatement instanceof PyExpressionStatement &&
- ((PyExpressionStatement)firstStatement).getExpression() == docStringOwner.getDocStringExpression()) {
- element = statementList.addAfter(element, firstStatement);
+ PyStatement anchor = statements[0];
+ if (docStringOwner != null && anchor instanceof PyExpressionStatement &&
+ ((PyExpressionStatement)anchor).getExpression() == docStringOwner.getDocStringExpression()) {
+ final PyStatement next = PsiTreeUtil.getNextSiblingOfType(anchor, PyStatement.class);
+ if (next == null) {
+ return statementList.addAfter(element, anchor);
+ }
+ anchor = next;
+ }
+ while (anchor instanceof PyExpressionStatement) {
+ final PyExpression expression = ((PyExpressionStatement)anchor).getExpression();
+ if (expression instanceof PyCallExpression) {
+ final PyExpression callee = ((PyCallExpression)expression).getCallee();
+ if ((isSuperCall((PyCallExpression)expression) || (callee != null && PyNames.INIT.equals(callee.getName())))) {
+ final PyStatement next = PsiTreeUtil.getNextSiblingOfType(anchor, PyStatement.class);
+ if (next == null) {
+ return statementList.addAfter(element, anchor);
+ }
+ anchor = next;
+ }
+ else break;
+ }
+ else break;
}
- else
- element = statementList.addBefore(element, firstStatement);
+ element = statementList.addBefore(element, anchor);
}
else {
element = statementList.add(element);
diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
index 0a9959d23f64..47fb3470a972 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
@@ -585,7 +585,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
@Nullable
@Override
- public Property findProperty(@NotNull final String name) {
+ public Property findProperty(@NotNull final String name, boolean inherited) {
Property property = findLocalProperty(name);
if (property != null) {
return property;
@@ -593,10 +593,12 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
if (findMethodByName(name, false) != null || findClassAttribute(name, false) != null) {
return null;
}
- for (PyClass aClass : getAncestorClasses()) {
- final Property ancestorProperty = ((PyClassImpl)aClass).findLocalProperty(name);
- if (ancestorProperty != null) {
- return ancestorProperty;
+ if (inherited) {
+ for (PyClass aClass : getAncestorClasses()) {
+ final Property ancestorProperty = ((PyClassImpl)aClass).findLocalProperty(name);
+ if (ancestorProperty != null) {
+ return ancestorProperty;
+ }
}
}
return null;
diff --git a/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java b/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java
index f15a664fcbba..f64b533f3303 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java
@@ -74,8 +74,8 @@ public class PyDecoratorImpl extends StubBasedPsiElementBase<PyDecoratorStub> im
}
public boolean hasArgumentList() {
- ASTNode arglist_node = getNode().findChildByType(PyElementTypes.ARGUMENT_LIST);
- return (arglist_node != null) && (arglist_node.findChildByType(PyTokenTypes.LPAR) != null);
+ final ASTNode arglistNode = getNode().findChildByType(PyElementTypes.ARGUMENT_LIST);
+ return (arglistNode != null) && (arglistNode.findChildByType(PyTokenTypes.LPAR) != null);
}
public QualifiedName getQualifiedName() {
diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java
index 3f438437190e..8c71346575cc 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java
@@ -174,29 +174,28 @@ public class PyFunctionImpl extends PyPresentableElementImpl<PyFunctionStub> imp
@Nullable
@Override
public PyType getReturnType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
- final PyType type = getGenericReturnType(context, callSite);
-
+ PyType type = getGenericReturnType(context, callSite);
if (callSite == null) {
return type;
}
final PyTypeChecker.AnalyzeCallResults results = PyTypeChecker.analyzeCallSite(callSite, context);
-
if (PyTypeChecker.hasGenerics(type, context)) {
if (results != null) {
final Map<PyGenericType, PyType> substitutions = PyTypeChecker.unifyGenericCall(this, results.getReceiver(), results.getArguments(),
context);
- if (substitutions != null) {
- return PyTypeChecker.substitute(type, substitutions, context);
- }
+ type = substitutions != null ? PyTypeChecker.substitute(type, substitutions, context) : null;
+ }
+ else {
+ type = null;
}
- return null;
+ }
+ if (results != null) {
+ type = replaceSelf(type, results.getReceiver(), context);
}
if (results != null && isDynamicallyEvaluated(results.getArguments().values(), context)) {
return PyUnionType.createWeakType(type);
}
- else {
- return type;
- }
+ return type;
}
@Nullable
@@ -205,16 +204,36 @@ public class PyFunctionImpl extends PyPresentableElementImpl<PyFunctionStub> imp
*/
public PyType getReturnTypeWithoutCallSite(@NotNull TypeEvalContext context,
@Nullable PyExpression receiver) {
- final PyType type = getGenericReturnType(context, null);
+ PyType type = getGenericReturnType(context, null);
if (PyTypeChecker.hasGenerics(type, context)) {
- final Map<PyGenericType, PyType> substitutions =
- PyTypeChecker.unifyGenericCall(this, receiver, Maps.<PyExpression, PyNamedParameter>newHashMap(), context);
+ final Map<PyGenericType, PyType> substitutions = PyTypeChecker.unifyGenericCall(this, receiver,
+ Maps.<PyExpression, PyNamedParameter>newHashMap(),
+ context);
if (substitutions != null) {
- return PyTypeChecker.substitute(type, substitutions, context);
+ type = PyTypeChecker.substitute(type, substitutions, context);
+ }
+ else {
+ type = null;
}
- return null;
}
- return type;
+ return replaceSelf(type, receiver, context);
+ }
+
+ @Nullable
+ private PyType replaceSelf(@Nullable PyType returnType, @Nullable PyExpression receiver, @NotNull TypeEvalContext context) {
+ if (receiver != null) {
+ // TODO: Currently we substitute only simple subclass types, but we could handle union and collection types as well
+ if (returnType instanceof PyClassType) {
+ final PyClassType returnClassType = (PyClassType)returnType;
+ if (returnClassType.getPyClass() == getContainingClass()) {
+ final PyType receiverType = context.getType(receiver);
+ if (receiverType instanceof PyClassType && PyTypeChecker.match(returnType, receiverType, context)) {
+ return returnClassType.isDefinition() ? receiverType : ((PyClassType)receiverType).toInstance();
+ }
+ }
+ }
+ }
+ return returnType;
}
private static boolean isDynamicallyEvaluated(@NotNull Collection<PyNamedParameter> parameters, @NotNull TypeEvalContext context) {
diff --git a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java
index 7b778a527635..455d4c597e71 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java
@@ -264,7 +264,7 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
if (qualifierType instanceof PyClassType) {
final PyClassType classType = (PyClassType)qualifierType;
PyClass pyClass = classType.getPyClass();
- Property property = pyClass.findProperty(name);
+ Property property = pyClass.findProperty(name, true);
if (property != null) {
if (classType.isDefinition()) {
return Ref.<PyType>create(PyBuiltinCache.getInstance(pyClass).getObjectType(PyNames.PROPERTY));
@@ -291,7 +291,7 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
}
@Nullable
- private PyType getTypeFromProviders(TypeEvalContext context) {
+ private PyType getTypeFromProviders(@NotNull TypeEvalContext context) {
for (PyTypeProvider provider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
try {
final PyType type = provider.getReferenceExpressionType(this, context);
diff --git a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java
index fd49c2543cc7..ae2e30f28f0a 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java
@@ -241,8 +241,8 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
if (exprType instanceof PyClassType) {
final PyClass cls = ((PyClassType)exprType).getPyClass();
final PyFunction enter = cls.findMethodByName(PyNames.ENTER, true);
- if (enter != null) {
- final PyType enterType = enter.getReturnType(context, null);
+ if (enter instanceof PyFunctionImpl) {
+ final PyType enterType = ((PyFunctionImpl)enter).getReturnTypeWithoutCallSite(context, expression);
if (enterType != null) {
return enterType;
}
diff --git a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java
index 7be077f8bc17..e475429e0143 100644
--- a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java
+++ b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java
@@ -23,6 +23,7 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiInvalidElementAccessException;
@@ -156,22 +157,9 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
}
if (resolveContext.allowProperties()) {
- Property property = myClass.findProperty(name);
- if (property != null) {
- Maybe<Callable> accessor = property.getByDirection(direction);
- if (accessor.isDefined()) {
- Callable accessor_code = accessor.value();
- ResolveResultList ret = new ResolveResultList();
- if (accessor_code != null) ret.poke(accessor_code, RatedResolveResult.RATE_NORMAL);
- PyTargetExpression site = property.getDefinitionSite();
- if (site != null) ret.poke(site, RatedResolveResult.RATE_LOW);
- if (ret.size() > 0) {
- return ret;
- }
- else {
- return null;
- } // property is found, but the required accessor is explicitly absent
- }
+ final Ref<ResolveResultList> resultRef = findProperty(name, direction, true);
+ if (resultRef != null) {
+ return resultRef.get();
}
}
@@ -198,6 +186,11 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
return ResolveResultList.to(classMember);
}
+ classMember = resolveByOverridingAncestorsMembersProviders(this, name, location);
+ if (classMember != null) {
+ return ResolveResultList.to(classMember);
+ }
+
if (inherited) {
for (PyClassLikeType type : myClass.getAncestorTypes(context)) {
if (type instanceof PyClassType) {
@@ -237,12 +230,10 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
for (PyClassLikeType type : myClass.getAncestorTypes(context)) {
if (type instanceof PyClassType) {
final PyClass pyClass = ((PyClassType)type).getPyClass();
- if (pyClass != null) {
- PsiElement superMember = resolveByMembersProviders(new PyClassTypeImpl(pyClass, isDefinition()), name, location);
+ PsiElement superMember = resolveByMembersProviders(new PyClassTypeImpl(pyClass, isDefinition()), name, location);
- if (superMember != null) {
- return ResolveResultList.to(superMember);
- }
+ if (superMember != null) {
+ return ResolveResultList.to(superMember);
}
}
}
@@ -251,6 +242,28 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
return Collections.emptyList();
}
+ private Ref<ResolveResultList> findProperty(String name, AccessDirection direction, boolean inherited) {
+ Ref<ResolveResultList> resultRef = null;
+ Property property = myClass.findProperty(name, inherited);
+ if (property != null) {
+ Maybe<Callable> accessor = property.getByDirection(direction);
+ if (accessor.isDefined()) {
+ Callable accessor_code = accessor.value();
+ ResolveResultList ret = new ResolveResultList();
+ if (accessor_code != null) ret.poke(accessor_code, RatedResolveResult.RATE_NORMAL);
+ PyTargetExpression site = property.getDefinitionSite();
+ if (site != null) ret.poke(site, RatedResolveResult.RATE_LOW);
+ if (ret.size() > 0) {
+ resultRef = Ref.create(ret);
+ }
+ else {
+ resultRef = Ref.create();
+ } // property is found, but the required accessor is explicitly absent
+ }
+ }
+ return resultRef;
+ }
+
@Nullable
private PyClassType getMetaclassType() {
final PyClass metaClass = PyUtil.getMetaClass(myClass);
@@ -330,6 +343,17 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
}
@Nullable
+ private static PsiElement resolveByOverridingAncestorsMembersProviders(PyClassType type, String name, @Nullable PyExpression location) {
+ for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
+ if (provider instanceof PyOverridingAncestorsClassMembersProvider) {
+ final PsiElement resolveResult = provider.resolveMember(type, name, location);
+ if (resolveResult != null) return resolveResult;
+ }
+ }
+ return null;
+ }
+
+ @Nullable
private static PsiElement resolveInner(@NotNull PyClass cls,
boolean isDefinition,
@NotNull String name,
diff --git a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java
index 8a1bd6b60bae..aeb1efae5824 100644
--- a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java
+++ b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java
@@ -40,7 +40,10 @@ import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.hash.HashMap;
-import com.jetbrains.python.*;
+import com.jetbrains.python.PyBundle;
+import com.jetbrains.python.PyNames;
+import com.jetbrains.python.PythonFileType;
+import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.codeInsight.codeFragment.PyCodeFragment;
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
@@ -332,9 +335,12 @@ public class PyExtractMethodUtil {
}
}
- private static void setSelectionAndCaret(Editor editor, final PsiElement callElement) {
+ private static void setSelectionAndCaret(Editor editor, @Nullable final PsiElement callElement) {
editor.getSelectionModel().removeSelection();
- editor.getCaretModel().moveToOffset(callElement.getTextOffset());
+ if (callElement != null) {
+ final int offset = callElement.getTextOffset();
+ editor.getCaretModel().moveToOffset(offset);
+ }
}
private static PsiElement replaceElements(final List<PsiElement> elementsRange, @NotNull PsiElement callElement) {
diff --git a/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java b/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java
index 3fbc168acc1c..077ced33e0fc 100644
--- a/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java
+++ b/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java
@@ -267,6 +267,7 @@ public class PySkeletonRefresher {
final String skeletonsPath = getSkeletonsPath();
final File skeletonsDir = new File(skeletonsPath);
if (!skeletonsDir.exists()) {
+ //noinspection ResultOfMethodCallIgnored
skeletonsDir.mkdirs();
}
final String readablePath = FileUtil.getLocationRelativeToUserHome(homePath);
@@ -446,7 +447,7 @@ public class PySkeletonRefresher {
reader.close();
}
}
- catch (IOException e) {
+ catch (IOException ignored) {
}
return null;
}
diff --git a/python/src/com/jetbrains/python/testing/PyTestFrameworkService.java b/python/src/com/jetbrains/python/testing/PyTestFrameworkService.java
new file mode 100644
index 000000000000..8eac0886d277
--- /dev/null
+++ b/python/src/com/jetbrains/python/testing/PyTestFrameworkService.java
@@ -0,0 +1,50 @@
+/*
+ * 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.jetbrains.python.testing;
+
+import com.intellij.openapi.components.*;
+import com.intellij.util.containers.HashMap;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+
+import java.util.Map;
+
+@State(
+ name = "PyTestFrameworkService",
+ storages = {
+ @Storage(
+ file = StoragePathMacros.APP_CONFIG + "/other.xml"
+ )}
+)
+public class PyTestFrameworkService implements PersistentStateComponent<PyTestFrameworkService> {
+
+ public static PyTestFrameworkService getInstance() {
+ return ServiceManager.getService(PyTestFrameworkService.class);
+ }
+
+ public Map<String, Boolean> SDK_TO_PYTEST = new HashMap<String, Boolean>();
+ public Map <String, Boolean> SDK_TO_NOSETEST = new HashMap<String, Boolean>();
+ public Map <String, Boolean> SDK_TO_ATTEST = new HashMap<String, Boolean>();
+
+ @Override
+ public PyTestFrameworkService getState() {
+ return this;
+ }
+
+ @Override
+ public void loadState(PyTestFrameworkService state) {
+ XmlSerializerUtil.copyBean(state, this);
+ }
+}
diff --git a/python/src/com/jetbrains/python/testing/VFSTestFrameworkListener.java b/python/src/com/jetbrains/python/testing/VFSTestFrameworkListener.java
index 7130b1aedf78..69d1ce01dd2a 100644
--- a/python/src/com/jetbrains/python/testing/VFSTestFrameworkListener.java
+++ b/python/src/com/jetbrains/python/testing/VFSTestFrameworkListener.java
@@ -16,22 +16,22 @@
package com.jetbrains.python.testing;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.components.*;
+import com.intellij.openapi.components.ApplicationComponent;
+import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
-import com.intellij.util.containers.HashMap;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
-import com.intellij.util.xmlb.XmlSerializerUtil;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.packaging.PyExternalProcessException;
import com.jetbrains.python.packaging.PyPackageManager;
@@ -41,25 +41,17 @@ import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
import java.util.List;
-import java.util.Map;
/**
* User: catherine
*/
-@State(
- name = "VFSTestFrameworkListener",
- storages = {
- @Storage(
- file = StoragePathMacros.APP_CONFIG + "/other.xml"
- )}
-)
-public class VFSTestFrameworkListener implements ApplicationComponent, PersistentStateComponent<VFSTestFrameworkListener> {
-
+public class VFSTestFrameworkListener implements ApplicationComponent {
private static final Logger LOG = Logger.getInstance("#com.jetbrains.python.testing.VFSTestFrameworkListener");
-
private static final MergingUpdateQueue myQueue = new MergingUpdateQueue("TestFrameworkChecker", 5000, true, null);
+ private PyTestFrameworkService myService;
public VFSTestFrameworkListener() {
+ myService = PyTestFrameworkService.getInstance();
MessageBus messageBus = ApplicationManager.getApplication().getMessageBus();
messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() {
@Override
@@ -76,8 +68,9 @@ public class VFSTestFrameworkListener implements ApplicationComponent, Persisten
if (PySdkUtil.isRemote(sdk)) {
continue;
}
- for (String root : sdk.getRootProvider().getUrls(OrderRootType.CLASSES)) {
- if (path.contains(root)) {
+ for (VirtualFile virtualFile : sdk.getRootProvider().getFiles(OrderRootType.CLASSES)) {
+ String root = virtualFile.getCanonicalPath();
+ if (root != null && path.contains(root)) {
if (containsNose) {
updateTestFrameworks(sdk, PyNames.NOSE_TEST);
return;
@@ -152,26 +145,12 @@ public class VFSTestFrameworkListener implements ApplicationComponent, Persisten
return ServiceManager.getService(VFSTestFrameworkListener.class);
}
- public Map<String, Boolean> SDK_TO_PYTEST = new HashMap<String, Boolean>();
- public Map <String, Boolean> SDK_TO_NOSETEST = new HashMap<String, Boolean>();
- public Map <String, Boolean> SDK_TO_ATTEST = new HashMap<String, Boolean>();
-
- @Override
- public VFSTestFrameworkListener getState() {
- return this;
- }
-
- @Override
- public void loadState(VFSTestFrameworkListener state) {
- XmlSerializerUtil.copyBean(state, this);
- }
-
public void pyTestInstalled(boolean installed, String sdkHome) {
- SDK_TO_PYTEST.put(sdkHome, installed);
+ myService.SDK_TO_PYTEST.put(sdkHome, installed);
}
public boolean isPyTestInstalled(final Sdk sdk) {
- Boolean isInstalled = SDK_TO_PYTEST.get(sdk.getHomePath());
+ Boolean isInstalled = myService.SDK_TO_PYTEST.get(sdk.getHomePath());
if (isInstalled == null) {
updateTestFrameworks(sdk, PyNames.PY_TEST);
return true;
@@ -180,11 +159,11 @@ public class VFSTestFrameworkListener implements ApplicationComponent, Persisten
}
public void noseTestInstalled(boolean installed, String sdkHome) {
- SDK_TO_NOSETEST.put(sdkHome, installed);
+ myService.SDK_TO_NOSETEST.put(sdkHome, installed);
}
public boolean isNoseTestInstalled(final Sdk sdk) {
- Boolean isInstalled = SDK_TO_NOSETEST.get(sdk.getHomePath());
+ Boolean isInstalled = myService.SDK_TO_NOSETEST.get(sdk.getHomePath());
if (isInstalled == null) {
updateTestFrameworks(sdk, PyNames.NOSE_TEST);
return true;
@@ -193,11 +172,11 @@ public class VFSTestFrameworkListener implements ApplicationComponent, Persisten
}
public void atTestInstalled(boolean installed, String sdkHome) {
- SDK_TO_ATTEST.put(sdkHome, installed);
+ myService.SDK_TO_ATTEST.put(sdkHome, installed);
}
public boolean isAtTestInstalled(final Sdk sdk) {
- Boolean isInstalled = SDK_TO_ATTEST.get(sdk.getHomePath());
+ Boolean isInstalled = myService.SDK_TO_ATTEST.get(sdk.getHomePath());
if (isInstalled == null) {
updateTestFrameworks(sdk, PyNames.AT_TEST);
return true;
diff --git a/python/testData/formatter/commentBetweenClasses_after.py b/python/testData/formatter/commentBetweenClasses_after.py
index b8523949c0b6..e97c76b04590 100644
--- a/python/testData/formatter/commentBetweenClasses_after.py
+++ b/python/testData/formatter/commentBetweenClasses_after.py
@@ -2,6 +2,7 @@ class T1(object):
def m1(self):
pass
+
# comment about T2
class T2(object):
diff --git a/python/testData/formatter/continuationIndentInIndentingStatement.py b/python/testData/formatter/continuationIndentInIndentingStatement.py
new file mode 100644
index 000000000000..5822bc4971bb
--- /dev/null
+++ b/python/testData/formatter/continuationIndentInIndentingStatement.py
@@ -0,0 +1,31 @@
+if True \
+ or False:
+ pass
+elif \
+ False:
+ pass
+
+for i in \
+ range(1, 100):
+ pass
+
+with open('file1') as file1, \
+ open('file2') as file2:
+ pass
+
+
+class \
+ A(object):
+ pass
+
+
+def \
+ foo():
+ pass
+
+
+try:
+ pass
+except \
+ AttributeError:
+ pass \ No newline at end of file
diff --git a/python/testData/formatter/continuationIndentInIndentingStatement_after.py b/python/testData/formatter/continuationIndentInIndentingStatement_after.py
new file mode 100644
index 000000000000..f38dd5199edd
--- /dev/null
+++ b/python/testData/formatter/continuationIndentInIndentingStatement_after.py
@@ -0,0 +1,31 @@
+if True \
+ or False:
+ pass
+elif \
+ False:
+ pass
+
+for i in \
+ range(1, 100):
+ pass
+
+with open('file1') as file1, \
+ open('file2') as file2:
+ pass
+
+
+class \
+ A(object):
+ pass
+
+
+def \
+ foo():
+ pass
+
+
+try:
+ pass
+except \
+ AttributeError:
+ pass \ No newline at end of file
diff --git a/python/testData/formatter/indentParensInImport.py b/python/testData/formatter/indentParensInImport.py
new file mode 100644
index 000000000000..ab20f1b5571b
--- /dev/null
+++ b/python/testData/formatter/indentParensInImport.py
@@ -0,0 +1,3 @@
+from some.module import (
+ thing
+ ) \ No newline at end of file
diff --git a/python/testData/formatter/indentParensInImport_after.py b/python/testData/formatter/indentParensInImport_after.py
new file mode 100644
index 000000000000..2ad9216af71c
--- /dev/null
+++ b/python/testData/formatter/indentParensInImport_after.py
@@ -0,0 +1,3 @@
+from some.module import (
+ thing
+) \ No newline at end of file
diff --git a/python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment.py b/python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment.py
new file mode 100644
index 000000000000..a0f52904114e
--- /dev/null
+++ b/python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment.py
@@ -0,0 +1,18 @@
+class A(object):
+ pass
+
+#comment
+def one():
+ pass
+
+# comment
+def two():
+ pass
+
+#comment
+class B(object):
+ pass
+
+#comment
+class C(object):
+ pass \ No newline at end of file
diff --git a/python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment_after.py b/python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment_after.py
new file mode 100644
index 000000000000..d582036d8654
--- /dev/null
+++ b/python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment_after.py
@@ -0,0 +1,22 @@
+class A(object):
+ pass
+
+
+#comment
+def one():
+ pass
+
+
+# comment
+def two():
+ pass
+
+
+#comment
+class B(object):
+ pass
+
+
+#comment
+class C(object):
+ pass \ No newline at end of file
diff --git a/python/testData/inspections/FieldFromUnusedParameterKeyword.py b/python/testData/inspections/FieldFromUnusedParameterKeyword.py
deleted file mode 100644
index 35851f0f87df..000000000000
--- a/python/testData/inspections/FieldFromUnusedParameterKeyword.py
+++ /dev/null
@@ -1,3 +0,0 @@
-class A:
- def __init__(self, <weak_warning descr="Parameter 'foo' value is not used">f<caret>oo=True</weak_warning>):
- print('hello') \ No newline at end of file
diff --git a/python/testData/inspections/FieldFromUnusedParameterKeyword_after.py b/python/testData/inspections/FieldFromUnusedParameterKeyword_after.py
deleted file mode 100644
index 7e0d6627cc00..000000000000
--- a/python/testData/inspections/FieldFromUnusedParameterKeyword_after.py
+++ /dev/null
@@ -1,4 +0,0 @@
-class A:
- def __init__(self, foo=True):
- print('hello')
- self.foo = foo \ No newline at end of file
diff --git a/python/testData/inspections/FieldFromUnusedParameter_after.py b/python/testData/inspections/FieldFromUnusedParameter_after.py
deleted file mode 100644
index 7405ba3ec789..000000000000
--- a/python/testData/inspections/FieldFromUnusedParameter_after.py
+++ /dev/null
@@ -1,4 +0,0 @@
-class A:
- def __init__(self, foo):
- print('hello')
- self.foo = foo \ No newline at end of file
diff --git a/python/testData/inspections/PyArgumentListInspection/decoratorsPy3K.py b/python/testData/inspections/PyArgumentListInspection/decoratorsPy3K.py
new file mode 100644
index 000000000000..07e9942700b1
--- /dev/null
+++ b/python/testData/inspections/PyArgumentListInspection/decoratorsPy3K.py
@@ -0,0 +1,7 @@
+
+def deco(func, *args):
+ return func
+
+@deco # <= Here is a false positive.
+def myfunc(a, b):
+ print(a, b) \ No newline at end of file
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/contextManagerSubclass.py b/python/testData/inspections/PyUnresolvedReferencesInspection/contextManagerSubclass.py
new file mode 100644
index 000000000000..f7406dedbb6f
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/contextManagerSubclass.py
@@ -0,0 +1,12 @@
+class C(object):
+ def __enter__(self):
+ return self
+
+
+class D(C):
+ def foo(self):
+ pass
+
+
+with D() as cm:
+ cm.foo() # pass
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/ivarInDocstring.py b/python/testData/inspections/PyUnresolvedReferencesInspection/ivarInDocstring.py
new file mode 100644
index 000000000000..1fec85f8b63b
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/ivarInDocstring.py
@@ -0,0 +1,10 @@
+
+class SomeClass(object):
+ """ Awesome class
+
+ @ivar someVar: great stuff
+ @type someVar: string
+ """
+
+ def __init__(self):
+ self.someVar = None \ No newline at end of file
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/returnSelfInSuperClass.py b/python/testData/inspections/PyUnresolvedReferencesInspection/returnSelfInSuperClass.py
new file mode 100644
index 000000000000..79c56a020033
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/returnSelfInSuperClass.py
@@ -0,0 +1,13 @@
+class C(object):
+ def get_self(self):
+ return self
+
+
+class D(C):
+ def foo(self):
+ pass
+
+
+d = D()
+print(d.foo())
+print(d.get_self().foo()) # pass
diff --git a/python/testData/inspections/PyUnusedLocalVariableInspection/test.py b/python/testData/inspections/PyUnusedLocalVariableInspection/test.py
index 5edffda057d2..65913e27c745 100644
--- a/python/testData/inspections/PyUnusedLocalVariableInspection/test.py
+++ b/python/testData/inspections/PyUnusedLocalVariableInspection/test.py
@@ -303,3 +303,16 @@ def test_unused_condition_local_with_last_if_in_cycle(c):
x = False #pass
if c:
x = True
+
+
+# PY-7527
+def test_unused_empty_init_parameter():
+ class C(object):
+ def __init__(self, <weak_warning descr="Parameter 'foo' value is not used">foo</weak_warning>):
+ pass
+
+ def f(self, bar):
+ pass
+
+ return C
+
diff --git a/python/testData/inspections/ReplaceNotEqOperator.py b/python/testData/inspections/ReplaceNotEqOperator.py
index c0c6300b8e1f..790a765f19ca 100644
--- a/python/testData/inspections/ReplaceNotEqOperator.py
+++ b/python/testData/inspections/ReplaceNotEqOperator.py
@@ -1 +1 @@
-print(<warning descr="Python version 3.0, 3.1, 3.2, 3.3, 3.4 do not support <>, use != instead.">a <> b</warning>) \ No newline at end of file
+print(<warning descr="Python version 3.0, 3.1, 3.2, 3.3, 3.4 do not support <>, use != instead.">a<caret> <> b</warning>) \ No newline at end of file
diff --git a/python/testData/quickFixes/AddFieldQuickFixTest/addFieldFromInstance_after.py b/python/testData/quickFixes/AddFieldQuickFixTest/addFieldFromInstance_after.py
index 686290338cf5..7027a3993765 100644
--- a/python/testData/quickFixes/AddFieldQuickFixTest/addFieldFromInstance_after.py
+++ b/python/testData/quickFixes/AddFieldQuickFixTest/addFieldFromInstance_after.py
@@ -1,8 +1,7 @@
class A:
def __init__(self):
- self.x = 1
self.y = None
-
+ self.x = 1
a = A()
a.y+1
diff --git a/python/testData/quickFixes/AddFieldQuickFixTest/addFieldFromMethod_after.py b/python/testData/quickFixes/AddFieldQuickFixTest/addFieldFromMethod_after.py
index 3ac2f7ecd201..c0ce40fe9e03 100644
--- a/python/testData/quickFixes/AddFieldQuickFixTest/addFieldFromMethod_after.py
+++ b/python/testData/quickFixes/AddFieldQuickFixTest/addFieldFromMethod_after.py
@@ -1,7 +1,7 @@
class A:
def __init__(self):
- self.x = 1
self.y = None
+ self.x = 1
def foo(self):
a = self.y
diff --git a/python/testData/inspections/FieldFromUnusedParameter.py b/python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameter.py
index a9b802bb0136..a9b802bb0136 100644
--- a/python/testData/inspections/FieldFromUnusedParameter.py
+++ b/python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameter.py
diff --git a/python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameterKeyword.py b/python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameterKeyword.py
new file mode 100644
index 000000000000..27f1600fe718
--- /dev/null
+++ b/python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameterKeyword.py
@@ -0,0 +1,3 @@
+class A:
+ def __init__(self, fo<caret>o=True):
+ print('hello') \ No newline at end of file
diff --git a/python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameterKeyword_after.py b/python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameterKeyword_after.py
new file mode 100644
index 000000000000..3f86fa418459
--- /dev/null
+++ b/python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameterKeyword_after.py
@@ -0,0 +1,4 @@
+class A:
+ def __init__(self, foo=True):
+ self.foo = foo
+ print('hello') \ No newline at end of file
diff --git a/python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameter_after.py b/python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameter_after.py
new file mode 100644
index 000000000000..58785edcedea
--- /dev/null
+++ b/python/testData/quickFixes/AddFieldQuickFixTest/fromUnusedParameter_after.py
@@ -0,0 +1,4 @@
+class A:
+ def __init__(self, foo):
+ self.foo = foo
+ print('hello') \ No newline at end of file
diff --git a/python/testData/quickFixes/AddMethodQuickFixTest/addMethodFromMethod_after.py b/python/testData/quickFixes/AddMethodQuickFixTest/addMethodFromMethod_after.py
index 978acaf15275..5c47b58a48dc 100644
--- a/python/testData/quickFixes/AddMethodQuickFixTest/addMethodFromMethod_after.py
+++ b/python/testData/quickFixes/AddMethodQuickFixTest/addMethodFromMethod_after.py
@@ -8,6 +8,7 @@ class A:
def y(self, param, a):
pass
+
# Some comment
class B:
diff --git a/python/testData/quickFixes/PyMoveAttributeToInitQuickFixTest/addPass_after.py b/python/testData/quickFixes/PyMoveAttributeToInitQuickFixTest/addPass_after.py
index da65a030ea4d..040de7386118 100644
--- a/python/testData/quickFixes/PyMoveAttributeToInitQuickFixTest/addPass_after.py
+++ b/python/testData/quickFixes/PyMoveAttributeToInitQuickFixTest/addPass_after.py
@@ -3,8 +3,8 @@ __author__ = 'ktisha'
class A:
def __init__(self):
- self._a = 1
self.b = 1
+ self._a = 1
def foo(self):
pass
diff --git a/python/testData/quickFixes/PyMoveAttributeToInitQuickFixTest/moveToInit_after.py b/python/testData/quickFixes/PyMoveAttributeToInitQuickFixTest/moveToInit_after.py
index 2dc80743d949..9a83f676bfdc 100644
--- a/python/testData/quickFixes/PyMoveAttributeToInitQuickFixTest/moveToInit_after.py
+++ b/python/testData/quickFixes/PyMoveAttributeToInitQuickFixTest/moveToInit_after.py
@@ -3,8 +3,8 @@ __author__ = 'ktisha'
class A:
def __init__(self):
- self._a = 1
self.b = 1
+ self._a = 1
def foo(self):
c = 1 \ No newline at end of file
diff --git a/python/testData/refactoring/introduceField/py4437.after.py b/python/testData/refactoring/introduceField/py4437.after.py
index e9c7d7535699..07a1331b604a 100644
--- a/python/testData/refactoring/introduceField/py4437.after.py
+++ b/python/testData/refactoring/introduceField/py4437.after.py
@@ -1,7 +1,7 @@
class SomeClass():
def __init__(self):
- self.x = 1
self.a = ''
+ self.x = 1
def foo(self):
self.a
diff --git a/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java b/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java
index 7947ffb6dc46..2e55003cddd0 100644
--- a/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java
+++ b/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java
@@ -38,7 +38,7 @@ public class PyClassicPropertyTest extends PyTestCase {
public void testV1() throws Exception {
Property p;
Maybe<Callable> accessor;
- p = myClass.findProperty("v1");
+ p = myClass.findProperty("v1", true);
assertNotNull(p);
assertNull(p.getDoc());
PyTargetExpression site = p.getDefinitionSite();
@@ -62,7 +62,7 @@ public class PyClassicPropertyTest extends PyTestCase {
public void testV2() throws Exception {
Property p;
Maybe<Callable> accessor;
- p = myClass.findProperty("v2");
+ p = myClass.findProperty("v2", true);
assertNotNull(p);
assertEquals("doc of v2", p.getDoc());
PyTargetExpression site = p.getDefinitionSite();
@@ -86,7 +86,7 @@ public class PyClassicPropertyTest extends PyTestCase {
public void testV3() throws Exception {
Maybe<Callable> accessor;
- Property p = myClass.findProperty("v3");
+ Property p = myClass.findProperty("v3", true);
assertNotNull(p);
assertNull(p.getDoc());
PyTargetExpression site = p.getDefinitionSite();
diff --git a/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java b/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java
index 414c3558d948..ac9f83afce6a 100644
--- a/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java
+++ b/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java
@@ -35,7 +35,7 @@ public class PyDecoratedPropertyTest extends PyTestCase {
Property p;
Maybe<Callable> accessor;
final String name = "w1";
- p = myClass.findProperty(name);
+ p = myClass.findProperty(name, true);
assertNotNull(p);
assertNull(p.getDoc());
assertNull(p.getDefinitionSite());
@@ -60,7 +60,7 @@ public class PyDecoratedPropertyTest extends PyTestCase {
Property p;
Maybe<Callable> accessor;
final String name = "w2";
- p = myClass.findProperty(name);
+ p = myClass.findProperty(name, true);
assertNotNull(p);
assertNull(p.getDoc());
assertNull(p.getDefinitionSite());
diff --git a/python/testSrc/com/jetbrains/python/PyEditingTest.java b/python/testSrc/com/jetbrains/python/PyEditingTest.java
index 6619bf878749..5f0e7c2de446 100644
--- a/python/testSrc/com/jetbrains/python/PyEditingTest.java
+++ b/python/testSrc/com/jetbrains/python/PyEditingTest.java
@@ -26,6 +26,8 @@ import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiFile;
+import com.jetbrains.python.documentation.DocStringFormat;
+import com.jetbrains.python.documentation.PyDocumentationSettings;
import com.jetbrains.python.fixtures.PyTestCase;
/**
@@ -142,7 +144,7 @@ public class PyEditingTest extends PyTestCase {
}
public void testEnterInStatement() {
- doTestEnter("if a <caret>and b: pass", "if a \\\n and b: pass");
+ doTestEnter("if a <caret>and b: pass", "if a \\\n and b: pass");
}
public void testEnterBeforeStatement() {
@@ -202,10 +204,17 @@ public class PyEditingTest extends PyTestCase {
}
public void testEnterStubInDocstring() { // CR-PY-144
- doTestEnter("def foo():\n \"\"\"<caret>", "def foo():\n" +
- " \"\"\"\n" +
- " \n" +
- " \"\"\"");
+ final PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
+ final String oldFormat = documentationSettings.getFormat();
+ documentationSettings.setFormat(DocStringFormat.PLAIN);
+ try {
+ doTestEnter("def foo():\n \"\"\"<caret>", "def foo():\n" +
+ " \"\"\"\n" +
+ " \n" +
+ " \"\"\"");
+ } finally {
+ documentationSettings.setFormat(oldFormat);
+ }
}
public void testEnterInString() { // PY-1738
@@ -216,7 +225,7 @@ public class PyEditingTest extends PyTestCase {
public void testEnterInImportWithParens() { // PY-2661
doTestEnter("from django.http import (HttpResponse,<caret>)",
"from django.http import (HttpResponse,\n" +
- " )");
+ ")");
}
public void testEnterInKeyword() {
diff --git a/python/testSrc/com/jetbrains/python/PyFormatterTest.java b/python/testSrc/com/jetbrains/python/PyFormatterTest.java
index d25a62f48818..3ca878b44ef7 100644
--- a/python/testSrc/com/jetbrains/python/PyFormatterTest.java
+++ b/python/testSrc/com/jetbrains/python/PyFormatterTest.java
@@ -126,6 +126,10 @@ public class PyFormatterTest extends PyTestCase {
doTest();
}
+ public void testTwoLinesBetweenTopLevelDeclarationsWithComment() { // PY-9923
+ doTest();
+ }
+
public void testSpecialSlice() { // PY-1928
doTest();
}
@@ -199,6 +203,10 @@ public class PyFormatterTest extends PyTestCase {
doTest();
}
+ public void testContinuationIndentInIndentingStatement() { // PY-9573
+ doTest();
+ }
+
public void testBlankLineAfterDecorator() {
doTest();
}
@@ -358,6 +366,10 @@ public class PyFormatterTest extends PyTestCase {
doTest();
}
+ public void testIndentParensInImport() { // PY-9075
+ doTest();
+ }
+
private void doTest() {
doTest(false);
}
diff --git a/python/testSrc/com/jetbrains/python/PyQuickDocTest.java b/python/testSrc/com/jetbrains/python/PyQuickDocTest.java
index 0b78bd5021b9..fb45faeeec09 100644
--- a/python/testSrc/com/jetbrains/python/PyQuickDocTest.java
+++ b/python/testSrc/com/jetbrains/python/PyQuickDocTest.java
@@ -20,6 +20,8 @@ import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.testFramework.TestDataFile;
+import com.jetbrains.python.documentation.DocStringFormat;
+import com.jetbrains.python.documentation.PyDocumentationSettings;
import com.jetbrains.python.documentation.PythonDocumentationProvider;
import com.jetbrains.python.fixtures.LightMarkedTestCase;
import com.jetbrains.python.fixtures.PyTestCase;
@@ -35,12 +37,23 @@ import java.util.Map;
*/
public class PyQuickDocTest extends LightMarkedTestCase {
private PythonDocumentationProvider myProvider;
+ private String myFormat;
@Override
protected void setUp() throws Exception {
super.setUp();
// the provider is stateless, can be reused, as in real life
myProvider = new PythonDocumentationProvider();
+ final PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
+ myFormat = documentationSettings.getFormat();
+ documentationSettings.setFormat(DocStringFormat.PLAIN);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ final PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
+ documentationSettings.setFormat(myFormat);
+ super.tearDown();
}
private void checkByHTML(String text) {
diff --git a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
index e0f82b0718c4..4083775e8a41 100644
--- a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
+++ b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
@@ -173,13 +173,6 @@ public class PyQuickFixTest extends PyTestCase {
doInspectionTest("AddClass.py", PyUnresolvedReferencesInspection.class, "Create class 'Xyzzy'", true, true);
}
- public void testFieldFromUnusedParameter() { // PY-1398
- doInspectionTest("FieldFromUnusedParameter.py", PyUnusedLocalInspection.class, "Add field 'foo' to class A", true, true);
- }
-
- public void testFieldFromUnusedParameterKeyword() { // PY-1602
- doInspectionTest("FieldFromUnusedParameterKeyword.py", PyUnusedLocalInspection.class, "Add field 'foo' to class A", true, true);
- }
public void testAddFunctionToModule() { // PY-1602
doInspectionTest(
diff --git a/python/testSrc/com/jetbrains/python/PyStubsTest.java b/python/testSrc/com/jetbrains/python/PyStubsTest.java
index 6ad2dc4bff16..7706dd7c9ef8 100644
--- a/python/testSrc/com/jetbrains/python/PyStubsTest.java
+++ b/python/testSrc/com/jetbrains/python/PyStubsTest.java
@@ -118,12 +118,12 @@ public class PyStubsTest extends PyTestCase {
pyClass = classes.get(1);
assertEquals("BarClass", pyClass.getName());
- Property prop = pyClass.findProperty("value");
+ Property prop = pyClass.findProperty("value", true);
Maybe<Callable> maybe_function = prop.getGetter();
assertTrue(maybe_function.isDefined());
assertEquals(pyClass.getMethods()[0], maybe_function.value());
- Property setvalueProp = pyClass.findProperty("setvalue");
+ Property setvalueProp = pyClass.findProperty("setvalue", true);
Maybe<Callable> setter = setvalueProp.getSetter();
assertTrue(setter.isDefined());
assertEquals("__set", setter.value().getName());
@@ -131,7 +131,7 @@ public class PyStubsTest extends PyTestCase {
// properties by decorator
pyClass = classes.get(2);
assertEquals("BazClass", pyClass.getName());
- prop = pyClass.findProperty("x");
+ prop = pyClass.findProperty("x", true);
maybe_function = prop.getGetter();
assertTrue(maybe_function.isDefined());
assertEquals(pyClass.getMethods()[0], maybe_function.value());
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java
index fabba0c2458f..c0b20d80a542 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java
@@ -34,6 +34,16 @@ public class PyArgumentListInspectionTest extends PyTestCase {
public void testDecorators() {
doTest();
}
+
+ public void testDecoratorsPy3K() {
+ PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), LanguageLevel.PYTHON30);
+ try {
+ doTest();
+ }
+ finally {
+ PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), null);
+ }
+ }
public void testTupleVsLiteralList() {
doTest();
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
index 54cbf2e1aebf..53bcbc34d60e 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
@@ -133,6 +133,10 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase {
doTest();
}
+ public void testIvarInDocstring() {
+ doTest();
+ }
+
// PY-6634
public void testModuleAttribute() {
doTest();
@@ -322,6 +326,16 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase {
doTest();
}
+ // PY-10977
+ public void testContextManagerSubclass() {
+ doTest();
+ }
+
+ // PY-11413
+ public void testReturnSelfInSuperClass() {
+ doTest();
+ }
+
private void doTest() {
myFixture.configureByFile(TEST_DIRECTORY + getTestName(true) + ".py");
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
diff --git a/python/testSrc/com/jetbrains/python/quickFixes/AddFieldQuickFixTest.java b/python/testSrc/com/jetbrains/python/quickFixes/AddFieldQuickFixTest.java
index 5ffe1a651f2b..c93553d2c3a4 100644
--- a/python/testSrc/com/jetbrains/python/quickFixes/AddFieldQuickFixTest.java
+++ b/python/testSrc/com/jetbrains/python/quickFixes/AddFieldQuickFixTest.java
@@ -15,13 +15,16 @@
*/
package com.jetbrains.python.quickFixes;
+import com.intellij.testFramework.TestDataPath;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyQuickFixTestCase;
import com.jetbrains.python.inspections.PyUnresolvedReferencesInspection;
+import com.jetbrains.python.inspections.PyUnusedLocalInspection;
/**
* User: ktisha
*/
+@TestDataPath("$CONTENT_ROOT/../testData//quickFixes/AddFieldQuickFixTest/")
public class AddFieldQuickFixTest extends PyQuickFixTestCase {
public void testAddClassField() {
@@ -44,4 +47,12 @@ public class AddFieldQuickFixTest extends PyQuickFixTestCase {
doQuickFixTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.field.$0.to.class.$1", "x", "B"));
}
+ public void testFromUnusedParameter() { // PY-1398
+ doQuickFixTest(PyUnusedLocalInspection.class, "Add field 'foo' to class A");
+ }
+
+ public void testFromUnusedParameterKeyword() { // PY-1602
+ doQuickFixTest(PyUnusedLocalInspection.class, "Add field 'foo' to class A");
+ }
+
}
diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DomAnchorImpl.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DomAnchorImpl.java
index 4e6ec59c62b9..01c0bf7ec468 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/impl/DomAnchorImpl.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DomAnchorImpl.java
@@ -82,7 +82,6 @@ public abstract class DomAnchorImpl<T extends DomElement> implements DomAnchor<T
final int index = values.indexOf(t);
if (index < 0) {
- t.equals(values.get(10));
diagnoseNegativeIndex2(t, parent, description, values);
}
return new IndexedAnchor<T>(parentAnchor, description, index);
diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/BrowserSettingsProviderImpl.java b/xml/impl/src/com/intellij/ide/browsers/impl/BrowserSettingsProviderImpl.java
index 568a265d1a57..11ee96f8cd4d 100644
--- a/xml/impl/src/com/intellij/ide/browsers/impl/BrowserSettingsProviderImpl.java
+++ b/xml/impl/src/com/intellij/ide/browsers/impl/BrowserSettingsProviderImpl.java
@@ -43,7 +43,7 @@ public class BrowserSettingsProviderImpl extends BrowserSettingsProvider {
}
public boolean isModified() {
- return mySettingsPanel.isModified();
+ return mySettingsPanel != null && mySettingsPanel.isModified();
}
public void apply() throws ConfigurationException {