Merge remote-tracking branch 'origin/master'
authorVassiliy Kudryashov <Vassiliy.Kudryashov@jetbrains.com>
Tue, 13 Nov 2012 13:00:53 +0000 (17:00 +0400)
committerVassiliy Kudryashov <Vassiliy.Kudryashov@jetbrains.com>
Tue, 13 Nov 2012 13:00:53 +0000 (17:00 +0400)
255 files changed:
.idea/codeStyleSettings.xml
.idea/libraries/sass_stdlib.xml [new file with mode: 0644]
bin/linux/fsnotifier
bin/linux/fsnotifier64
build/scripts/dist.gant
build/update.sh
colorSchemes/src/colorSchemes/Darcula.xml
java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java
java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsPanel.form
java/compiler/impl/testSrc/com/intellij/compiler/BaseCompilerTestCase.java
java/compiler/openapi/src/com/intellij/openapi/compiler/options/ExcludedEntriesConfiguration.java
java/idea-ui/src/com/intellij/ide/actions/ImportModuleAction.java
java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.java
java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromTemplateMode.java
java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectWizardStepFactoryImpl.java
java/idea-ui/src/com/intellij/platform/templates/ArchivedProjectTemplate.java
java/idea-ui/src/com/intellij/platform/templates/ArchivedTemplatesFactory.java
java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateAction.java
java/idea-ui/src/com/intellij/platform/templates/SaveProjectAsTemplateDialog.java
java/java-impl/src/com/intellij/codeInsight/completion/RefactoringCompletionContributor.java [new file with mode: 0644]
java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/MethodOrClassSelectioner.java
java/java-impl/src/com/intellij/codeInsight/intention/impl/ConcatenationToMessageFormatAction.java
java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateSubclassAction.java
java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java
java/java-impl/src/com/intellij/ide/fileTemplates/JavaCreateFromTemplateHandler.java
java/java-impl/src/com/intellij/ide/fileTemplates/JavaTemplateUtil.java
java/java-impl/src/com/intellij/openapi/roots/impl/ExcludeCompilerOutputPolicy.java
java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PackagePrefixFileSystemItem.java
java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java
java/java-impl/src/com/intellij/refactoring/inline/InlineLocalHandler.java
java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java
java/java-impl/src/com/intellij/refactoring/ui/ClassNameReferenceEditor.java
java/java-indexing-impl/src/com/intellij/psi/impl/search/AnnotatedElementsSearcher.java
java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
java/java-psi-api/src/com/intellij/psi/CommonClassNames.java
java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
java/java-psi-impl/src/com/intellij/core/CoreJavaCodeStyleManager.java
java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java
java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java
java/java-tests/testData/psi/parser-partial/expressions/LambdaExpression12.txt
java/java-tests/testData/psi/parser-partial/expressions/LambdaExpression13.txt
java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java
java/openapi/src/com/intellij/ide/util/projectWizard/JavaModuleBuilder.java
jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootDescriptor.java
jps/jps-builders/src/org/jetbrains/jps/builders/BuildTarget.java
jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java
jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaSourceRootDescriptor.java
jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourceRootDescriptor.java [new file with mode: 0644]
jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourcesOnlyRootDescriptor.java [deleted file]
jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourcesTargetType.java [new file with mode: 0644]
jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java
jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java
jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderCategory.java
jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java
jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java
jps/jps-builders/src/org/jetbrains/jps/incremental/JVMModuleBuildTarget.java [new file with mode: 0644]
jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java
jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleBuildTarget.java
jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java [new file with mode: 0644]
jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTarget.java
jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java
jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CompilerMessage.java
jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java
jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java
jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerResponseHandler.java
native/fsNotifier/linux/fsnotifier.h
native/fsNotifier/linux/inotify.c
native/fsNotifier/linux/main.c
native/fsNotifier/linux/make.sh
native/fsNotifier/linux/util.c
platform/core-api/src/com/intellij/concurrency/AsyncFuture.java [new file with mode: 0644]
platform/core-api/src/com/intellij/concurrency/AsyncFutureFactory.java [new file with mode: 0644]
platform/core-api/src/com/intellij/concurrency/AsyncFutureResult.java [new file with mode: 0644]
platform/core-api/src/com/intellij/concurrency/AsyncUtil.java [new file with mode: 0644]
platform/core-api/src/com/intellij/concurrency/DefaultResultConsumer.java [new file with mode: 0644]
platform/core-api/src/com/intellij/concurrency/DoOnce.java [new file with mode: 0644]
platform/core-api/src/com/intellij/concurrency/DoWhile.java [new file with mode: 0644]
platform/core-api/src/com/intellij/concurrency/FinallyFuture.java [new file with mode: 0644]
platform/core-api/src/com/intellij/concurrency/Iterate.java [new file with mode: 0644]
platform/core-api/src/com/intellij/concurrency/JobLauncher.java
platform/core-api/src/com/intellij/concurrency/ResultConsumer.java [new file with mode: 0644]
platform/core-api/src/com/intellij/concurrency/SameThreadExecutor.java [new file with mode: 0644]
platform/core-api/src/com/intellij/openapi/project/Project.java
platform/core-api/src/com/intellij/util/AbstractQuery.java [moved from platform/util/src/com/intellij/util/AbstractQuery.java with 71% similarity]
platform/core-api/src/com/intellij/util/ArrayQuery.java [moved from platform/util/src/com/intellij/util/ArrayQuery.java with 74% similarity]
platform/core-api/src/com/intellij/util/CollectionQuery.java [moved from platform/util/src/com/intellij/util/CollectionQuery.java with 76% similarity]
platform/core-api/src/com/intellij/util/EmptyQuery.java [moved from platform/util/src/com/intellij/util/EmptyQuery.java with 85% similarity]
platform/core-api/src/com/intellij/util/ExecutorsQuery.java [moved from platform/util/src/com/intellij/util/ExecutorsQuery.java with 100% similarity]
platform/core-api/src/com/intellij/util/FilteredQuery.java [moved from platform/util/src/com/intellij/util/FilteredQuery.java with 75% similarity]
platform/core-api/src/com/intellij/util/InstanceofQuery.java [moved from platform/util/src/com/intellij/util/InstanceofQuery.java with 74% similarity]
platform/core-api/src/com/intellij/util/LazyQuery.java [moved from platform/util/src/com/intellij/util/LazyQuery.java with 100% similarity]
platform/core-api/src/com/intellij/util/MergeQuery.java [moved from platform/util/src/com/intellij/util/MergeQuery.java with 66% similarity]
platform/core-api/src/com/intellij/util/Query.java [moved from platform/util/src/com/intellij/util/Query.java with 93% similarity]
platform/core-api/src/com/intellij/util/QueryExecutor.java [moved from platform/util/src/com/intellij/util/QueryExecutor.java with 100% similarity]
platform/core-api/src/com/intellij/util/QueryFactory.java [moved from platform/util/src/com/intellij/util/QueryFactory.java with 100% similarity]
platform/core-api/src/com/intellij/util/UniqueResultsQuery.java [moved from platform/util/src/com/intellij/util/UniqueResultsQuery.java with 72% similarity]
platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
platform/icons/src/actions/checkOut_dark.png [new file with mode: 0644]
platform/icons/src/actions/commit_dark.png [new file with mode: 0644]
platform/icons/src/actions/compile_dark.png [new file with mode: 0644]
platform/icons/src/actions/copy_dark.png [new file with mode: 0644]
platform/icons/src/actions/menu-cut_dark.png [new file with mode: 0644]
platform/icons/src/actions/menu-replace_dark.png [new file with mode: 0644]
platform/icons/src/actions/preview_dark.png [new file with mode: 0644]
platform/icons/src/actions/profileMemory_dark.png [new file with mode: 0644]
platform/icons/src/actions/replace_dark.png [new file with mode: 0644]
platform/icons/src/actions/startDebugger_dark.png [new file with mode: 0644]
platform/icons/src/debugger/evaluateExpression.png
platform/icons/src/debugger/restoreLayout.png
platform/icons/src/debugger/stackFrame.png
platform/icons/src/general/runWithCoverage.png
platform/icons/src/hierarchy/subtypes_dark.png [new file with mode: 0644]
platform/icons/src/hierarchy/supertypes_dark.png [new file with mode: 0644]
platform/icons/src/toolbarDecorator/mac/addRemoteDatasource.png [new file with mode: 0644]
platform/icons/src/toolbarDecorator/mac/addRemoteDatasource_dark.png [new file with mode: 0644]
platform/icons/src/vcs/not_equal_dark.png [new file with mode: 0644]
platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java
platform/indexing-api/src/com/intellij/psi/search/SearchRequestQuery.java
platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java
platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementConstants.java
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementNodeDisplayManager.java
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/AddArrangementRuleAction.java
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/EditArrangementRuleAction.java
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/RemoveArrangementRuleAction.java
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAtomMatchConditionComponent.java
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementEditIconMatchConditionComponent.java [deleted file]
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/EmptyArrangementRuleComponent.java [new file with mode: 0644]
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesPanel.java
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementConfigUtil.java
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/IntObjectMap.java
platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/TitleWithToolbar.java [new file with mode: 0644]
platform/lang-impl/src/com/intellij/codeInsight/documentation/DockablePopupManager.java
platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
platform/lang-impl/src/com/intellij/codeInsight/editorActions/ExtendWordSelectionHandlerBase.java
platform/lang-impl/src/com/intellij/codeInsight/template/actions/SaveAsTemplateAction.java
platform/lang-impl/src/com/intellij/execution/impl/ConsoleUtil.java
platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java
platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java
platform/lang-impl/src/com/intellij/ide/fileTemplates/CreateFromTemplateHandler.java
platform/lang-impl/src/com/intellij/ide/fileTemplates/DefaultCreateFromTemplateHandler.java
platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java
platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java
platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
platform/lang-impl/src/com/intellij/ide/util/gotoByName/ModelDiff.java
platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java
platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionContributor.java
platform/lang-impl/testSources/com/intellij/application/options/codeStyle/arrangement/util/IntObjectMapTest.groovy
platform/platform-api/src/com/intellij/openapi/progress/Task.java
platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java
platform/platform-api/src/com/intellij/ui/ScreenUtil.java
platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeBuilder.java
platform/platform-impl/platform-impl.iml
platform/platform-impl/src/com/intellij/concurrency/AsyncFutureFactoryImpl.java [new file with mode: 0644]
platform/platform-impl/src/com/intellij/concurrency/AsyncFutureResultImpl.java [new file with mode: 0644]
platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java
platform/platform-impl/src/com/intellij/execution/process/RunnerMediator.java
platform/platform-impl/src/com/intellij/execution/process/ScriptRunnerUtil.java
platform/platform-impl/src/com/intellij/ide/ClipboardSynchronizer.java
platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java
platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java
platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxBorder.java [new file with mode: 0644]
platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxUI.java
platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java
platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTest.form
platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTest.java
platform/platform-impl/src/com/intellij/notification/impl/actions/NotificationTestAction.java
platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/IdeaActionButtonLook.java
platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java
platform/platform-impl/src/com/intellij/openapi/keymap/impl/DefaultKeymap.java
platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java
platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InlineProgressIndicator.java
platform/platform-impl/src/com/intellij/platform/ProjectTemplatesFactory.java
platform/platform-impl/src/com/intellij/ui/AbstractTitledSeparatorWithIcon.java
platform/platform-impl/src/com/intellij/ui/ShowUIDefaultsAction.java
platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java
platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
platform/platform-resources-en/src/messages/ApplicationBundle.properties
platform/platform-resources/src/META-INF/PlatformExtensions.xml
platform/platform-resources/src/idea/LangActions.xml
platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java
platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java
platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java
platform/util/src/com/intellij/openapi/util/SystemInfo.java
platform/util/src/com/intellij/openapi/util/text/StringUtil.java
platform/util/src/com/intellij/util/BitUtil.java
platform/util/src/com/intellij/util/io/IOUtil.java
platform/util/src/com/intellij/util/ui/UIUtil.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/DelayedNotificator.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdateRequestsQueue.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitLegendPanel.java
plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties
plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/MagicNumberInspection.java
plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/UtilityClassWithoutPrivateConstructorInspection.java
plugins/InspectionGadgets/src/com/siyeh/ig/initialization/AbstractMethodCallInConstructorInspection.java
plugins/InspectionGadgets/src/com/siyeh/ig/initialization/OverridableMethodCallDuringObjectConstructionInspection.java
plugins/InspectionGadgets/src/com/siyeh/ig/initialization/OverriddenMethodCallDuringObjectConstructionInspection.java
plugins/InspectionGadgets/src/com/siyeh/ig/internationalization/StringConcatenationInspection.java
plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/MethodCallUtils.java
plugins/InspectionGadgets/src/inspectionDescriptions/AbstractMethodCallInConstructor.html
plugins/InspectionGadgets/src/inspectionDescriptions/OverridableMethodCallDuringObjectConstruction.html
plugins/InspectionGadgets/src/inspectionDescriptions/OverriddenMethodCallDuringObjectConstruction.html
plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenation.html
plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/SimpleStringConcatenationPredicate.java
plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ParenthesesUtils.java
plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ArrayAccessExpression.java [new file with mode: 0644]
plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ArrayAccessExpression_after.java [new file with mode: 0644]
plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ArrayInitializer.java [new file with mode: 0644]
plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ArrayInitializer_after.java [new file with mode: 0644]
plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/parenthesis/UnnecessaryParenthesesIntentionTest.java
plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceDialog.java
plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidAdditionalRootProviderService.java
plugins/devkit/src/inspections/TitleCapitalizationInspection.java
plugins/devkit/src/run/PluginRunConfiguration.java
plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java
plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseProjectOpenProcessor.java
plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseWorkspaceRootStep.java
plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonCreateProjectDialog.form [new file with mode: 0644]
plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonCreateProjectDialog.java [new file with mode: 0644]
plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonFramework.java
plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/RemoveUnnecessaryEscapeCharactersIntention.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/EachWithIndexClosureCompleter.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrContainerTypeConverter.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java
plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java
plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignabilityTest.groovy
plugins/hg4idea/src/org/zmlx/hg4idea/HgGlobalSettings.java
plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourcesBuilder.java
plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourcesTarget.java
plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenPropertyPsiReference.java
plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java
plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java
plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/AnnotationProcessorImportingTest.groovy
plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java
plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateExternalAction.java
plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnExternalTests.java [new file with mode: 0644]
plugins/testng/src/com/theoryinpractice/testng/ui/ResultTreeRenderer.java
resources/src/META-INF/IdeaPlugin.xml
resources/src/colorSchemes/Darcula.xml
xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java

index 115d3885eb424c7d148f1c1f2d657f1fa232fe07..4965a0dbd23d7cf8186ee4a4552da46614f26345 100644 (file)
         <option name="WHILE_BRACE_FORCE" value="1" />
         <option name="FOR_BRACE_FORCE" value="1" />
         <option name="FIELD_ANNOTATION_WRAP" value="0" />
+        <AndroidXmlCodeStyleSettings>
+          <option name="LAYOUT_SETTINGS">
+            <value />
+          </option>
+          <option name="MANIFEST_SETTINGS">
+            <value />
+          </option>
+          <option name="VALUE_RESOURCE_FILE_SETTINGS">
+            <value />
+          </option>
+          <option name="OTHER_SETTINGS">
+            <value />
+          </option>
+        </AndroidXmlCodeStyleSettings>
         <XML>
           <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
         </XML>
           <option name="PARENT_SETTINGS_INSTALLED" value="true" />
         </codeStyleSettings>
         <codeStyleSettings language="SQL">
-          <option name="KEEP_LINE_BREAKS" value="false" />
           <option name="PARENT_SETTINGS_INSTALLED" value="true" />
         </codeStyleSettings>
         <codeStyleSettings language="XML">
diff --git a/.idea/libraries/sass_stdlib.xml b/.idea/libraries/sass_stdlib.xml
new file mode 100644 (file)
index 0000000..fa4e8b4
--- /dev/null
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+  <library name="sass-stdlib">
+    <CLASSES />
+    <JAVADOC />
+    <SOURCES>
+      <root url="file://$APPLICATION_HOME_DIR$/plugins/sass/lib/stubs/sass_functions.scss" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
index e4b7dcb6b24c89afa31a02863b43b067e6dafb24..3d90bedafc45cf7384ceb2832efbcb38e7963a24 100755 (executable)
Binary files a/bin/linux/fsnotifier and b/bin/linux/fsnotifier differ
index 8a73a32e167fac2120187db59b80aeedf615d6e7..6427e4b31599d80a4f3cbed8c9c97c67640aeb84 100755 (executable)
Binary files a/bin/linux/fsnotifier64 and b/bin/linux/fsnotifier64 differ
index 0cd9bdcfc85d095c5371a22a18f42444e555edd2..fed966d6fc0024f5c351912a64f95efff82e0daa 100644 (file)
@@ -79,7 +79,7 @@ target('default': 'The default target') {
   layoutAll([buildNumber: "IC-$snapshot",
              system_selector: "IdeaIC${p("component.version.major")}",
              tools_jar: true],
-            home, null, paths)
+            home, null, paths, true)
 }
 
 target('build-dist-jars' : 'Target to build jars from locally compiled classes') {
@@ -90,10 +90,10 @@ target('build-dist-jars' : 'Target to build jars from locally compiled classes')
   layoutAll([buildNumber: "IC-$snapshot",
              system_selector: "IdeaIC${p("component.version.major")}",
              tools_jar: true],
-            home, null, paths)
+             home, null, paths)
 }
 
-def layoutAll(Map args, String home, String out, Paths _paths = null) {
+def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = false) {
   Paths paths = _paths != null ? _paths : new Paths(out)
 
   wireBuildDate(args.buildNumber, appInfoFile())
@@ -105,8 +105,10 @@ def layoutAll(Map args, String home, String out, Paths _paths = null) {
   notifyArtifactBuilt(paths.artifacts_core)
   layouts.layout_core_upsource(home, paths.artifacts_core_upsource)
   notifyArtifactBuilt(paths.artifacts_core_upsource)
-  layouts.layout_jps(home, paths.artifacts_jps)
-  notifyArtifactBuilt(paths.artifacts_jps)
+  if (buildJps) {
+    layouts.layout_jps(home, paths.artifacts_jps)
+    notifyArtifactBuilt(paths.artifacts_jps)
+  }
 
   layout(paths.distAll) {
     dir("bin") {
index 61f009e28087517c3fed469b8679dd46e518f393..a4b17148414683df9c70bd7542748d91207f3c3d 100755 (executable)
@@ -29,3 +29,13 @@ rm -rf $WORK_IDEA_HOME/lib
 rm -rf $WORK_IDEA_HOME/plugins
 
 cp -R $DEV_IDEA_HOME/out/deploy/* $WORK_IDEA_HOME
+
+OS_TYPE=`uname -s`
+if [ "$OS_TYPE" = "Linux" ]; then
+  cp -a $DEV_IDEA_HOME/bin/linux/*.so $WORK_IDEA_HOME/bin
+  cp -a $DEV_IDEA_HOME/bin/linux/fsnotifier* $WORK_IDEA_HOME/bin
+elif [ "$OS_TYPE" = "Darwin" ]; then
+  cp -a $DEV_IDEA_HOME/bin/mac/*.jnilib $WORK_IDEA_HOME/bin
+  cp -a $DEV_IDEA_HOME/bin/mac/fsnotifier $WORK_IDEA_HOME/bin
+  cp -a $DEV_IDEA_HOME/bin/mac/relaunch $WORK_IDEA_HOME/bin
+fi
index 206bfc7968358e2052eff82060249cb78d2f3209..cfe201f76f9933d522eb3a357a3f06144403a9d4 100644 (file)
     <option name="SEARCH_RESULT_ATTRIBUTES">
       <value>
         <option name="FOREGROUND" />
-        <option name="BACKGROUND" value="35627f" />
+        <option name="BACKGROUND" value="006300" />
         <option name="FONT_TYPE" value="0" />
         <option name="EFFECT_COLOR" />
         <option name="EFFECT_TYPE" value="0" />
     <option name="TEXT_SEARCH_RESULT_ATTRIBUTES">
       <value>
         <option name="FOREGROUND" />
-        <option name="BACKGROUND" value="a4a459" />
+        <option name="BACKGROUND" value="006300" />
         <option name="FONT_TYPE" value="0" />
         <option name="EFFECT_COLOR" />
         <option name="EFFECT_TYPE" value="0" />
index d460e8e7d1760b602a147074aefcb7f4cf336fa5..67acd7f88cc8d8c5aef1876c60b8774e6b1a566b 100644 (file)
@@ -93,6 +93,7 @@ import gnu.trove.TObjectHashingStrategy;
 import org.jetbrains.annotations.NonNls;\r
 import org.jetbrains.annotations.NotNull;\r
 import org.jetbrains.annotations.Nullable;\r
+import org.jetbrains.annotations.TestOnly;\r
 import org.jetbrains.jps.api.CmdlineProtoUtil;\r
 import org.jetbrains.jps.api.CmdlineRemoteProto;\r
 import org.jetbrains.jps.api.RequestFuture;\r
@@ -595,7 +596,7 @@ public class CompileDriver {
   }\r
 \r
 \r
-  public static final Key<ExitStatus> COMPILE_SERVER_BUILD_STATUS = Key.create("COMPILE_SERVER_BUILD_STATUS");\r
+  private static final Key<ExitStatus> COMPILE_SERVER_BUILD_STATUS = Key.create("COMPILE_SERVER_BUILD_STATUS");\r
 \r
   private void startup(final CompileScope scope,\r
                        final boolean isRebuild,\r
@@ -612,7 +613,7 @@ public class CompileDriver {
     final CompilerTask compileTask = new CompilerTask(myProject, contentName, ApplicationManager.getApplication().isUnitTestMode(), true);\r
 \r
     StatusBar.Info.set("", myProject, "Compiler");\r
-    if (useExtProcessBuild && BuildManager.getInstance().rescanRequired(myProject)) {\r
+    if (useExtProcessBuild) {\r
       // ensure the project model seen by build process is up-to-date\r
       myProject.save();\r
     }\r
@@ -750,6 +751,11 @@ public class CompileDriver {
     });\r
   }\r
 \r
+  @Nullable @TestOnly\r
+  public static ExitStatus getExternalBuildExitStatus(CompileContext context) {\r
+    return context.getUserData(COMPILE_SERVER_BUILD_STATUS);\r
+  }\r
+\r
   private void doCompile(final CompileContextImpl compileContext,\r
                          final boolean isRebuild,\r
                          final boolean forceCompile,\r
index 285637bf33f0aa1a9a1b6793e0b09d5da6b01d3e..268b98fcdea5e735b26d9b77083776cb6380de7b 100644 (file)
           <text value="Compile independent modules in parallel"/>\r
         </properties>\r
       </component>\r
+      <component id="91979" class="javax.swing.JLabel">\r
+        <constraints>\r
+          <grid row="6" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>\r
+        </constraints>\r
+        <properties>\r
+          <text value="(may require larger heap size)"/>\r
+        </properties>\r
+      </component>\r
     </children>\r
   </grid>\r
 </form>\r
index ac395c75523020a54cc7b6bdd7a37ded0ac742fa..42d566552ee9ce79b68d5699b1e4f76a89fbb729 100644 (file)
@@ -1,5 +1,7 @@
 package com.intellij.compiler;
 
+import com.intellij.compiler.impl.CompileDriver;
+import com.intellij.compiler.impl.ExitStatus;
 import com.intellij.ide.highlighter.ModuleFileType;
 import com.intellij.openapi.application.Result;
 import com.intellij.openapi.application.WriteAction;
@@ -226,7 +228,9 @@ public abstract class BaseCompilerTestCase extends ModuleTestCase {
               if (aborted) {
                 Assert.fail("compilation aborted");
               }
-              result.set(new CompilationLog(CompilerManagerImpl.getPathsToRecompile(), CompilerManagerImpl.getPathsToDelete(),
+              ExitStatus status = CompileDriver.getExternalBuildExitStatus(compileContext);
+              result.set(new CompilationLog(status == ExitStatus.UP_TO_DATE,
+                                            CompilerManagerImpl.getPathsToRecompile(), CompilerManagerImpl.getPathsToDelete(),
                                             compileContext.getMessages(CompilerMessageCategory.ERROR),
                                             compileContext.getMessages(CompilerMessageCategory.WARNING)));
             }
@@ -363,10 +367,12 @@ public abstract class BaseCompilerTestCase extends ModuleTestCase {
   protected class CompilationLog {
     private final Set<String> myRecompiledPaths;
     private final Set<String> myDeletedPaths;
+    private final boolean myExternalBuildUpToDate;
     private final CompilerMessage[] myErrors;
     private final CompilerMessage[] myWarnings;
 
-    public CompilationLog(String[] recompiledPaths, String[] deletedPaths, CompilerMessage[] errors, CompilerMessage[] warnings) {
+    public CompilationLog(boolean externalBuildUpToDate, String[] recompiledPaths, String[] deletedPaths, CompilerMessage[] errors, CompilerMessage[] warnings) {
+      myExternalBuildUpToDate = externalBuildUpToDate;
       myErrors = errors;
       myWarnings = warnings;
       myRecompiledPaths = getRelativePaths(recompiledPaths);
@@ -374,8 +380,13 @@ public abstract class BaseCompilerTestCase extends ModuleTestCase {
     }
 
     public void assertUpToDate() {
-      checkRecompiled();
-      checkDeleted();
+      if (useExternalCompiler()) {
+        assertTrue(myExternalBuildUpToDate);
+      }
+      else {
+        checkRecompiled();
+        checkDeleted();
+      }
     }
 
     public void assertRecompiled(String... expected) {
index 273ec5f75546f5cad812bbbb0103e8c5860927ad..67e87454336d08fcc676204aad7901e2e9695230 100644 (file)
@@ -51,6 +51,11 @@ public class ExcludedEntriesConfiguration implements PersistentStateComponent<Ex
     myCachedDescriptions = null;
   }
 
+  public synchronized void removeExcludeEntryDescription(ExcludeEntryDescription description) {
+    myExcludeEntryDescriptions.remove(description);
+    myCachedDescriptions = null;
+  }
+
   public synchronized void removeAllExcludeEntryDescriptions() {
     myExcludeEntryDescriptions.clear();
     myCachedDescriptions = null;
index 64a65428a867f5aff805f30333bd4f815e675cb5..b8b6f3babe1de366fadeb269695432921f9c0bbe 100644 (file)
@@ -47,7 +47,7 @@ public class ImportModuleAction extends AnAction {
   public void actionPerformed(AnActionEvent e) {
     final Project project = getEventProject(e);
     FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFileOrFolderDescriptor();
-    descriptor.setTitle("Select File Or Directory To Import");
+    descriptor.setTitle("Select File or Directory to Import");
     ProjectImportProvider[] providers = ProjectImportProvider.PROJECT_IMPORT_PROVIDER.getExtensions();
     List<ProjectImportProvider> list = ContainerUtil.filter(providers, new Condition<ProjectImportProvider>() {
       @Override
index 913eec825c2d5bf91b4a4abc7366762b680e3a43..4e4ef6f268794f1452caa887f68efa3384904158 100644 (file)
@@ -178,7 +178,7 @@ public class SelectTemplateStep extends ModuleWizardStep implements SettingsStep
 
       @Override
       public boolean isAutoExpandNode(NodeDescriptor nodeDescriptor) {
-        return false;
+        return myMatchers != null && myMatchers.length > 0;
       }
 
       @Override
@@ -317,7 +317,9 @@ public class SelectTemplateStep extends ModuleWizardStep implements SettingsStep
     }
 
 //    mySettingsPanel.setVisible(template != null);
-    myExpertPlaceholder.setVisible(!(myModuleBuilder instanceof TemplateModuleBuilder) && myExpertPanel.getComponentCount() > 0);
+    myExpertPlaceholder.setVisible(!(myModuleBuilder instanceof TemplateModuleBuilder) &&
+                                   !(myModuleBuilder instanceof EmptyModuleBuilder) &&
+                                   myExpertPanel.getComponentCount() > 0);
     myDescriptionPanel.setVisible(StringUtil.isNotEmpty(description));
 
     mySettingsPanel.revalidate();
index a20356605adefb87bc04c2a3836d115839d01356..d15b773361ab71f6405ebb9d1b0968675b6e05a1 100644 (file)
@@ -26,7 +26,6 @@ import com.intellij.platform.DirectoryProjectGenerator;
 import com.intellij.platform.ProjectTemplate;
 import com.intellij.platform.ProjectTemplatesFactory;
 import com.intellij.platform.templates.ArchivedProjectTemplate;
-import com.intellij.platform.templates.ArchivedTemplatesFactory;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.MultiMap;
 import org.jetbrains.annotations.NotNull;
@@ -69,7 +68,7 @@ public class CreateFromTemplateMode extends WizardMode {
     for (Map.Entry<String, Collection<ProjectTemplate>> entry : groups.entrySet()) {
       Collection<ProjectTemplate> templates = entry.getValue();
       if (templates.size() == 1 &&
-          !ArchivedTemplatesFactory.CUSTOM_GROUP.equals(entry.getKey())) {
+          !ProjectTemplatesFactory.CUSTOM_GROUP.equals(entry.getKey())) {
 
         if (!(templates.iterator().next() instanceof ArchivedProjectTemplate)) {
           sorted.putValues(ProjectTemplatesFactory.OTHER_GROUP, templates);
index 49cdd88729470fcd2c5647f56ddc3710c5b43117..a6a05afb07b222dc4cfa3c0bc003a64dfbeae915 100644 (file)
@@ -17,7 +17,6 @@ package com.intellij.ide.util.projectWizard;
 
 import com.intellij.ide.util.frameworkSupport.FrameworkSupportUtil;
 import com.intellij.ide.util.newProjectWizard.*;
-import com.intellij.ide.util.newProjectWizard.ProjectNameStep;
 import com.intellij.openapi.projectRoots.Sdk;
 import com.intellij.openapi.projectRoots.SdkType;
 import com.intellij.openapi.projectRoots.SdkTypeId;
@@ -43,7 +42,7 @@ public class ProjectWizardStepFactoryImpl extends ProjectWizardStepFactory {
   }
 
   public ModuleWizardStep createNameAndLocationStep(final WizardContext wizardContext) {
-    return new ProjectNameStep(wizardContext, null);
+    return new ProjectNameStep(wizardContext);
   }
 
   /**
index 4564c89a204e3a07dfd642b49499a89746a16a3f..b5c007e81f2180541755ec0796564638c368bb69 100644 (file)
@@ -15,9 +15,7 @@
  */
 package com.intellij.platform.templates;
 
-import com.intellij.ide.util.newProjectWizard.ProjectNameStep;
 import com.intellij.ide.util.projectWizard.ModuleBuilder;
-import com.intellij.ide.util.projectWizard.WizardContext;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.module.ModuleType;
 import com.intellij.openapi.module.ModuleTypeManager;
@@ -26,7 +24,6 @@ import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.JDOMUtil;
 import com.intellij.openapi.util.io.StreamUtil;
 import com.intellij.platform.ProjectTemplate;
-import com.intellij.ui.IdeBorderFactory;
 import org.jdom.Document;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -47,19 +44,13 @@ public class ArchivedProjectTemplate implements ProjectTemplate {
   private final String myDisplayName;
   private final URL myArchivePath;
   private final ModuleType myModuleType;
-  private final WizardContext myContext;
-  private final ProjectNameStep mySettingsStep;
 
   public ArchivedProjectTemplate(String displayName,
-                                 URL archivePath,
-                                 WizardContext context) {
+                                 URL archivePath) {
 
     myDisplayName = displayName;
     myArchivePath = archivePath;
-    myContext = context;
     myModuleType = computeModuleType(this);
-    mySettingsStep = new ProjectNameStep(context, null);
-    mySettingsStep.getComponent().setBorder(IdeBorderFactory.createEmptyBorder(0));
   }
 
   @NotNull
index 26a014774434e8aabaec549b0f93acc428c0b1fe..ff441c330a52067941769e3f382927bd2a826b1c 100644 (file)
@@ -41,7 +41,6 @@ import java.util.*;
  */
 public class ArchivedTemplatesFactory implements ProjectTemplatesFactory {
 
-  public static final String CUSTOM_GROUP = "Custom";
   private static final String ZIP = ".zip";
 
   private final NotNullLazyValue<MultiMap<String, URL>> myGroups = new NotNullLazyValue<MultiMap<String, URL>>() {
@@ -102,6 +101,11 @@ public class ArchivedTemplatesFactory implements ProjectTemplatesFactory {
     return PathManager.getConfigPath() + "/resources/projectTemplates";
   }
 
+  public static File getTemplateFile(String name) {
+    String configURL = getCustomTemplatesPath();
+    return new File(configURL + "/" + name + ".zip");
+  }
+
   @NotNull
   @Override
   public String[] getGroups() {
@@ -123,7 +127,7 @@ public class ArchivedTemplatesFactory implements ProjectTemplatesFactory {
           if (child.endsWith(ZIP)) {
             URL templateUrl = new URL(url.toExternalForm() + "/" + child);
             String name = child.substring(0, child.length() - ZIP.length()).replace('_', ' ');
-            templates.add(new ArchivedProjectTemplate(name, templateUrl, context));
+            templates.add(new ArchivedProjectTemplate(name, templateUrl));
           }
         }
       }
index 2c35a4cacf2e2830f7168036a89aa8d04ac4e2d1..e4a3cbdb539c4d84876e5151585f44c4bde4f442 100644 (file)
@@ -18,21 +18,32 @@ package com.intellij.platform.templates;
 import com.intellij.CommonBundle;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.components.StorageScheme;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.progress.PerformInBackgroundOption;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.project.ex.ProjectEx;
+import com.intellij.openapi.roots.ContentIterator;
+import com.intellij.openapi.roots.FileIndex;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.ProjectRootManager;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.io.StreamUtil;
 import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.util.io.ZipUtil;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.io.File;
-import java.io.FileFilter;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.zip.ZipEntry;
@@ -44,9 +55,11 @@ import java.util.zip.ZipOutputStream;
  */
 public class SaveProjectAsTemplateAction extends AnAction {
 
+  private static final Logger LOG = Logger.getInstance(SaveProjectAsTemplateAction.class);
+
   @Override
   public void actionPerformed(AnActionEvent e) {
-    Project project = getEventProject(e);
+    final Project project = getEventProject(e);
     assert project != null;
     StorageScheme scheme = ((ProjectEx)project).getStateStore().getStorageScheme();
     if (scheme != StorageScheme.DIRECTORY_BASED) {
@@ -55,52 +68,127 @@ public class SaveProjectAsTemplateAction extends AnAction {
       return;
     }
 
-    VirtualFile descriptionFile = VfsUtil.findRelativeFile(project.getBaseDir(), ArchivedProjectTemplate.DESCRIPTION_PATH.split("/"));
-    SaveProjectAsTemplateDialog dialog = new SaveProjectAsTemplateDialog(project, descriptionFile);
+    final VirtualFile descriptionFile = getDescriptionFile(project);
+    final SaveProjectAsTemplateDialog dialog = new SaveProjectAsTemplateDialog(project, descriptionFile);
+
     if (dialog.showAndGet()) {
-      File file = dialog.getTemplateFile();
-      ZipOutputStream stream = null;
-      try {
-        file.getParentFile().mkdirs();
-        stream = new ZipOutputStream(new FileOutputStream(file));
-
-        VirtualFile dir = getDirectoryToSave(project, dialog.getModuleToSave());
-        String description = dialog.getDescription();
-        if (descriptionFile == null) {
-          stream.putNextEntry(new ZipEntry(dir.getName() + "/" + ArchivedProjectTemplate.DESCRIPTION_PATH));
-          stream.write(description.getBytes());
-          stream.closeEntry();
+
+      final Module moduleToSave = dialog.getModuleToSave();
+      final File file = dialog.getTemplateFile();
+      final String description = dialog.getDescription();
+
+      ProgressManager.getInstance().run(new Task.Backgroundable(project, "Saving Project as Template", true, PerformInBackgroundOption.DEAF) {
+        @Override
+        public void run(@NotNull final ProgressIndicator indicator) {
+          saveProject(project, file, moduleToSave, description, indicator);
         }
-        else {
-          VfsUtil.saveText(descriptionFile, description);
+
+        @Override
+        public void onSuccess() {
+          Messages.showInfoMessage(FileUtil.getNameWithoutExtension(file) + " was successfully created.\n" +
+                                   "It's available now in Project Wizard", "Template Created");
         }
-        ZipUtil.addDirToZipRecursively(stream, null, new File(dir.getPath()), dir.getName(), new FileFilter() {
-          @Override
-          public boolean accept(File pathname) {
-            if (!".idea".equals(pathname.getParent())) return true;
-            // todo filter out some garbage from .idea
-            return true;
+
+        @Override
+        public void onCancel() {
+          file.delete();
+        }
+      });
+    }
+  }
+
+  public static VirtualFile getDescriptionFile(Project project) {
+    return VfsUtil.findRelativeFile(ArchivedProjectTemplate.DESCRIPTION_PATH, project.getBaseDir());
+  }
+
+  public static void saveProject(final Project project,
+                                  final File zipFile,
+                                  Module moduleToSave,
+                                  final String description,
+                                  final ProgressIndicator indicator) {
+
+    indicator.setText("Saving project...");
+    UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+      @Override
+      public void run() {
+        ApplicationManager.getApplication().runWriteAction(new Runnable() {
+          public void run() {
+            project.save();
           }
-        }, null);
-        Messages.showInfoMessage(FileUtil.getNameWithoutExtension(file) + " was successfully created.\n" +
-                                 "It's available now in Project Wizard", "Template Created");
+        });
       }
-      catch (IOException ex) {
-        Messages.showErrorDialog(project, ex.getMessage(), "Error");
+    });
+    indicator.setText("Processing project files...");
+    ZipOutputStream stream = null;
+    try {
+      FileUtil.ensureExists(zipFile.getParentFile());
+      stream = new ZipOutputStream(new FileOutputStream(zipFile));
+
+      final VirtualFile dir = getDirectoryToSave(project, moduleToSave);
+      final VirtualFile descriptionFile = getDescriptionFile(project);
+      if (descriptionFile == null) {
+        stream.putNextEntry(new ZipEntry(dir.getName() + "/" + ArchivedProjectTemplate.DESCRIPTION_PATH));
+        stream.write(description.getBytes());
+        stream.closeEntry();
       }
-      finally {
-        StreamUtil.closeStream(stream);
+      else {
+        UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+          public void run() {
+            try {
+              VfsUtil.saveText(descriptionFile, description);
+            }
+            catch (IOException e) {
+              LOG.error(e);
+            }
+          }
+        });
       }
+
+      FileIndex index = moduleToSave == null
+                        ? ProjectRootManager.getInstance(project).getFileIndex()
+                        : ModuleRootManager.getInstance(moduleToSave).getFileIndex();
+      final ZipOutputStream finalStream = stream;
+      index.iterateContent(new ContentIterator() {
+        @Override
+        public boolean processFile(VirtualFile file) {
+          if (!file.isDirectory()) {
+            indicator.setText2(file.getName());
+            try {
+              String relativePath = VfsUtilCore.getRelativePath(file, dir, '/');
+              if (relativePath == null) {
+                throw new RuntimeException("Can't find relative path for " + file);
+              }
+              ZipUtil.addFileToZip(finalStream, new File(file.getPath()), dir.getName() + "/" + relativePath, null, null);
+            }
+            catch (IOException e) {
+              throw new RuntimeException(e);
+            }
+          }
+          indicator.checkCanceled();
+          // if (!".idea".equals(fileName.getParent())) return true;
+          // todo filter out some garbage from .idea
+          return true;
+        }
+      });
+    }
+    catch (Exception ex) {
+      LOG.error(ex);
+      UIUtil.invokeLaterIfNeeded(new Runnable() {
+        public void run() {
+          Messages.showErrorDialog(project, "Can't save project as template", "Internal Error");
+        }
+      });
+    }
+    finally {
+      StreamUtil.closeStream(stream);
     }
   }
 
-  private static VirtualFile getDirectoryToSave(Project project, @Nullable String moduleName) {
-    if (moduleName == null) {
+  private static VirtualFile getDirectoryToSave(Project project, @Nullable Module module) {
+    if (module == null) {
       return project.getBaseDir();
     }
     else {
-      Module module = ModuleManager.getInstance(project).findModuleByName(moduleName);
-      assert module != null : "Can't find module " + moduleName;
       VirtualFile moduleFile = module.getModuleFile();
       assert moduleFile != null;
       return moduleFile.getParent();
index bd7278ef5a1d4ad581ae1328cab2d99fcc79da8a..860c54f325e1ba7f7352243a5989a2a898440e14 100644 (file)
@@ -45,6 +45,7 @@ import java.util.List;
 public class SaveProjectAsTemplateDialog extends DialogWrapper {
 
   private static final String WHOLE_PROJECT = "<whole project>";
+  @NotNull private final Project myProject;
   private JPanel myPanel;
   private JTextField myName;
   private EditorTextField myDescription;
@@ -53,6 +54,7 @@ public class SaveProjectAsTemplateDialog extends DialogWrapper {
 
   protected SaveProjectAsTemplateDialog(@NotNull Project project, @Nullable VirtualFile descriptionFile) {
     super(project);
+    myProject = project;
 
     setTitle("Save Project As Template");
     Module[] modules = ModuleManager.getInstance(project).getModules();
@@ -113,8 +115,7 @@ public class SaveProjectAsTemplateDialog extends DialogWrapper {
 
   File getTemplateFile() {
     String name = myName.getText();
-    String configURL = ArchivedTemplatesFactory.getCustomTemplatesPath();
-    return new File(configURL + "/" + name + ".zip");
+    return ArchivedTemplatesFactory.getTemplateFile(name);
   }
 
   String getDescription() {
@@ -122,10 +123,10 @@ public class SaveProjectAsTemplateDialog extends DialogWrapper {
   }
 
   @Nullable
-  String getModuleToSave() {
+  Module getModuleToSave() {
     String item = (String)myModuleCombo.getSelectedItem();
     if (item == null || item.equals(WHOLE_PROJECT)) return null;
-    return item;
+    return ModuleManager.getInstance(myProject).findModuleByName(item);
   }
 
   private final static Logger LOG = Logger.getInstance(SaveProjectAsTemplateDialog.class);
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/RefactoringCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/RefactoringCompletionContributor.java
new file mode 100644 (file)
index 0000000..62dbd0d
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.completion;
+
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementDecorator;
+import com.intellij.codeInsight.lookup.LookupElementPresentation;
+import com.intellij.codeInsight.lookup.LookupElementRenderer;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.psi.PsiClass;
+import com.intellij.refactoring.ui.ClassNameReferenceEditor;
+import com.intellij.util.Consumer;
+
+/**
+ * @author peter
+ */
+public class RefactoringCompletionContributor extends CompletionContributor {
+  @Override
+  public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet resultSet) {
+    if (parameters.getOriginalFile().getUserData(ClassNameReferenceEditor.CLASS_NAME_REFERENCE_FRAGMENT) == null) {
+      return;
+    }
+    
+    resultSet.runRemainingContributors(parameters, new Consumer<CompletionResult>() {
+      @Override
+      public void consume(CompletionResult result) {
+        LookupElement element = result.getLookupElement();
+        Object object = element.getObject();
+        if (object instanceof PsiClass) {
+          Module module = ModuleUtil.findModuleForPsiElement((PsiClass)object);
+          if (module != null) {
+            resultSet.consume(LookupElementDecorator.withRenderer(element, new AppendModuleName(module)));
+            return;
+          }
+        }
+        resultSet.passResult(result);
+      }
+    });
+  }
+
+  private static class AppendModuleName extends LookupElementRenderer<LookupElementDecorator<LookupElement>> {
+    private final Module myModule;
+
+    public AppendModuleName(Module module) {
+      myModule = module;
+    }
+
+    @Override
+    public void renderElement(LookupElementDecorator<LookupElement> element, LookupElementPresentation presentation) {
+      element.getDelegate().renderElement(presentation);
+      presentation.appendTailText(" [" + myModule.getName() + "]", true);
+    }
+  }
+}
index 3c04dfc5f3ae845018569c27d4bf7f2d5136ba08..4601188632385c5ee293f455df70f513f0d17471 100644 (file)
@@ -20,6 +20,7 @@ import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.psi.*;
 import com.intellij.psi.javadoc.PsiDocComment;
+import com.intellij.util.containers.CollectionFactory;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Collection;
@@ -39,7 +40,8 @@ public class MethodOrClassSelectioner extends BasicSelectioner {
 
   @Override
   public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
-    List<TextRange> result = super.select(e, editorText, cursorOffset, editor);
+    List<TextRange> result = CollectionFactory.arrayList(e.getTextRange());
+    result.addAll(expandToWholeLinesWithBlanks(editorText, e.getTextRange()));
 
     PsiElement firstChild = e.getFirstChild();
     PsiElement[] children = e.getChildren();
@@ -52,10 +54,10 @@ public class MethodOrClassSelectioner extends BasicSelectioner {
       }
 
       TextRange range = new TextRange(children[i].getTextRange().getStartOffset(), e.getTextRange().getEndOffset());
-      result.addAll(expandToWholeLine(editorText, range));
+      result.addAll(expandToWholeLinesWithBlanks(editorText, range));
 
       range = TextRange.create(firstChild.getTextRange());
-      result.addAll(expandToWholeLine(editorText, range));
+      result.addAll(expandToWholeLinesWithBlanks(editorText, range));
     }
     else if (firstChild instanceof PsiComment) {
       int i = 1;
@@ -66,11 +68,11 @@ public class MethodOrClassSelectioner extends BasicSelectioner {
       PsiElement last = children[i - 1] instanceof PsiWhiteSpace ? children[i - 2] : children[i - 1];
       TextRange range = new TextRange(firstChild.getTextRange().getStartOffset(), last.getTextRange().getEndOffset());
       if (range.contains(cursorOffset)) {
-        result.addAll(expandToWholeLine(editorText, range));
+        result.addAll(expandToWholeLinesWithBlanks(editorText, range));
       }
 
       range = new TextRange(children[i].getTextRange().getStartOffset(), e.getTextRange().getEndOffset());
-      result.addAll(expandToWholeLine(editorText, range));
+      result.addAll(expandToWholeLinesWithBlanks(editorText, range));
     }
 
     if (e instanceof PsiClass) {
@@ -98,7 +100,7 @@ public class MethodOrClassSelectioner extends BasicSelectioner {
     if (start != 0) {
       int end = CodeBlockOrInitializerSelectioner.findClosingBrace(children, start);
 
-      return expandToWholeLine(editorText, new TextRange(start, end));
+      return expandToWholeLinesWithBlanks(editorText, new TextRange(start, end));
     }
     return Collections.emptyList();
   }
index 8ae1771837f326421e08529f3a52fde502d3b09a..898f0e1ca98c414337d583844029213ad66004be 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.intellij.codeInsight.intention.impl;
 
+import com.intellij.codeInsight.AnnotationUtil;
 import com.intellij.codeInsight.CodeInsightBundle;
 import com.intellij.codeInsight.CodeInsightUtilBase;
 import com.intellij.codeInsight.intention.IntentionAction;
@@ -132,11 +133,7 @@ public class ConcatenationToMessageFormatAction implements IntentionAction {
     if (PsiUtil.getLanguageLevel(file).compareTo(LanguageLevel.JDK_1_4) < 0) return false;
     final PsiElement element = findElementAtCaret(editor, file);
     PsiPolyadicExpression binaryExpression = getEnclosingLiteralConcatenation(element);
-    return binaryExpression != null && !isInsideAnnotation(binaryExpression);
-  }
-
-  private static boolean isInsideAnnotation(PsiElement element) {
-    return PsiTreeUtil.getParentOfType(element, PsiNameValuePair.class, PsiArrayInitializerMemberValue.class) != null;
+    return binaryExpression != null && !AnnotationUtil.isInsideAnnotation(binaryExpression);
   }
 
   @Nullable
index db7de4fc67be10c6a84c6c07968e3573ba1340f3..8ff6332998d124c41b6b6d1e4c3e6a98e16fd6f0 100644 (file)
@@ -43,8 +43,8 @@ import com.intellij.openapi.command.WriteCommandAction;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.CaretModel;
 import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.RangeMarker;
 import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory;
-import com.intellij.openapi.module.ModuleUtil;
 import com.intellij.openapi.module.ModuleUtilCore;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.Messages;
@@ -272,15 +272,20 @@ public class CreateSubclassAction extends BaseIntentionAction {
           PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
 
           final TextRange textRange = targetClass.getTextRange();
-          final int startClassOffset = textRange.getStartOffset();
+          final RangeMarker startClassOffset = editor.getDocument().createRangeMarker(textRange.getStartOffset(), textRange.getEndOffset());
           editor.getDocument().deleteString(textRange.getStartOffset(), textRange.getEndOffset());
           CreateFromUsageBaseFix.startTemplate(editor, template, project, new TemplateEditingAdapter() {
             @Override
             public void templateFinished(Template template, boolean brokenOff) {
-              final PsiElement psiElement = containingFile.findElementAt(startClassOffset);
-              final PsiClass aTargetClass = PsiTreeUtil.getParentOfType(psiElement, PsiClass.class);
-              LOG.assertTrue(aTargetClass != null, psiElement);
-              chooseAndImplement(psiClass, project, aTargetClass, editor);
+              try {
+                final PsiElement psiElement = containingFile.findElementAt(startClassOffset.getStartOffset());
+                final PsiClass aTargetClass = PsiTreeUtil.getParentOfType(psiElement, PsiClass.class);
+                LOG.assertTrue(aTargetClass != null, psiElement);
+                chooseAndImplement(psiClass, project, aTargetClass, editor);
+              }
+              finally {
+                startClassOffset.dispose();
+              }
             }
           }, getTitle(psiClass));
         }
index c86e5adfa6d04d271d04c1324f574951af3f607c..e0d1552655801a9c762be60af908905efc093c9f 100644 (file)
@@ -62,11 +62,6 @@ import java.util.*;
 public class EntryPointsManagerImpl implements PersistentStateComponent<Element>, EntryPointsManager {
   @NonNls private static final String[] STANDARD_ANNOS = {
     "javax.ws.rs.*",
-    "javax.annotation.Resource",
-    "javax.xml.ws.WebServiceRef",
-    "javax.persistence.PersistenceContext",
-    "javax.persistence.PersistenceUnit",
-    "javax.persistence.GeneratedValue"
   };
 
   // null means uninitialized
index 7507f9dfd68b9bf534dfe224da4e3470c5d3157b..6c130ec472d17cab57aba5451fec11e97c47c76a 100644 (file)
@@ -26,7 +26,7 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
 import com.intellij.psi.impl.file.JavaDirectoryServiceImpl;
 import com.intellij.util.IncorrectOperationException;
 
-import java.util.Properties;
+import java.util.Map;
 
 /**
  * @author yole
@@ -80,10 +80,10 @@ public class JavaCreateFromTemplateHandler implements CreateFromTemplateHandler
     }
   }
 
-  static void hackAwayEmptyPackage(PsiJavaFile file, FileTemplate template, Properties props) throws IncorrectOperationException {
+  static void hackAwayEmptyPackage(PsiJavaFile file, FileTemplate template, Map<String, Object> props) throws IncorrectOperationException {
     if (!template.isTemplateOfType(StdFileTypes.JAVA)) return;
 
-    String packageName = props.getProperty(FileTemplate.ATTRIBUTE_PACKAGE_NAME);
+    String packageName = (String)props.get(FileTemplate.ATTRIBUTE_PACKAGE_NAME);
     if(packageName == null || packageName.length() == 0 || packageName.equals(FileTemplate.ATTRIBUTE_PACKAGE_NAME)){
       PsiPackageStatement packageStatement = file.getPackageStatement();
       if (packageStatement != null) {
@@ -98,7 +98,7 @@ public class JavaCreateFromTemplateHandler implements CreateFromTemplateHandler
   }
 
   public PsiElement createFromTemplate(final Project project, final PsiDirectory directory, final String fileName, FileTemplate template,
-                                       String templateText, Properties props) throws IncorrectOperationException {
+                                       String templateText, Map<String, Object> props) throws IncorrectOperationException {
     String extension = template.getExtension();
     PsiElement result = createClassOrInterface(project, directory, templateText, template.isReformatCode(), extension);
     hackAwayEmptyPackage((PsiJavaFile)result.getContainingFile(), template, props);
@@ -120,13 +120,11 @@ public class JavaCreateFromTemplateHandler implements CreateFromTemplateHandler
   }
 
   @Override
-  public Properties prepareProperties(Properties props) {
-    String packageName = props.getProperty(FileTemplate.ATTRIBUTE_PACKAGE_NAME);
+  public void prepareProperties(Map<String, Object> props) {
+    String packageName = (String)props.get(FileTemplate.ATTRIBUTE_PACKAGE_NAME);
     if(packageName == null || packageName.length() == 0){
-      props = new Properties(props);
-      props.setProperty(FileTemplate.ATTRIBUTE_PACKAGE_NAME, FileTemplate.ATTRIBUTE_PACKAGE_NAME);
+      props.put(FileTemplate.ATTRIBUTE_PACKAGE_NAME, FileTemplate.ATTRIBUTE_PACKAGE_NAME);
     }
-    return props;
   }
 
   public static boolean canCreate(PsiDirectory dir) {
index 4e513db754672a83a33458c17f2b2985d057f591..647357b0cd6b70837513b90d7510da814003a431 100644 (file)
@@ -19,6 +19,7 @@ import com.intellij.psi.*;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
+import java.util.Map;
 import java.util.Properties;
 
 /**
@@ -53,15 +54,12 @@ public class JavaTemplateUtil {
     properties.setProperty(FileTemplate.ATTRIBUTE_METHOD_NAME, methodName);
   }
 
-  public static void setPackageNameAttribute (@NotNull Properties properties, @NotNull PsiDirectory directory) {
+  public static String getPackageName(@NotNull PsiDirectory directory) {
     PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(directory);
-    if (aPackage != null) {
-      String packageName = aPackage.getQualifiedName();
-      if (packageName.length() > 0) {
-        properties.setProperty(FileTemplate.ATTRIBUTE_PACKAGE_NAME, packageName);
-        return;
-      }
-    }
-    properties.setProperty(FileTemplate.ATTRIBUTE_PACKAGE_NAME, "");
+    return aPackage != null ? aPackage.getQualifiedName() : "";
+  }
+
+  public static void setPackageNameAttribute(@NotNull Properties properties, @NotNull PsiDirectory directory) {
+    properties.setProperty(FileTemplate.ATTRIBUTE_PACKAGE_NAME, getPackageName(directory));
   }
 }
index 7dfb138567b491926d16e3a415711f8ed47fa452..f880d36a6b19ecc2cb05932bc13b6926aa476d32 100644 (file)
@@ -25,6 +25,7 @@ import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
 import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
 
@@ -39,25 +40,26 @@ public class ExcludeCompilerOutputPolicy implements DirectoryIndexExcludePolicy
   }
 
   @Override
-  public boolean isExcludeRoot(final VirtualFile f) {
+  public boolean isExcludeRoot(final VirtualFile file) {
     CompilerProjectExtension compilerProjectExtension = CompilerProjectExtension.getInstance(myProject);
-    if (isEqualWithFileOrUrl(f, compilerProjectExtension.getCompilerOutput(), compilerProjectExtension.getCompilerOutputUrl())) return true;
+    if (isEqualWithFileOrUrl(file, compilerProjectExtension.getCompilerOutput(), compilerProjectExtension.getCompilerOutputUrl())) return true;
 
     for (Module m : ModuleManager.getInstance(myProject).getModules()) {
       CompilerModuleExtension rm = CompilerModuleExtension.getInstance(m);
-      if (isEqualWithFileOrUrl(f, rm.getCompilerOutputPath(), rm.getCompilerOutputUrl())) return true;
-      if (isEqualWithFileOrUrl(f, rm.getCompilerOutputPathForTests(), rm.getCompilerOutputUrlForTests())) return true;
+      if (isEqualWithFileOrUrl(file, rm.getCompilerOutputPath(), rm.getCompilerOutputUrl())) return true;
+      if (isEqualWithFileOrUrl(file, rm.getCompilerOutputPathForTests(), rm.getCompilerOutputUrlForTests())) return true;
     }
     return false;
   }
 
   @Override
-  public boolean isExcludeRootForModule(final Module module, final VirtualFile excludeRoot) {
+  public boolean isExcludeRootForModule(@NotNull final Module module, final VirtualFile excludeRoot) {
     final CompilerModuleExtension compilerModuleExtension = CompilerModuleExtension.getInstance(module);
     return Comparing.equal(compilerModuleExtension.getCompilerOutputPath(), excludeRoot) ||
            Comparing.equal(compilerModuleExtension.getCompilerOutputPathForTests(), excludeRoot);
   }
 
+  @NotNull
   @Override
   public VirtualFile[] getExcludeRootsForProject() {
     VirtualFile outputPath = CompilerProjectExtension.getInstance(myProject).getCompilerOutput();
@@ -67,8 +69,9 @@ public class ExcludeCompilerOutputPolicy implements DirectoryIndexExcludePolicy
     return VirtualFile.EMPTY_ARRAY;
   }
 
+  @NotNull
   @Override
-  public VirtualFilePointer[] getExcludeRootsForModule(final ModuleRootModel rootModel) {
+  public VirtualFilePointer[] getExcludeRootsForModule(@NotNull final ModuleRootModel rootModel) {
     ArrayList<VirtualFilePointer> result = new ArrayList<VirtualFilePointer>();
     final CompilerModuleExtension extension = rootModel.getModuleExtension(CompilerModuleExtension.class);
     if (extension == null) {
@@ -87,12 +90,12 @@ public class ExcludeCompilerOutputPolicy implements DirectoryIndexExcludePolicy
     return result.isEmpty() ? VirtualFilePointer.EMPTY_ARRAY : result.toArray(new VirtualFilePointer[result.size()]);
   }
 
-  private static boolean isEqualWithFileOrUrl(VirtualFile f, VirtualFile fileToCompareWith, String url) {
+  private static boolean isEqualWithFileOrUrl(VirtualFile file, VirtualFile fileToCompareWith, String url) {
     if (fileToCompareWith != null) {
-      if (Comparing.equal(fileToCompareWith, f)) return true;
+      if (Comparing.equal(fileToCompareWith, file)) return true;
     }
     else if (url != null) {
-      if (FileUtil.pathsEqual(url, f.getUrl())) return true;
+      if (FileUtil.pathsEqual(url, file.getUrl())) return true;
     }
     return false;
   }
index 9c70587cc12bc07f8866eef0139eed8da73be806..022f69acc9b7a9ea31a7af48c3f652ee0a3fad84 100644 (file)
@@ -18,6 +18,7 @@ package com.intellij.psi.impl.source.resolve.reference.impl.providers;
 import com.intellij.lang.ASTNode;
 import com.intellij.lang.Language;
 import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.ex.dummy.DummyFileSystem;
 import com.intellij.psi.*;
@@ -57,7 +58,7 @@ class PackagePrefixFileSystemItem extends PsiElementBase implements PsiFileSyste
   @Override
   @NotNull
   public String getName() {
-    return myPackages[myIndex].getName();
+    return StringUtil.notNullize(myPackages[myIndex].getName());
   }
 
   @Override
index bb32a53612baa4b4257e4fdf331572046ea72f27..522ea10336f83ca2f0da107f9b89cc150c03b55f 100644 (file)
@@ -25,6 +25,7 @@ import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.psi.*;
+import com.intellij.psi.impl.light.LightModifierList;
 import com.intellij.psi.util.PsiTreeUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -138,10 +139,12 @@ public class JavaChangeSignatureDetector implements LanguageChangeSignatureDetec
   private static boolean isInsideMethodSignature(PsiElement element, @NotNull PsiMethod method) {
     final PsiCodeBlock body = method.getBody();
     final TextRange textRange = element.getTextRange();
+    final PsiModifierList psiModifierList = method.getModifierList();
+    if (psiModifierList instanceof LightModifierList) return false;
     if (body != null) {
-      return textRange.getEndOffset() <= body.getTextOffset() && textRange.getStartOffset() >= method.getModifierList().getTextRange().getEndOffset();
+      return textRange.getEndOffset() <= body.getTextOffset() && textRange.getStartOffset() >= psiModifierList.getTextRange().getEndOffset();
     }
-    return textRange.getStartOffset() >= method.getModifierList().getTextRange().getEndOffset() &&
+    return textRange.getStartOffset() >= psiModifierList.getTextRange().getEndOffset() &&
            textRange.getEndOffset() <= method.getTextRange().getEndOffset();
   }
 
index 4b5f32ccf1b53561542ae73e71a28aba44ce2144..344a5f0cc3f4cfb16e8cc62d0b4f6e186c1b32a5 100644 (file)
@@ -115,7 +115,11 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
     });
 
     final PsiCodeBlock containerBlock = PsiTreeUtil.getParentOfType(local, PsiCodeBlock.class);
-    LOG.assertTrue(containerBlock != null, local);
+    if (containerBlock == null) {
+      final String message = RefactoringBundle.getCannotRefactorMessage("Variable is declared outside a code block");
+      CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE);
+      return;
+    }
 
     final PsiExpression defToInline = innerClassesWithUsages.isEmpty()
                                       ? getDefToInline(local, refExpr, containerBlock)
index 6f506022caf08fd6bf717336314d578af1d5347b..09f26a48179043a09ee2683ef13e8c9b07951fc1 100644 (file)
@@ -389,7 +389,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
       if (hasErrors[0]) return null;
 
       final PsiReferenceExpression refExpr = PsiTreeUtil.getParentOfType(toBeExpression.findElementAt(refIdx[0]), PsiReferenceExpression.class);
-      assert refExpr != null;
+      if (refExpr == null) return null;
       if (toBeExpression == refExpr && refIdx[0] > 0) {
         return null;
       }
index 4b440d6a26dc53c682029c5c5e0552bc1a7eb464..bf80d601c81bdf51c07b89e807ff05e427777aaf 100644 (file)
@@ -343,7 +343,9 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor {
     }
     else {
       myLabeler.setConversionMapping(expression, conversion);
-      myTypeEvaluator.setType(new TypeMigrationUsageInfo(expression), myTypeEvaluator.evaluateType(expression));
+      final PsiType psiType = myTypeEvaluator.evaluateType(expression);
+      LOG.assertTrue(psiType != null,  expression);
+      myTypeEvaluator.setType(new TypeMigrationUsageInfo(expression), psiType);
     }
   }
 
index ecb1c9b31c17d5d7412404211ea31de7c95993c1..d9df37ab69ee699a7d136c176c2e7ff6d848d971 100644 (file)
@@ -20,6 +20,7 @@ import com.intellij.ide.util.TreeClassChooser;
 import com.intellij.ide.util.TreeClassChooserFactory;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
 import com.intellij.psi.*;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.util.Function;
@@ -34,6 +35,7 @@ import java.awt.event.ActionListener;
  * @author yole
  */
 public class ClassNameReferenceEditor extends ReferenceEditorWithBrowseButton {
+  public static final Key<Boolean> CLASS_NAME_REFERENCE_FRAGMENT = Key.create("CLASS_NAME_REFERENCE_FRAGMENT");
   private Project myProject;
   private PsiClass mySelectedClass;
   private String myChooserTitle;
@@ -52,6 +54,7 @@ public class ClassNameReferenceEditor extends ReferenceEditorWithBrowseButton {
         if (resolveScope != null) {
           fragment.forceResolveScope(resolveScope);
         }
+        fragment.putUserData(CLASS_NAME_REFERENCE_FRAGMENT, true);
         return PsiDocumentManager.getInstance(project).getDocument(fragment);
       }
     }, selectedClass != null ? selectedClass.getQualifiedName() : "");
index 1ceaaa9295dd13d4a38f0fb66a22d52a1dc50e39..a4aa95266d537264291c11fa956223e8625793e4 100644 (file)
@@ -32,7 +32,12 @@ public class AnnotatedElementsSearcher implements QueryExecutor<PsiModifierListO
     final PsiClass annClass = p.getAnnotationClass();
     assert annClass.isAnnotationType() : "Annotation type should be passed to annotated members search";
 
-    final String annotationFQN = annClass.getQualifiedName();
+    final String annotationFQN = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+      @Override
+      public String compute() {
+        return annClass.getQualifiedName();
+      }
+    });
     assert annotationFQN != null;
 
     final PsiManagerImpl psiManager = (PsiManagerImpl)annClass.getManager();
index d9e801eb08a52727068e17c2ada561f9d94bf913..0ca2c370968002d33b13f6aa571115a43be85f81 100644 (file)
@@ -424,4 +424,8 @@ public class AnnotationUtil {
     }
     return annotations;
   }
+
+  public static boolean isInsideAnnotation(PsiElement element) {
+    return PsiTreeUtil.getParentOfType(element, PsiNameValuePair.class, PsiArrayInitializerMemberValue.class) != null;
+  }
 }
index e8c043bc7431caf0ea1db873edbc204f1a2d7396..dd339ffc4cefe388ffb96671c06776730f0c8df9 100644 (file)
@@ -92,4 +92,5 @@ public interface CommonClassNames {
   @NonNls String JAVA_IO_FILE = "java.io.File";
   String JAVA_LANG_ASSERTION_ERROR = "java.lang.AssertionError";
   @NonNls String JAVA_UTIL_CONCURRENT_CALLABLE = "java.util.concurrent.Callable";
+  @NonNls String JAVA_UTIL_MAP_ENTRY = "java.util.Map.Entry";
 }
index 2fd912939d7ec31ce80788555c0d3888b6e0def2..1d6834be1dcb76094cd542cc629b23c446dcc7a8 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.intellij.psi;
 
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.Pair;
 import com.intellij.psi.search.GlobalSearchScope;
@@ -33,6 +34,8 @@ import java.util.*;
  */
 public class GenericsUtil {
 
+  private static final Logger LOG = Logger.getInstance("#" + GenericsUtil.class.getName());
+
   private GenericsUtil() {}
 
   public static PsiType getGreatestLowerBound(PsiType type1, PsiType type2) {
@@ -296,6 +299,7 @@ public class GenericsUtil {
               toPut = accepted;
             }
           }
+          LOG.assertTrue(toPut == null || toPut.isValid(), toPut);
           substitutor = substitutor.put(typeParameter, toPut);
         }
         final PsiAnnotation[] applicableAnnotations = classType.getApplicableAnnotations();
index 4e9f5e68a6f8cfd67d599debf2ae6fc740370e12..e311029cd77d70daaa4d7603465b2ce5527ac489 100644 (file)
  */\r
 package com.intellij.core;\r
 \r
+import com.intellij.openapi.util.Comparing;\r
 import com.intellij.psi.*;\r
 import com.intellij.psi.codeStyle.JavaCodeStyleManager;\r
 import com.intellij.psi.codeStyle.SuggestedNameInfo;\r
 import com.intellij.psi.codeStyle.VariableKind;\r
+import com.intellij.psi.util.PsiTreeUtil;\r
+import com.intellij.psi.util.PsiUtil;\r
+import com.intellij.util.ArrayUtil;\r
 import com.intellij.util.IncorrectOperationException;\r
 import org.intellij.lang.annotations.MagicConstant;\r
 import org.jetbrains.annotations.NonNls;\r
@@ -26,6 +30,7 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;\r
 \r
 import java.util.Collection;\r
+import java.util.LinkedHashSet;\r
 \r
 public class CoreJavaCodeStyleManager extends JavaCodeStyleManager {\r
   @Override\r
@@ -96,16 +101,75 @@ public class CoreJavaCodeStyleManager extends JavaCodeStyleManager {
 \r
   @Override\r
   public String suggestUniqueVariableName(@NonNls String baseName, PsiElement place, boolean lookForward) {\r
-    return null;\r
+    int index = 0;\r
+    PsiElement scope = PsiTreeUtil.getNonStrictParentOfType(place, PsiStatement.class, PsiCodeBlock.class, PsiMethod.class);\r
+    NextName:\r
+    while (true) {\r
+      String name = baseName;\r
+      if (index > 0) {\r
+        name += index;\r
+      }\r
+      index++;\r
+      if (PsiUtil.isVariableNameUnique(name, place)) {\r
+        if (lookForward) {\r
+          final String name1 = name;\r
+          PsiElement run = scope;\r
+          while (run != null) {\r
+            class CancelException extends RuntimeException {\r
+            }\r
+            try {\r
+              run.accept(new JavaRecursiveElementWalkingVisitor() {\r
+                @Override\r
+                public void visitAnonymousClass(final PsiAnonymousClass aClass) {\r
+                }\r
+\r
+                @Override public void visitVariable(PsiVariable variable) {\r
+                  if (name1.equals(variable.getName())) {\r
+                    throw new CancelException();\r
+                  }\r
+                }\r
+              });\r
+            }\r
+            catch (CancelException e) {\r
+              continue NextName;\r
+            }\r
+            run = run.getNextSibling();\r
+            if (scope instanceof PsiMethod) {//do not check next member for param name conflict\r
+              break;\r
+            }\r
+          }\r
+\r
+        }\r
+        return name;\r
+      }\r
+    }\r
   }\r
 \r
   @NotNull\r
   @Override\r
-  public SuggestedNameInfo suggestUniqueVariableName(@NotNull SuggestedNameInfo baseNameInfo,\r
+  public SuggestedNameInfo suggestUniqueVariableName(@NotNull final SuggestedNameInfo baseNameInfo,\r
                                                      PsiElement place,\r
                                                      boolean ignorePlaceName,\r
                                                      boolean lookForward) {\r
-    return SuggestedNameInfo.NULL_INFO;\r
+    final String[] names = baseNameInfo.names;\r
+    final LinkedHashSet<String> uniqueNames = new LinkedHashSet<String>(names.length);\r
+    for (String name : names) {\r
+      if (ignorePlaceName && place instanceof PsiNamedElement) {\r
+        final String placeName = ((PsiNamedElement)place).getName();\r
+        if (Comparing.strEqual(placeName, name)) {\r
+          uniqueNames.add(name);\r
+          continue;\r
+        }\r
+      }\r
+      uniqueNames.add(suggestUniqueVariableName(name, place, lookForward));\r
+    }\r
+\r
+    return new SuggestedNameInfo(ArrayUtil.toStringArray(uniqueNames)) {\r
+      @Override\r
+      public void nameChosen(String name) {\r
+        baseNameInfo.nameChosen(name);\r
+      }\r
+    };\r
   }\r
 \r
   @Override\r
index 0c37ad317ebc148c2af9b1098bf405a8dd00f446..72a4c6a04637a2338a4bd2457a331bc2802f922b 100644 (file)
@@ -266,7 +266,7 @@ public class ExpressionParser {
       builder.advanceLexer();
 
       final ReferenceParser.TypeInfo typeInfo =
-        myParser.getReferenceParser().parseTypeInfo(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD);
+        myParser.getReferenceParser().parseTypeInfo(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD | ReferenceParser.CONJUNCTIONS);
       if (typeInfo == null || !expect(builder, JavaTokenType.RPARENTH)) {
         typeCast.rollbackTo();
         return parsePostfix(builder);
index 461e6efd75fed7b89839a96c5b6266810c1bd9bb..989f895393b017c9e85cadc96d02137e287fa77c 100644 (file)
@@ -28,6 +28,8 @@ import org.jetbrains.annotations.Nullable;
 import static com.intellij.lang.PsiBuilderUtil.expect;
 import static com.intellij.lang.java.parser.JavaParserUtil.*;
 import static com.intellij.util.BitUtil.isSet;
+import static com.intellij.util.BitUtil.notSet;
+import static com.intellij.util.BitUtil.set;
 
 public class ReferenceParser {
   public static final int EAT_LAST_DOT = 0x01;
@@ -35,6 +37,7 @@ public class ReferenceParser {
   public static final int WILDCARD = 0x04;
   public static final int DIAMONDS = 0x08;
   public static final int DISJUNCTIONS = 0x10;
+  public static final int CONJUNCTIONS = 0x20;
 
   public static class TypeInfo {
     public boolean isPrimitive = false;
@@ -61,29 +64,32 @@ public class ReferenceParser {
 
   @Nullable
   public TypeInfo parseTypeInfo(final PsiBuilder builder, final int flags) {
-    final TypeInfo typeInfo = parseTypeInfo(builder, isSet(flags, EAT_LAST_DOT), isSet(flags, WILDCARD), false, isSet(flags, DIAMONDS),
-                                            isSet(flags, ELLIPSIS));
+    final TypeInfo typeInfo = parseTypeInfo(builder, flags, false);
 
-    if (typeInfo != null && isSet(flags, DISJUNCTIONS) && builder.getTokenType() == JavaTokenType.OR) {
-      typeInfo.marker = typeInfo.marker.precede();
+    if (typeInfo != null) {
+      assert notSet(flags, DISJUNCTIONS|CONJUNCTIONS) : "don't not set both flags simultaneously";
+      final IElementType operator = isSet(flags, DISJUNCTIONS) ? JavaTokenType.OR : isSet(flags, CONJUNCTIONS) ? JavaTokenType.AND : null;
 
-      while (builder.getTokenType() == JavaTokenType.OR) {
-        builder.advanceLexer();
-        if (builder.getTokenType() != JavaTokenType.IDENTIFIER) {
-          error(builder, JavaErrorMessages.message("expected.identifier"));
+      if (operator != null && builder.getTokenType() == operator) {
+        typeInfo.marker = typeInfo.marker.precede();
+
+        while (builder.getTokenType() == operator) {
+          builder.advanceLexer();
+          if (builder.getTokenType() != JavaTokenType.IDENTIFIER) {
+            error(builder, JavaErrorMessages.message("expected.identifier"));
+          }
+          parseTypeInfo(builder, flags, false);
         }
-        parseTypeInfo(builder, isSet(flags, EAT_LAST_DOT), isSet(flags, WILDCARD), false, isSet(flags, DIAMONDS), isSet(flags, ELLIPSIS));
-      }
 
-      typeInfo.marker.done(JavaElementType.TYPE);
+        typeInfo.marker.done(JavaElementType.TYPE);
+      }
     }
 
     return typeInfo;
   }
 
   @Nullable
-  private TypeInfo parseTypeInfo(final PsiBuilder builder, final boolean eatLastDot, final boolean wildcard, final boolean badWildcard,
-                                 final boolean diamonds, final boolean ellipsis) {
+  private TypeInfo parseTypeInfo(final PsiBuilder builder, final int flags, final boolean badWildcard) {
     if (builder.getTokenType() == null) return null;
 
     final TypeInfo typeInfo = new TypeInfo();
@@ -96,14 +102,14 @@ public class ReferenceParser {
       typeInfo.isPrimitive = true;
     }
     else if (tokenType == JavaTokenType.IDENTIFIER) {
-      parseJavaCodeReference(builder, eatLastDot, true, false, false, false, diamonds, typeInfo);
+      parseJavaCodeReference(builder, isSet(flags, EAT_LAST_DOT), true, false, false, false, isSet(flags, DIAMONDS), typeInfo);
     }
-    else if ((wildcard || badWildcard) && tokenType == JavaTokenType.QUEST) {
+    else if ((isSet(flags, WILDCARD) || badWildcard) && tokenType == JavaTokenType.QUEST) {
       type.drop();
-      typeInfo.marker = parseWildcardType(builder, wildcard);
+      typeInfo.marker = parseWildcardType(builder, isSet(flags, WILDCARD));
       return typeInfo.marker != null ? typeInfo : null;
     }
-    else if (diamonds && tokenType == JavaTokenType.GT) {
+    else if (isSet(flags, DIAMONDS) && tokenType == JavaTokenType.GT) {
       emptyElement(builder, JavaElementType.DIAMOND_TYPE);
       type.done(JavaElementType.TYPE);
       typeInfo.marker = type;
@@ -133,7 +139,7 @@ public class ReferenceParser {
       type = type.precede();
     }
 
-    if (ellipsis && builder.getTokenType() == JavaTokenType.ELLIPSIS) {
+    if (isSet(flags, ELLIPSIS) && builder.getTokenType() == JavaTokenType.ELLIPSIS) {
       type = type.precede();
       builder.advanceLexer();
       type.done(JavaElementType.TYPE);
@@ -263,9 +269,10 @@ public class ReferenceParser {
       return false;
     }
 
+    final int flags = set(set(EAT_LAST_DOT, WILDCARD, wildcard), DIAMONDS, diamonds);
     boolean isOk = true;
     while (true) {
-      if (parseTypeInfo(builder, true, wildcard, true, diamonds, false) == null) {
+      if (parseTypeInfo(builder, flags, true) == null) {
         error(builder, JavaErrorMessages.message("expected.identifier"));
       }
       else {
index 576a40ebec842686fc40611c8ae3ae517044bbca..8230bc75702bb02114734dfe410137fcd03fc200 100644 (file)
@@ -1,18 +1,28 @@
 PsiJavaFile:LambdaExpression12.java
-  PsiErrorElement:Unparsed tokens
-    PsiJavaToken:LT('<')
-    PsiIdentifier:T('T')
-    PsiJavaToken:GT('>')
+  PsiTypeCastExpression:(I1 & I2) () -> null
     PsiJavaToken:LPARENTH('(')
+    PsiTypeElement:I1 & I2
+      PsiTypeElement:I1
+        PsiJavaCodeReferenceElement:I1
+          PsiIdentifier:I1('I1')
+          PsiReferenceParameterList
+            <empty list>
+      PsiWhiteSpace(' ')
+      PsiJavaToken:AND('&')
+      PsiWhiteSpace(' ')
+      PsiTypeElement:I2
+        PsiJavaCodeReferenceElement:I2
+          PsiIdentifier:I2('I2')
+          PsiReferenceParameterList
+            <empty list>
     PsiJavaToken:RPARENTH(')')
     PsiWhiteSpace(' ')
-    PsiJavaToken:ARROW('->')
-    PsiWhiteSpace(' ')
-    PsiKeyword:new('new')
-    PsiWhiteSpace(' ')
-    PsiIdentifier:C('C')
-    PsiJavaToken:LT('<')
-    PsiIdentifier:T('T')
-    PsiJavaToken:GT('>')
-    PsiJavaToken:LPARENTH('(')
-    PsiJavaToken:RPARENTH(')')
\ No newline at end of file
+    PsiLambdaExpression:() -> null
+      PsiParameterList:()
+        PsiJavaToken:LPARENTH('(')
+        PsiJavaToken:RPARENTH(')')
+      PsiWhiteSpace(' ')
+      PsiJavaToken:ARROW('->')
+      PsiWhiteSpace(' ')
+      PsiLiteralExpression:null
+        PsiJavaToken:NULL_KEYWORD('null')
\ No newline at end of file
index 2b6c6786cfbbc3b0679af095087032df5e0e83a7..6d3574958161833583df693f0346a7bdd407a2e9 100644 (file)
@@ -1,10 +1,29 @@
 PsiJavaFile:LambdaExpression13.java
-  PsiErrorElement:Unparsed tokens
-    PsiJavaToken:LT('<')
-    PsiIdentifier:T('T')
-    PsiJavaToken:GT('>')
-    PsiIdentifier:t('t')
+  PsiTypeCastExpression:(I1 & I2) () -> {}
+    PsiJavaToken:LPARENTH('(')
+    PsiTypeElement:I1 & I2
+      PsiTypeElement:I1
+        PsiJavaCodeReferenceElement:I1
+          PsiIdentifier:I1('I1')
+          PsiReferenceParameterList
+            <empty list>
+      PsiWhiteSpace(' ')
+      PsiJavaToken:AND('&')
+      PsiWhiteSpace(' ')
+      PsiTypeElement:I2
+        PsiJavaCodeReferenceElement:I2
+          PsiIdentifier:I2('I2')
+          PsiReferenceParameterList
+            <empty list>
+    PsiJavaToken:RPARENTH(')')
     PsiWhiteSpace(' ')
-    PsiJavaToken:ARROW('->')
-    PsiWhiteSpace(' ')
-    PsiIdentifier:t('t')
\ No newline at end of file
+    PsiLambdaExpression:() -> {}
+      PsiParameterList:()
+        PsiJavaToken:LPARENTH('(')
+        PsiJavaToken:RPARENTH(')')
+      PsiWhiteSpace(' ')
+      PsiJavaToken:ARROW('->')
+      PsiWhiteSpace(' ')
+      PsiCodeBlock
+        PsiJavaToken:LBRACE('{')
+        PsiJavaToken:RBRACE('}')
\ No newline at end of file
index 8f5726aba7f3b2397e2fea27835c25189f2f9ac8..4a30c6dcbf6762316e996498805e8b6ec2d227ca 100644 (file)
@@ -134,15 +134,14 @@ public class ExpressionParserTest extends JavaParsingTestCase {
   public void testLambdaExpression9() { doParserTest("(I)p -> null"); }
   public void testLambdaExpression10() { doParserTest("(I)(p -> null)"); }
   public void testLambdaExpression11() { doParserTest("() -> { }"); }
-  public void testLambdaExpression12() { doParserTest("<T>() -> new C<T>()"); }  // these two expressions
-  public void testLambdaExpression13() { doParserTest("<T>t -> t"); }            // should no longer be parsed
+  public void testLambdaExpression12() { doParserTest("(I1 & I2) () -> null"); }
+  public void testLambdaExpression13() { doParserTest("(I1 & I2) () -> {}"); }
   public void testLambdaExpression14() { doParserTest("(String t) -> t"); }
   public void testLambdaExpression15() { doParserTest("(int a, int b) -> a + b"); }
   public void testLambdaExpression16() { doParserTest("(final int x) -> x"); }
   public void testLambdaExpression17() { doParserTest("(String s -> s"); }
   public void testLambdaExpression18() { doParserTest("(java.lang.String s, -> s"); }
   public void testLambdaExpression19() { doParserTest("(@A T t) -> (null)"); }
-
   public void testAmbiguousLambdaExpression() { doParserTest("f( (x) < y , z > (w) -> v )"); }
 
   private void doParserTest(@NonNls final String text) {
index c2ce19f6e3fcbb311982bd81e98a91cb9244c9f4..b7224d01c32749745a91ce1275afc30ade2218f3 100644 (file)
@@ -19,6 +19,8 @@ package com.intellij.ide.util.projectWizard;
 import com.intellij.openapi.module.ModuleType;
 import com.intellij.openapi.module.StdModuleTypes;
 import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.projectRoots.JavaSdkType;
+import com.intellij.openapi.projectRoots.SdkTypeId;
 import com.intellij.openapi.roots.CompilerModuleExtension;
 import com.intellij.openapi.roots.ContentEntry;
 import com.intellij.openapi.roots.ModifiableRootModel;
@@ -75,6 +77,11 @@ public class JavaModuleBuilder extends ModuleBuilder implements SourcePathsBuild
     return StdModuleTypes.JAVA;
   }
 
+  @Override
+  public boolean isSuitableSdkType(SdkTypeId sdkType) {
+    return sdkType instanceof JavaSdkType;
+  }
+
   @Nullable
   @Override
   public ModuleWizardStep modifySettingsStep(SettingsStep settingsStep) {
index 4a6fa8411493d492aae36ca111dad343077c9987..39ba1c7685c4a896d1ce70c1cc87cb0a36a5337e 100644 (file)
@@ -1,7 +1,11 @@
 package org.jetbrains.jps.builders;
 
+import org.jetbrains.annotations.NotNull;
+
 import java.io.File;
 import java.io.FileFilter;
+import java.util.Collections;
+import java.util.Set;
 
 /**
  * @author nik
@@ -15,6 +19,14 @@ public abstract class BuildRootDescriptor {
 
   public abstract FileFilter createFileFilter();
 
+  /**
+   * @return the set of excluded directories under this root
+   */
+  @NotNull
+  public Set<File> getExcludedRoots() {
+    return Collections.emptySet();
+  }
+
   public boolean isGenerated() {
     return false;
   }
index 990f64280b1c3c545319bcd756ee124d4c4ff9c2..286daf4dadd380104041e9ffe20a8b3bcf926488 100644 (file)
@@ -41,7 +41,7 @@ public abstract class BuildTarget<R extends BuildRootDescriptor> {
                                                  BuildDataPaths dataPaths);
 
   @Nullable
-  public abstract BuildRootDescriptor findRootDescriptor(String rootId, BuildRootIndex rootIndex);
+  public abstract R findRootDescriptor(String rootId, BuildRootIndex rootIndex);
 
   @NotNull
   public abstract String getPresentableName();
index 6171a13bf81ad1ccbd2bfdff0f85a24aec36d0c5..2100b0b383f313976c480c8efb03f1417b7fc97a 100644 (file)
@@ -8,11 +8,9 @@ import com.intellij.util.containers.ConcurrentHashMap;
 import gnu.trove.THashMap;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jps.ProjectPaths;
 import org.jetbrains.jps.builders.*;
 import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
 import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
-import org.jetbrains.jps.builders.java.ResourcesOnlyRootDescriptor;
 import org.jetbrains.jps.builders.storage.BuildDataPaths;
 import org.jetbrains.jps.incremental.BuilderRegistry;
 import org.jetbrains.jps.incremental.CompileContext;
@@ -20,10 +18,6 @@ import org.jetbrains.jps.incremental.ModuleBuildTarget;
 import org.jetbrains.jps.indices.IgnoredFileIndex;
 import org.jetbrains.jps.indices.ModuleExcludeIndex;
 import org.jetbrains.jps.model.JpsModel;
-import org.jetbrains.jps.model.JpsProject;
-import org.jetbrains.jps.model.java.JpsJavaExtensionService;
-import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
-import org.jetbrains.jps.model.java.compiler.ProcessorConfigProfile;
 import org.jetbrains.jps.service.JpsServiceManager;
 
 import java.io.File;
@@ -52,41 +46,6 @@ public class BuildRootIndexImpl implements BuildRootIndex {
         addRoots(dataPaths, rootsProviders, target, model, index, ignoredFileIndex);
       }
     }
-
-    // registering resource-only roots for annotation processor's generated classes
-    Map<String, List<ModuleBuildTarget>> moduleNameToTargetsMap = null;
-
-    final JpsProject project = model.getProject();
-    final ProjectPaths paths = new ProjectPaths(project);
-    final JpsJavaCompilerConfiguration compilerConfig = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
-    for (ProcessorConfigProfile profile : compilerConfig.getAnnotationProcessingConfigurations()) {
-      if (!profile.isEnabled()) {
-        continue;
-      }
-      for (String moduleName : profile.getModuleNames()) {
-        if (moduleNameToTargetsMap == null) {
-          moduleNameToTargetsMap = buildModuleNameToTargetsMap(targetIndex); // lazy init
-        }
-        final List<ModuleBuildTarget> targets = moduleNameToTargetsMap.get(moduleName);
-        if (targets != null) {
-          for (ModuleBuildTarget target : targets) {
-            final File annotationOut = paths.getAnnotationProcessorGeneratedSourcesOutputDir(target.getModule(), target.isTests(), profile);
-            if (annotationOut != null) {
-              if (findJavaRootDescriptor(null, annotationOut) == null && !FileUtil.filesEqual(annotationOut, target.getOutputDir())) {
-                // register only if the root is not under already existing roots and not is the same as target's output root
-                final ResourcesOnlyRootDescriptor descriptor = new ResourcesOnlyRootDescriptor(annotationOut, target, true, false, "");
-                registerDescriptor(descriptor);
-                //noinspection unchecked
-                final List<BuildRootDescriptor> descriptors = (List<BuildRootDescriptor>)myRootsByTarget.get(target);
-                assert descriptors != null;
-                descriptors.add(descriptor);
-              }
-            }
-          }
-        }
-      }
-    }
-
   }
 
   private <R extends BuildRootDescriptor> void addRoots(BuildDataPaths dataPaths, Iterable<AdditionalRootsProviderService> rootsProviders,
index a31e82a44537bc57fc9f48503c7edf95558fefb3..27a13fad69bd9e3d5a59909b766ff322771e6f85 100644 (file)
@@ -9,6 +9,7 @@ import org.jetbrains.jps.model.java.compiler.JpsCompilerExcludes;
 
 import java.io.File;
 import java.io.FileFilter;
+import java.util.Set;
 
 /**
 * @author Eugene Zhuravlev
@@ -22,13 +23,20 @@ public class JavaSourceRootDescriptor extends BuildRootDescriptor {
   public final boolean isGeneratedSources;
   public final boolean isTemp;
   private final String myPackagePrefix;
+  private final Set<File> myExcludes;
 
-  public JavaSourceRootDescriptor(@NotNull File root, @NotNull ModuleBuildTarget target, boolean isGenerated, boolean isTemp, @NotNull String packagePrefix) {
+  public JavaSourceRootDescriptor(@NotNull File root,
+                                  @NotNull ModuleBuildTarget target,
+                                  boolean isGenerated,
+                                  boolean isTemp,
+                                  @NotNull String packagePrefix,
+                                  @NotNull Set<File> excludes) {
     this.root = root;
     this.target = target;
     this.isGeneratedSources = isGenerated;
     this.isTemp = isTemp;
     myPackagePrefix = packagePrefix;
+    myExcludes = excludes;
   }
 
   @Override
@@ -40,6 +48,12 @@ public class JavaSourceRootDescriptor extends BuildRootDescriptor {
            '}';
   }
 
+  @NotNull
+  @Override
+  public Set<File> getExcludedRoots() {
+    return myExcludes;
+  }
+
   @NotNull
   public String getPackagePrefix() {
     return myPackagePrefix;
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourceRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourceRootDescriptor.java
new file mode 100644 (file)
index 0000000..cc7b628
--- /dev/null
@@ -0,0 +1,86 @@
+package org.jetbrains.jps.builders.java;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+import org.jetbrains.jps.incremental.ResourcesTarget;
+import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.JpsCompilerExcludes;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.Set;
+
+/**
+* @author Eugene Zhuravlev
+*         Date: 1/3/12
+*/
+public final class ResourceRootDescriptor extends BuildRootDescriptor {
+
+  @NotNull private final File myRoot;
+  @NotNull private final ResourcesTarget myTarget;
+  private final boolean myGenerated;
+  @NotNull private final String myPackagePrefix;
+  @NotNull private final Set<File> myExcludes;
+
+  public ResourceRootDescriptor(@NotNull File root, @NotNull ResourcesTarget target, boolean isGenerated, @NotNull String packagePrefix, @NotNull Set<File> excludes) {
+    myRoot = root;
+    myTarget = target;
+    myGenerated = isGenerated;
+    myPackagePrefix = packagePrefix;
+    myExcludes = excludes;
+  }
+
+  @Override
+  public String getRootId() {
+    return FileUtil.toSystemIndependentName(myRoot.getPath());
+  }
+
+  @Override
+  public File getRootFile() {
+    return myRoot;
+  }
+
+  @NotNull
+  @Override
+  public Set<File> getExcludedRoots() {
+    return myExcludes;
+  }
+
+  @Override
+  public ResourcesTarget getTarget() {
+    return myTarget;
+  }
+
+  @NotNull
+  public String getPackagePrefix() {
+    return myPackagePrefix;
+  }
+
+  @Override
+  public FileFilter createFileFilter() {
+    final JpsProject project = myTarget.getModule().getProject();
+    final JpsCompilerExcludes excludes = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project).getCompilerExcludes();
+    return new FileFilter() {
+      @Override
+      public boolean accept(File file) {
+        return !excludes.isExcluded(file);
+      }
+    };
+  }
+
+  @Override
+  public boolean isGenerated() {
+    return myGenerated;
+  }
+
+  @Override
+  public String toString() {
+    return "ResourceRootDescriptor{" +
+           "target='" + myTarget + '\'' +
+           ", root=" + myRoot +
+           ", generated=" + myGenerated +
+           '}';
+  }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourcesOnlyRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourcesOnlyRootDescriptor.java
deleted file mode 100644 (file)
index 23f427b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.jetbrains.jps.builders.java;
-
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.jps.incremental.ModuleBuildTarget;
-
-import java.io.File;
-
-/**
-* @author Eugene Zhuravlev
-*         Date: 1/3/12
-*/
-public final class ResourcesOnlyRootDescriptor extends JavaSourceRootDescriptor {
-
-  public ResourcesOnlyRootDescriptor(@NotNull File root,
-                                     @NotNull ModuleBuildTarget target,
-                                     boolean isGenerated,
-                                     boolean isTemp,
-                                     @NotNull String packagePrefix) {
-    super(root, target, isGenerated, isTemp, packagePrefix);
-  }
-
-  @Override
-  public String toString() {
-    return "ResourceRootDescriptor{" +
-           "target='" + target + '\'' +
-           ", root=" + root +
-           ", generated=" + isGeneratedSources +
-           '}';
-  }
-}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourcesTargetType.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourcesTargetType.java
new file mode 100644 (file)
index 0000000..69947c1
--- /dev/null
@@ -0,0 +1,70 @@
+package org.jetbrains.jps.builders.java;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildTargetLoader;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.incremental.ResourcesTarget;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class ResourcesTargetType extends BuildTargetType<ResourcesTarget> {
+  public static final ResourcesTargetType PRODUCTION = new ResourcesTargetType("resources-production", false);
+  public static final ResourcesTargetType TEST = new ResourcesTargetType("resources-test", true);
+  public static final List<ResourcesTargetType> ALL_TYPES = Arrays.asList(PRODUCTION, TEST);
+
+  private boolean myTests;
+
+  private ResourcesTargetType(String typeId, boolean tests) {
+    super(typeId);
+    myTests = tests;
+  }
+
+  @NotNull
+  @Override
+  public List<ResourcesTarget> computeAllTargets(@NotNull JpsModel model) {
+    List<JpsModule> modules = model.getProject().getModules();
+    List<ResourcesTarget> targets = new ArrayList<ResourcesTarget>(modules.size());
+    for (JpsModule module : modules) {
+      targets.add(new ResourcesTarget(module, this));
+    }
+    return targets;
+  }
+
+  @NotNull
+  @Override
+  public Loader createLoader(@NotNull JpsModel model) {
+    return new Loader(model);
+  }
+
+  public boolean isTests() {
+    return myTests;
+  }
+
+  public static ResourcesTargetType getInstance(boolean tests) {
+    return tests ? TEST : PRODUCTION;
+  }
+
+  private class Loader extends BuildTargetLoader<ResourcesTarget> {
+    private final Map<String, JpsModule> myModules;
+
+    public Loader(JpsModel model) {
+      myModules = new HashMap<String, JpsModule>();
+      for (JpsModule module : model.getProject().getModules()) {
+        myModules.put(module.getName(), module);
+      }
+    }
+
+    @Nullable
+    @Override
+    public ResourcesTarget createTarget(@NotNull String targetId) {
+      JpsModule module = myModules.get(targetId);
+      return module != null ? new ResourcesTarget(module, ResourcesTargetType.this) : null;
+    }
+  }
+}
index ac99f5501928a70ee2607f23a3a4e2cd5433c093..58152ad476745ee8b1c9900b07f997ec28602a04 100644 (file)
@@ -4,6 +4,7 @@ import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
+import com.intellij.openapi.util.io.FileSystemUtil;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.util.concurrency.SequentialTaskExecutor;
 import com.intellij.util.io.DataOutputStream;
@@ -287,7 +288,10 @@ final class BuildSession implements Runnable, CanceledStatus {
         }
         for (BuildRootDescriptor descriptor : descriptors) {
           if (!descriptor.isGenerated()) { // ignore generates sources as they are processed at the time of generation
-            pd.fsState.markDirty(null, file, descriptor, timestamps, saveEventStamp);
+            long stamp = timestamps.getStamp(file, descriptor.getTarget());
+            if (stamp != FileSystemUtil.lastModified(file)) {
+              pd.fsState.markDirty(null, file, descriptor, timestamps, saveEventStamp);
+            }
           }
         }
       }
index a5baaec5845361c1f24b00089bc002f3d4fa82fb..e31c42b13faf96cb54a88f2fe79b617884009472 100644 (file)
@@ -133,6 +133,8 @@ public class ClasspathBootstrap {
     for (String path : PathManager.getUtilClassPath()) {
       cp.add(new File(path));
     }
+    cp.add(getResourcePath(JpsModel.class));  // jps-model-api
+    cp.add(getResourcePath(JpsModelImpl.class));  // jps-model-impl
     cp.add(getResourcePath(Message.class)); // protobuf
     cp.add(getResourcePath(Version.class)); // netty
 
index 23796ae6600b87f95e44dc97dc2189ae593aae8a..a1bf6a05d904a6c9856df95f33860df36cf1b10e 100644 (file)
@@ -7,19 +7,20 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.jps.builders.*;
 import org.jetbrains.jps.builders.impl.BuildTargetChunk;
 import org.jetbrains.jps.builders.impl.DirtyFilesHolderBase;
+import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
 import org.jetbrains.jps.builders.storage.SourceToOutputMapping;
 import org.jetbrains.jps.cmdline.ProjectDescriptor;
 import org.jetbrains.jps.incremental.fs.BuildFSState;
 import org.jetbrains.jps.incremental.messages.DoneSomethingNotification;
+import org.jetbrains.jps.incremental.messages.FileDeletedEvent;
 import org.jetbrains.jps.incremental.messages.FileGeneratedEvent;
+import org.jetbrains.jps.incremental.storage.BuildDataManager;
 import org.jetbrains.jps.incremental.storage.BuildTargetConfiguration;
 import org.jetbrains.jps.incremental.storage.Timestamps;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
+import java.util.*;
 
 /**
  * @author Eugene Zhuravlev
@@ -142,6 +143,70 @@ public class BuildOperations {
     return dropped;
   }
 
+  public static <R extends BuildRootDescriptor, T extends BuildTarget<R>>
+  Map<T, Set<File>> cleanOutputsCorrespondingToChangedFiles(final CompileContext context, DirtyFilesHolder<R, T> dirtyFilesHolder) throws ProjectBuildException {
+    final BuildDataManager dataManager = context.getProjectDescriptor().dataManager;
+    try {
+      final Map<T, Set<File>> cleanedSources = new java.util.HashMap<T, Set<File>>();
+
+      ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger();
+      final Collection<String> outputsToLog = logger.isEnabled() ? new LinkedList<String>() : null;
+      final THashSet<File> dirsToDelete = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+
+      dirtyFilesHolder.processDirtyFiles(new FileProcessor<R, T>() {
+        private final Map<T, SourceToOutputMapping> mappingsCache = new java.util.HashMap<T, SourceToOutputMapping>(); // cache the mapping locally
+
+        @Override
+        public boolean apply(T target, File file, R sourceRoot) throws IOException {
+          SourceToOutputMapping srcToOut = mappingsCache.get(target);
+          if (srcToOut == null) {
+            srcToOut = dataManager.getSourceToOutputMap(target);
+            mappingsCache.put(target, srcToOut);
+          }
+          final String srcPath = file.getPath();
+          final Collection<String> outputs = srcToOut.getOutputs(srcPath);
+          if (outputs != null) {
+            final boolean shouldPruneOutputDirs = target instanceof ModuleBasedTarget;
+            for (String output : outputs) {
+              if (outputsToLog != null) {
+                outputsToLog.add(output);
+              }
+              final File outFile = new File(output);
+              final boolean deleted = outFile.delete();
+              if (deleted && shouldPruneOutputDirs) {
+                final File parent = outFile.getParentFile();
+                if (parent != null) {
+                  dirsToDelete.add(parent);
+                }
+              }
+            }
+            if (!outputs.isEmpty()) {
+              context.processMessage(new FileDeletedEvent(outputs));
+            }
+            Set<File> cleaned = cleanedSources.get(target);
+            if (cleaned == null) {
+              cleaned = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+              cleanedSources.put(target, cleaned);
+            }
+            cleaned.add(file);
+          }
+          return true;
+        }
+      });
+
+      if (outputsToLog != null && context.isMake()) {
+        logger.logDeletedFiles(outputsToLog);
+      }
+      // attempting to delete potentially empty directories
+      FSOperations.pruneEmptyDirs(dirsToDelete);
+
+      return cleanedSources;
+    }
+    catch (Exception e) {
+      throw new ProjectBuildException(e);
+    }
+  }
+
   private static class BuildOutputConsumerImpl implements BuildOutputConsumer {
     private final BuildTarget<?> myTarget;
     private final CompileContext myContext;
@@ -161,9 +226,10 @@ public class BuildOperations {
       final File outputFile = new File(outputFilePath);
       for (File outputRoot : myOutputs) {
         if (FileUtil.isAncestor(outputRoot, outputFile, false)) {
-          final String relativePath = FileUtil.getRelativePath(outputRoot, outputFile);
+          String outputRootPath = FileUtil.toSystemIndependentName(outputRoot.getPath());
+          final String relativePath = FileUtil.getRelativePath(outputRootPath, FileUtil.toSystemIndependentName(outputFilePath), '/');
           if (relativePath != null) {
-            myFileGeneratedEvent.add(FileUtil.toSystemIndependentName(outputRoot.getPath()), FileUtil.toSystemIndependentName(relativePath));
+            myFileGeneratedEvent.add(outputRootPath, relativePath);
           }
           break;
         }
index 444b59bfb14a4a54cce3c6955e9fe5678ddaf9ee..37ce14f9456be01295c1ea9590d9b3d28acfc111 100644 (file)
@@ -14,6 +14,4 @@ public enum BuilderCategory {
   RESOURCES_PROCESSOR,
   CLASS_INSTRUMENTER,
   CLASS_POST_PROCESSOR,
-  PACKAGER,
-  VALIDATOR
 }
index 3fe18ccdb65a5ce6a651d718ea6692de90a0822b..3f0e50e79fa266eb44e4f3a15a969586d152fa1f 100644 (file)
@@ -13,15 +13,12 @@ import org.jetbrains.jps.builders.impl.BuildTargetChunk;
 import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
 import org.jetbrains.jps.cmdline.ProjectDescriptor;
 import org.jetbrains.jps.incremental.storage.Timestamps;
-import org.jetbrains.jps.indices.ModuleExcludeIndex;
 import org.jetbrains.jps.model.java.JpsJavaClasspathKind;
 import org.jetbrains.jps.model.java.JpsJavaExtensionService;
 import org.jetbrains.jps.model.module.JpsModule;
-import org.jetbrains.jps.util.JpsPathUtil;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -121,15 +118,6 @@ public class FSOperations {
   }
 
   static void markDirtyFiles(CompileContext context, BuildTarget<?> target, Timestamps timestamps, boolean forceMarkDirty, @Nullable THashSet<File> currentFiles) throws IOException {
-    final Set<File> excludes;
-    if (target instanceof ModuleBuildTarget) {
-      excludes = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
-      final ModuleExcludeIndex index = context.getProjectDescriptor().getModuleExcludeIndex();
-      excludes.addAll(index.getModuleExcludes(((ModuleBuildTarget)target).getModule()));
-    }
-    else {
-      excludes = Collections.emptySet();
-    }
     for (BuildRootDescriptor rd : context.getProjectDescriptor().getBuildRootIndex().getTargetRoots(target, context)) {
       if (!rd.getRootFile().exists() ||
           //temp roots are managed by compilers themselves
@@ -137,14 +125,13 @@ public class FSOperations {
         continue;
       }
       context.getProjectDescriptor().fsState.clearRecompile(rd);
-      traverseRecursively(context, rd, rd.getRootFile(), excludes, timestamps, forceMarkDirty, currentFiles);
+      traverseRecursively(context, rd, rd.getRootFile(), timestamps, forceMarkDirty, currentFiles);
     }
   }
 
   private static void traverseRecursively(CompileContext context,
                                           final BuildRootDescriptor rd,
                                           final File file,
-                                          Set<File> excludes,
                                           @NotNull final Timestamps tsStorage,
                                           final boolean forceDirty,
                                           @Nullable Set<File> currentFiles) throws IOException {
@@ -153,9 +140,9 @@ public class FSOperations {
     }
     final File[] children = file.listFiles();
     if (children != null) { // is directory
-      if (children.length > 0 && !JpsPathUtil.isUnder(excludes, file)) {
+      if (children.length > 0 && !rd.getExcludedRoots().contains(file)) {
         for (File child : children) {
-          traverseRecursively(context, rd, child, excludes, tsStorage, forceDirty, currentFiles);
+          traverseRecursively(context, rd, child, tsStorage, forceDirty, currentFiles);
         }
       }
     }
@@ -175,4 +162,26 @@ public class FSOperations {
       }
     }
   }
+
+  public static void pruneEmptyDirs(@Nullable final THashSet<File> dirsToDelete) {
+    THashSet<File> additionalDirs = null;
+    THashSet<File> toDelete = dirsToDelete;
+    while (toDelete != null) {
+      for (File file : toDelete) {
+        // important: do not force deletion if the directory is not empty!
+        final boolean deleted = file.delete();
+        if (deleted) {
+          final File parentFile = file.getParentFile();
+          if (parentFile != null) {
+            if (additionalDirs == null) {
+              additionalDirs = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+            }
+            additionalDirs.add(parentFile);
+          }
+        }
+      }
+      toDelete = additionalDirs;
+      additionalDirs = null;
+    }
+  }
 }
index 35fb45fe6e130f9bea11d52856165119bea5c1b5..ea8f0621fc0caa863cabc49d1f7c52b760533e4b 100644 (file)
@@ -32,7 +32,6 @@ import org.jetbrains.jps.cmdline.ProjectDescriptor;
 import org.jetbrains.jps.incremental.fs.BuildFSState;
 import org.jetbrains.jps.incremental.java.ExternalJavacDescriptor;
 import org.jetbrains.jps.incremental.messages.*;
-import org.jetbrains.jps.incremental.storage.BuildDataManager;
 import org.jetbrains.jps.incremental.storage.OneToManyPathsMapping;
 import org.jetbrains.jps.model.java.JpsJavaExtensionService;
 import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
@@ -359,7 +358,7 @@ public class IncProjectBuilder {
         context.processMessage(new FileDeletedEvent(outs));
       }
     }
-    pruneEmptyDirs(dirsToDelete);
+    FSOperations.pruneEmptyDirs(dirsToDelete);
   }
 
   private void clearOutputs(CompileContext context) throws ProjectBuildException, IOException {
@@ -757,7 +756,7 @@ public class IncProjectBuilder {
         Utils.REMOVED_SOURCES_KEY.set(context, targetToRemovedSources);
       }
 
-      pruneEmptyDirs(dirsToDelete);
+      FSOperations.pruneEmptyDirs(dirsToDelete);
     }
     catch (IOException e) {
       throw new ProjectBuildException(e);
@@ -787,7 +786,20 @@ public class IncProjectBuilder {
               FSOperations.processFilesToRecompile(context, chunk, processor);
             }
           };
-        deleteOutputsOfDirtyFiles(context, dirtyFilesHolder);
+        if (!context.isProjectRebuild()) {
+          final Map<ModuleBuildTarget, Set<File>> cleanedSources = BuildOperations
+            .cleanOutputsCorrespondingToChangedFiles(context, dirtyFilesHolder);
+          for (Map.Entry<ModuleBuildTarget, Set<File>> entry : cleanedSources.entrySet()) {
+            final ModuleBuildTarget target = entry.getKey();
+            final Set<File> files = entry.getValue();
+            if (!files.isEmpty()) {
+              final SourceToOutputMapping mapping = context.getProjectDescriptor().dataManager.getSourceToOutputMap(target);
+              for (File srcFile : files) {
+                mapping.setOutputs(srcFile.getPath(), Collections.<String>emptyList());
+              }
+            }
+          }
+        }
 
         BUILDER_CATEGORY_LOOP:
         for (BuilderCategory category : BuilderCategory.values()) {
@@ -860,88 +872,6 @@ public class IncProjectBuilder {
     return doneSomething;
   }
 
-  private static <R extends BuildRootDescriptor, T extends BuildTarget<R>>
-  void deleteOutputsOfDirtyFiles(final CompileContext context, DirtyFilesHolder<R, T> dirtyFilesHolder) throws ProjectBuildException {
-    if (context.isProjectRebuild()) {
-      return;
-    }
-
-    final BuildDataManager dataManager = context.getProjectDescriptor().dataManager;
-    try {
-      ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger();
-      final Collection<String> outputsToLog = logger.isEnabled() ? new LinkedList<String>() : null;
-      final THashSet<File> dirsToDelete = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
-
-      dirtyFilesHolder.processDirtyFiles(new FileProcessor<R, T>() {
-        private final Map<T, SourceToOutputMapping> storageMap = new HashMap<T, SourceToOutputMapping>(); // cache the mapping locally
-
-        @Override
-        public boolean apply(T target, File file, R sourceRoot) throws IOException {
-          SourceToOutputMapping srcToOut = storageMap.get(target);
-          if (srcToOut == null) {
-            srcToOut = dataManager.getSourceToOutputMap(target);
-            storageMap.put(target, srcToOut);
-          }
-          final String srcPath = file.getPath();
-          final Collection<String> outputs = srcToOut.getOutputs(srcPath);
-
-          if (outputs != null) {
-            final boolean shouldPruneOutputDirs = target instanceof ModuleBasedTarget;
-            for (String output : outputs) {
-              if (outputsToLog != null) {
-                outputsToLog.add(output);
-              }
-              final File outFile = new File(output);
-              final boolean deleted = outFile.delete();
-              if (deleted && shouldPruneOutputDirs) {
-                final File parent = outFile.getParentFile();
-                if (parent != null) {
-                  dirsToDelete.add(parent);
-                }
-              }
-            }
-            if (!outputs.isEmpty()) {
-              context.processMessage(new FileDeletedEvent(outputs));
-            }
-            srcToOut.setOutputs(srcPath, Collections.<String>emptyList());
-          }
-          return true;
-        }
-      });
-
-      if (outputsToLog != null && context.isMake()) {
-        logger.logDeletedFiles(outputsToLog);
-      }
-      // attempting to delete potentially empty directories
-      pruneEmptyDirs(dirsToDelete);
-    }
-    catch (Exception e) {
-      throw new ProjectBuildException(e);
-    }
-  }
-
-  private static void pruneEmptyDirs(@Nullable final THashSet<File> dirsToDelete) {
-    THashSet<File> additionalDirs = null;
-    THashSet<File> toDelete = dirsToDelete;
-    while (toDelete != null) {
-      for (File file : toDelete) {
-        // important: do not force deletion if the directory is not empty!
-        final boolean deleted = file.delete();
-        if (deleted) {
-          final File parentFile = file.getParentFile();
-          if (parentFile != null) {
-            if (additionalDirs == null) {
-              additionalDirs = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
-            }
-            additionalDirs.add(parentFile);
-          }
-        }
-      }
-      toDelete = additionalDirs;
-      additionalDirs = null;
-    }
-  }
-
   private static List<ChunkGroup> buildChunkGroups(BuildTargetIndex index) {
     final List<BuildTargetChunk> allChunks = index.getSortedTargetChunks();
 
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/JVMModuleBuildTarget.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/JVMModuleBuildTarget.java
new file mode 100644 (file)
index 0000000..03ef86b
--- /dev/null
@@ -0,0 +1,59 @@
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.containers.ContainerUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+import org.jetbrains.jps.builders.BuildRootIndex;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.builders.ModuleBasedTarget;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Eugene Zhuravlev
+ *         Date: 11/12/12
+ */
+public abstract class JVMModuleBuildTarget<R extends BuildRootDescriptor> extends ModuleBasedTarget<R> {
+
+  public JVMModuleBuildTarget(BuildTargetType<? extends JVMModuleBuildTarget<R>> targetType, JpsModule module) {
+    super(targetType, module);
+  }
+
+  @Override
+  public String getId() {
+    return getModule().getName();
+  }
+
+  @NotNull
+  protected Set<File> computeRootExcludes(File root, ModuleExcludeIndex index) {
+    final Collection<File> moduleExcludes = index.getModuleExcludes(getModule());
+    if (moduleExcludes.isEmpty()) {
+      return Collections.emptySet();
+    }
+    final Set<File> excludes = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+    for (File excluded : moduleExcludes) {
+      if (FileUtil.isAncestor(root, excluded, true)) {
+        excludes.add(excluded);
+      }
+    }
+    return excludes;
+  }
+
+
+  @Override
+  public R findRootDescriptor(String rootId, BuildRootIndex rootIndex) {
+    final List<R> descriptors = rootIndex.getRootDescriptors(
+      new File(rootId), Collections.singletonList((BuildTargetType<? extends JVMModuleBuildTarget<R>>)getTargetType()), null
+    );
+    return ContainerUtil.getFirstItem(descriptors);
+  }
+
+}
index 9232b27e51eead1807349dfa41888af21f84e09f..d0bf2f81bb98980384a9e83f4d90055f073cb400 100644 (file)
@@ -1,11 +1,14 @@
 package org.jetbrains.jps.incremental;
 
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildTargetType;
 import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
+import org.jetbrains.jps.builders.java.ResourcesTargetType;
 import org.jetbrains.jps.incremental.java.JavaBuilder;
 import org.jetbrains.jps.incremental.resources.ResourcesBuilder;
 import org.jetbrains.jps.service.SharedThreadPool;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -14,13 +17,22 @@ import java.util.List;
  */
 public class JavaBuilderService extends BuilderService {
   @Override
-  public List<JavaModuleBuildTargetType> getTargetTypes() {
-    return JavaModuleBuildTargetType.ALL_TYPES;
+  public List<? extends BuildTargetType<?>> getTargetTypes() {
+    final ArrayList<BuildTargetType<?>> types = new ArrayList<BuildTargetType<?>>();
+    types.addAll(JavaModuleBuildTargetType.ALL_TYPES);
+    types.addAll(ResourcesTargetType.ALL_TYPES);
+    return types;
   }
 
   @NotNull
   @Override
   public List<? extends ModuleLevelBuilder> createModuleLevelBuilders() {
-    return Arrays.asList(new JavaBuilder(SharedThreadPool.getInstance()), new ResourcesBuilder());
+    return Arrays.asList(new JavaBuilder(SharedThreadPool.getInstance()));
+  }
+
+  @NotNull
+  @Override
+  public List<? extends TargetBuilder<?, ?>> createBuilders() {
+    return Arrays.asList(new ResourcesBuilder());
   }
 }
index b30e37e146b4ff00a459560b4dab2251ebd9c7f9..0981f747e15c8f6034e3c1ed79f0eedf70682cf2 100644 (file)
@@ -1,14 +1,14 @@
 package org.jetbrains.jps.incremental;
 
+import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.util.Consumer;
 import com.intellij.util.SmartList;
-import com.intellij.util.containers.ContainerUtil;
+import gnu.trove.THashSet;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.jps.builders.BuildRootIndex;
 import org.jetbrains.jps.builders.BuildTarget;
 import org.jetbrains.jps.builders.BuildTargetRegistry;
-import org.jetbrains.jps.builders.ModuleBasedTarget;
 import org.jetbrains.jps.builders.java.ExcludedJavaSourceRootProvider;
 import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
 import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
@@ -23,25 +23,24 @@ import org.jetbrains.jps.model.java.compiler.ProcessorConfigProfile;
 import org.jetbrains.jps.model.module.JpsModule;
 import org.jetbrains.jps.model.module.JpsTypedModuleSourceRoot;
 import org.jetbrains.jps.service.JpsServiceManager;
+import org.jetbrains.jps.util.JpsPathUtil;
 
 import java.io.File;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 /**
  * @author nik
  */
-public class ModuleBuildTarget extends ModuleBasedTarget<JavaSourceRootDescriptor> {
-  private final String myModuleName;
+public final class ModuleBuildTarget extends JVMModuleBuildTarget<JavaSourceRootDescriptor> {
   private final JavaModuleBuildTargetType myTargetType;
 
   public ModuleBuildTarget(@NotNull JpsModule module, JavaModuleBuildTargetType targetType) {
     super(targetType, module);
     myTargetType = targetType;
-    myModuleName = module.getName();
   }
 
   @Nullable
@@ -67,20 +66,11 @@ public class ModuleBuildTarget extends ModuleBasedTarget<JavaSourceRootDescripto
     return result;
   }
 
-  public String getModuleName() {
-    return myModuleName;
-  }
-
   @Override
   public boolean isTests() {
     return myTargetType.isTests();
   }
 
-  @Override
-  public String getId() {
-    return myModuleName;
-  }
-
   @Override
   public Collection<BuildTarget<?>> computeDependencies(BuildTargetRegistry targetRegistry) {
     JpsJavaDependenciesEnumerator enumerator = JpsJavaExtensionService.dependencies(myModule).compileOnly();
@@ -106,30 +96,26 @@ public class ModuleBuildTarget extends ModuleBasedTarget<JavaSourceRootDescripto
     List<JavaSourceRootDescriptor> roots = new ArrayList<JavaSourceRootDescriptor>();
     JavaSourceRootType type = isTests() ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE;
     Iterable<ExcludedJavaSourceRootProvider> excludedRootProviders = JpsServiceManager.getInstance().getExtensions(ExcludedJavaSourceRootProvider.class);
+    final Set<File> moduleExcludes = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+    moduleExcludes.addAll(index.getModuleExcludes(myModule));
 
     roots_loop:
     for (JpsTypedModuleSourceRoot<JpsSimpleElement<JavaSourceRootProperties>> sourceRoot : myModule.getSourceRoots(type)) {
       for (ExcludedJavaSourceRootProvider provider : excludedRootProviders) {
-        if (provider.isExcludedFromCompilation(myModule, sourceRoot)) {
+        if (provider.isExcludedFromCompilation(myModule, sourceRoot) || JpsPathUtil.isUnder(moduleExcludes, sourceRoot.getFile())) {
           continue roots_loop;
         }
       }
-      String packagePrefix = sourceRoot.getProperties().getData().getPackagePrefix();
-      roots.add(new JavaSourceRootDescriptor(sourceRoot.getFile(), this, false, false, packagePrefix));
+      final String packagePrefix = sourceRoot.getProperties().getData().getPackagePrefix();
+      roots.add(new JavaSourceRootDescriptor(sourceRoot.getFile(), this, false, false, packagePrefix, computeRootExcludes(sourceRoot.getFile(), index)));
     }
     return roots;
   }
 
-  @Override
-  public JavaSourceRootDescriptor findRootDescriptor(String rootId, BuildRootIndex rootIndex) {
-    List<JavaSourceRootDescriptor> descriptors = rootIndex.getRootDescriptors(new File(rootId), Collections.<JavaModuleBuildTargetType>singletonList(myTargetType), null);
-    return ContainerUtil.getFirstItem(descriptors);
-  }
-
   @NotNull
   @Override
   public String getPresentableName() {
-    return "Module '" + myModuleName + "' " + (myTargetType.isTests() ? "tests" : "production");
+    return "Module '" + getModule().getName() + "' " + (myTargetType.isTests() ? "tests" : "production");
   }
 
   @Override
@@ -149,12 +135,6 @@ public class ModuleBuildTarget extends ModuleBasedTarget<JavaSourceRootDescripto
       fingerprint += bytecodeTarget.hashCode();
     }
 
-    // todo: can we tolerate project rebuild because of resource pattern changes?
-    //final List<String> patterns = config.getResourcePatterns();
-    //for (String pattern : patterns) {
-    //  fingerprint += pattern.hashCode();
-    //}
-
     out.write(Integer.toHexString(fingerprint));
   }
 
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java
new file mode 100644 (file)
index 0000000..c438e27
--- /dev/null
@@ -0,0 +1,148 @@
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.SmartList;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.ProjectPaths;
+import org.jetbrains.jps.builders.BuildRootIndex;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.BuildTargetRegistry;
+import org.jetbrains.jps.builders.java.ExcludedJavaSourceRootProvider;
+import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
+import org.jetbrains.jps.builders.java.ResourceRootDescriptor;
+import org.jetbrains.jps.builders.java.ResourcesTargetType;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.indices.IgnoredFileIndex;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.JpsSimpleElement;
+import org.jetbrains.jps.model.java.JavaSourceRootProperties;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
+import org.jetbrains.jps.model.java.compiler.ProcessorConfigProfile;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsTypedModuleSourceRoot;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public final class ResourcesTarget extends JVMModuleBuildTarget<ResourceRootDescriptor> {
+  private final ResourcesTargetType myTargetType;
+
+  public ResourcesTarget(@NotNull JpsModule module, ResourcesTargetType targetType) {
+    super(targetType, module);
+    myTargetType = targetType;
+  }
+
+  @Nullable
+  public File getOutputDir() {
+    return JpsJavaExtensionService.getInstance().getOutputDirectory(myModule, myTargetType.isTests());
+  }
+
+  @NotNull
+  @Override
+  public Collection<File> getOutputRoots(CompileContext context) {
+    Collection<File> result = new SmartList<File>();
+    final File outputDir = getOutputDir();
+    if (outputDir != null) {
+      result.add(outputDir);
+    }
+    return result;
+  }
+
+  @Override
+  public boolean isTests() {
+    return myTargetType.isTests();
+  }
+
+  @Override
+  public Collection<BuildTarget<?>> computeDependencies(BuildTargetRegistry targetRegistry) {
+    return Collections.<BuildTarget<?>>singleton(
+      new ModuleBuildTarget(myModule, isTests()? JavaModuleBuildTargetType.TEST: JavaModuleBuildTargetType.PRODUCTION)
+    );
+  }
+
+  @NotNull
+  @Override
+  public List<ResourceRootDescriptor> computeRootDescriptors(JpsModel model, ModuleExcludeIndex index, IgnoredFileIndex ignoredFileIndex, BuildDataPaths dataPaths) {
+    List<ResourceRootDescriptor> roots = new ArrayList<ResourceRootDescriptor>();
+    JavaSourceRootType type = isTests() ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE;
+    Iterable<ExcludedJavaSourceRootProvider> excludedRootProviders = JpsServiceManager.getInstance().getExtensions(ExcludedJavaSourceRootProvider.class);
+
+    final THashSet<File> addedRoots = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+
+    roots_loop:
+    for (JpsTypedModuleSourceRoot<JpsSimpleElement<JavaSourceRootProperties>> sourceRoot : myModule.getSourceRoots(type)) {
+      for (ExcludedJavaSourceRootProvider provider : excludedRootProviders) {
+        if (provider.isExcludedFromCompilation(myModule, sourceRoot)) {
+          continue roots_loop;
+        }
+      }
+      final String packagePrefix = sourceRoot.getProperties().getData().getPackagePrefix();
+      final File rootFile = sourceRoot.getFile();
+      roots.add(new ResourceRootDescriptor(rootFile, this, false, packagePrefix, computeRootExcludes(rootFile, index)));
+      addedRoots.add(rootFile);
+    }
+
+    final ProcessorConfigProfile profile = findAnnotationProcessingProfile(model);
+    if (profile != null) {
+      final File annotationOut = new ProjectPaths(model.getProject()).getAnnotationProcessorGeneratedSourcesOutputDir(getModule(), isTests(), profile);
+      if (annotationOut != null && !addedRoots.contains(annotationOut) && !FileUtil.filesEqual(annotationOut, getOutputDir())) {
+        roots.add(new ResourceRootDescriptor(annotationOut, this, true, "", computeRootExcludes(annotationOut, index)));
+      }
+    }
+
+    return roots;
+  }
+
+  @Nullable
+  private ProcessorConfigProfile findAnnotationProcessingProfile(JpsModel model) {
+    final Collection<ProcessorConfigProfile> allProfiles =
+      JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(model.getProject()).getAnnotationProcessingConfigurations();
+    ProcessorConfigProfile profile = null;
+    final String moduleName = getModule().getName();
+    for (ProcessorConfigProfile p : allProfiles) {
+      if (p.getModuleNames().contains(moduleName)) {
+        if (p.isEnabled()) {
+          profile = p;
+        }
+        break;
+      }
+    }
+    return profile;
+  }
+
+  @NotNull
+  @Override
+  public String getPresentableName() {
+    return "Resources for '" + getModule().getName() + "' " + (myTargetType.isTests() ? "tests" : "production");
+  }
+
+  @Override
+  public void writeConfiguration(PrintWriter out, BuildDataPaths dataPaths, BuildRootIndex buildRootIndex) {
+    final JpsJavaCompilerConfiguration config = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(getModule().getProject());
+    int fingerprint = 0;
+    final List<String> patterns = config.getResourcePatterns();
+    for (String pattern : patterns) {
+      fingerprint += pattern.hashCode();
+    }
+    final List<ResourceRootDescriptor> roots = buildRootIndex.getTargetRoots(this, null);
+    for (ResourceRootDescriptor root : roots) {
+      fingerprint += FileUtil.fileHashCode(root.getRootFile());
+      fingerprint += root.getPackagePrefix().hashCode();
+    }
+    out.write(Integer.toHexString(fingerprint));
+  }
+
+}
index e5819a1fadff113c5dc0a98cc81671272e2d332b..df8737efdb960b1dccb162c66432c428a86110ca 100644 (file)
@@ -5,7 +5,10 @@ import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.Processor;
 import com.intellij.util.SmartList;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.jps.builders.*;
+import org.jetbrains.jps.builders.BuildRootIndex;
+import org.jetbrains.jps.builders.BuildTarget;
+import org.jetbrains.jps.builders.BuildTargetRegistry;
+import org.jetbrains.jps.builders.ModuleBasedTarget;
 import org.jetbrains.jps.builders.storage.BuildDataPaths;
 import org.jetbrains.jps.incremental.CompileContext;
 import org.jetbrains.jps.incremental.artifacts.builders.LayoutElementBuildersRegistry;
@@ -113,7 +116,7 @@ public class ArtifactBuildTarget extends BuildTarget<ArtifactRootDescriptor> {
   }
 
   @Override
-  public BuildRootDescriptor findRootDescriptor(String rootId,
+  public ArtifactRootDescriptor findRootDescriptor(String rootId,
                                                 BuildRootIndex rootIndex) {
     return rootIndex.getTargetRoots(this, null).get(Integer.valueOf(rootId));
   }
index 7c747b7e755da4d2e06eaa951edaa5229c871340..788bc316dc12abda0f8f2e3be722debc3c804741 100644 (file)
@@ -237,7 +237,8 @@ public class IncArtifactBuilder extends TargetBuilder<ArtifactRootDescriptor, Ar
         BuildFSState fsState = context.getProjectDescriptor().fsState;
         BuildRootIndex rootsIndex = context.getProjectDescriptor().getBuildRootIndex();
         for (Pair<String, String> pair : paths) {
-          File file = new File(pair.getFirst(), pair.getSecond());
+          String relativePath = pair.getSecond();
+          File file = relativePath.equals(".") ? new File(pair.getFirst()) : new File(pair.getFirst(), relativePath);
           Collection<BuildRootDescriptor> descriptors = rootsIndex.findAllParentDescriptors(file, null, context);
           for (BuildRootDescriptor descriptor : descriptors) {
             try {
index 70d32f8696003e51804b50d3fe69187989c6b344..051968292fa25321da723ff19854f3d82a8d4969 100644 (file)
@@ -34,7 +34,6 @@ import org.jetbrains.jps.builders.DirtyFilesHolder;
 import org.jetbrains.jps.builders.FileProcessor;
 import org.jetbrains.jps.builders.java.JavaBuilderUtil;
 import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
-import org.jetbrains.jps.builders.java.ResourcesOnlyRootDescriptor;
 import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
 import org.jetbrains.jps.builders.java.dependencyView.Mappings;
 import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
@@ -202,9 +201,6 @@ public class JavaBuilder extends ModuleLevelBuilder {
 
       dirtyFilesHolder.processDirtyFiles(new FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget>() {
         public boolean apply(ModuleBuildTarget target, File file, JavaSourceRootDescriptor descriptor) throws IOException {
-          if (descriptor instanceof ResourcesOnlyRootDescriptor) {
-            return true;
-          }
           if (JAVA_SOURCES_FILTER.accept(file)) {
             filesToCompile.add(file);
           }
index 3fe04627663897ea1f66538e2b4cab98c5cb770a..afb3f4a49aeb6d2f93995f0fec32b78d0b5538f2 100644 (file)
@@ -44,7 +44,7 @@ public class CompilerMessage extends BuildMessage {
     myProblemBeginOffset = problemBeginOffset;
     myProblemEndOffset = problemEndOffset;
     myProblemLocationOffset = problemLocationOffset;
-    mySourcePath = sourcePath != null? sourcePath.replace(File.separatorChar, '/') : null;
+    mySourcePath = sourcePath != null && !sourcePath.isEmpty()? sourcePath.replace(File.separatorChar, '/') : null;
     myLine = locationLine;
     myColumn = locationColumn;
   }
index 519c888942906be92ec6160599be179ca5539087..8dbe88567f49d7c3b1b9e881605b40c7e59390ea 100644 (file)
@@ -1,39 +1,36 @@
 package org.jetbrains.jps.incremental.resources;
 
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.io.FileUtil;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.jps.ModuleChunk;
-import org.jetbrains.jps.builders.ChunkBuildOutputConsumer;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildOutputConsumer;
 import org.jetbrains.jps.builders.DirtyFilesHolder;
 import org.jetbrains.jps.builders.FileProcessor;
-import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
+import org.jetbrains.jps.builders.java.ResourceRootDescriptor;
+import org.jetbrains.jps.builders.java.ResourcesTargetType;
+import org.jetbrains.jps.builders.storage.SourceToOutputMapping;
 import org.jetbrains.jps.incremental.*;
 import org.jetbrains.jps.incremental.messages.BuildMessage;
 import org.jetbrains.jps.incremental.messages.CompilerMessage;
 import org.jetbrains.jps.incremental.messages.ProgressMessage;
-import org.jetbrains.jps.model.java.JpsJavaExtensionService;
 import org.jetbrains.jps.model.module.JpsModule;
-import org.jetbrains.jps.util.JpsPathUtil;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
 
 /**
  * @author Eugene Zhuravlev
  *         Date: 10/6/11
  */
-public class ResourcesBuilder extends ModuleLevelBuilder {
+public class ResourcesBuilder extends TargetBuilder<ResourceRootDescriptor, ResourcesTarget> {
   private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.resourses.ResourcesBuilder");
   public static final String BUILDER_NAME = "Resource Compiler";
   private static final List<StandardResourceBuilderEnabler> ourEnablers = new ArrayList<StandardResourceBuilderEnabler>();
 
   public ResourcesBuilder() {
-    super(BuilderCategory.RESOURCES_PROCESSOR);
+    super(ResourcesTargetType.ALL_TYPES);
   }
 
   public static void registerEnabler(StandardResourceBuilderEnabler enabler) {
@@ -49,43 +46,71 @@ public class ResourcesBuilder extends ModuleLevelBuilder {
     }
   }
 
-  public ExitCode build(final CompileContext context,
-                        final ModuleChunk chunk,
-                        DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
-                        final ChunkBuildOutputConsumer outputConsumer) throws ProjectBuildException {
+  @Override
+  public void build(@NotNull ResourcesTarget target,
+                    @NotNull DirtyFilesHolder<ResourceRootDescriptor, ResourcesTarget> holder,
+                    @NotNull final BuildOutputConsumer outputConsumer,
+                    @NotNull final CompileContext context) throws ProjectBuildException, IOException {
+
+    if (!isResourceProcessingEnabled(target.getModule())) {
+      return;
+    }
+
+    @Nullable
+    final Map<ResourcesTarget, Set<File>> cleanedSources;
+    if (context.isProjectRebuild()) {
+      cleanedSources = null;
+    }
+    else {
+      cleanedSources = BuildOperations.cleanOutputsCorrespondingToChangedFiles(context, holder);
+    }
+
     final ResourcePatterns patterns = ResourcePatterns.KEY.get(context);
     assert patterns != null;
-    try {
-      final Ref<Boolean> doneSomething = new Ref<Boolean>(false);
 
-      final FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget> processor = new FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget>() {
-        public boolean apply(ModuleBuildTarget target, final File file, final JavaSourceRootDescriptor sourceRoot) throws IOException {
-          if (patterns.isResourceFile(file, sourceRoot.root)) {
+    try {
+      holder.processDirtyFiles(new FileProcessor<ResourceRootDescriptor, ResourcesTarget>() {
+        public boolean apply(ResourcesTarget target, final File file, final ResourceRootDescriptor sourceRoot) throws IOException {
+          if (patterns.isResourceFile(file, sourceRoot.getRootFile())) {
             try {
               context.processMessage(new ProgressMessage("Copying " + file.getPath()));
-              doneSomething.set(true);
               copyResource(context, sourceRoot, file, outputConsumer);
             }
             catch (IOException e) {
               LOG.info(e);
               context.processMessage(
-                new CompilerMessage("Resource Compiler", BuildMessage.Kind.ERROR, e.getMessage(),
-                                    FileUtil.toSystemIndependentName(file.getPath()))
+                new CompilerMessage(
+                  "Resource Compiler", BuildMessage.Kind.ERROR, e.getMessage(), FileUtil.toSystemIndependentName(file.getPath())
+                )
               );
               return false;
             }
+            finally {
+              if (cleanedSources != null) {
+                final Set<File> files = cleanedSources.get(target);
+                if (files != null) {
+                  files.remove(file);
+                }
+              }
+            }
           }
           return true;
         }
-      };
-
-      for (ModuleBuildTarget target : chunk.getTargets()) {
-        if (isResourceProcessingEnabled(target.getModule())) {
-          FSOperations.processFilesToRecompile(context, target, processor);
+      });
+
+      if (cleanedSources != null) {
+        // cleanup mapping for the files that were copied before but not copied now
+        for (Map.Entry<ResourcesTarget, Set<File>> entry : cleanedSources.entrySet()) {
+          final Set<File> files = entry.getValue();
+          if (!files.isEmpty()) {
+            final SourceToOutputMapping mapping = context.getProjectDescriptor().dataManager.getSourceToOutputMap(entry.getKey());
+            for (File file : files) {
+              mapping.remove(file.getPath());
+            }
+          }
         }
       }
 
-      return doneSomething.get()? ExitCode.OK : ExitCode.NOTHING_DONE;
     }
     catch (Exception e) {
       throw new ProjectBuildException(e.getMessage(), e);
@@ -101,18 +126,17 @@ public class ResourcesBuilder extends ModuleLevelBuilder {
     return true;
   }
 
-  private static void copyResource(CompileContext context, JavaSourceRootDescriptor rd, File file, ChunkBuildOutputConsumer outputConsumer) throws IOException {
-    final ModuleBuildTarget target = rd.getTarget();
-    final String outputRootUrl = JpsJavaExtensionService.getInstance().getOutputUrl(target.getModule(), target.isTests());
-    if (outputRootUrl == null) {
+  private static void copyResource(CompileContext context, ResourceRootDescriptor rd, File file, BuildOutputConsumer outputConsumer) throws IOException {
+    final File outputRoot = rd.getTarget().getOutputDir();
+    if (outputRoot == null) {
       return;
     }
-    String rootPath = FileUtil.toSystemIndependentName(rd.root.getAbsolutePath());
-    final String relativePath = FileUtil.getRelativePath(rootPath, FileUtil.toSystemIndependentName(file.getPath()), '/');
+    final String sourceRootPath = FileUtil.toSystemIndependentName(rd.getRootFile().getAbsolutePath());
+    final String relativePath = FileUtil.getRelativePath(sourceRootPath, FileUtil.toSystemIndependentName(file.getPath()), '/');
     final String prefix = rd.getPackagePrefix();
 
     final StringBuilder targetPath = new StringBuilder();
-    targetPath.append(JpsPathUtil.urlToPath(outputRootUrl));
+    targetPath.append(FileUtil.toSystemIndependentName(outputRoot.getPath()));
     if (prefix.length() > 0) {
       targetPath.append('/').append(prefix.replace('.', '/'));
     }
@@ -121,7 +145,7 @@ public class ResourcesBuilder extends ModuleLevelBuilder {
     final String outputPath = targetPath.toString();
     FileUtil.copyContent(file, new File(outputPath));
     try {
-      outputConsumer.registerOutputFile(target, outputPath, Collections.singletonList(file.getPath()));
+      outputConsumer.registerOutputFile(outputPath, Collections.singletonList(file.getPath()));
     }
     catch (Exception e) {
       context.processMessage(new CompilerMessage(BUILDER_NAME, e));
index 6555c181b2b4dc5a75fa7a33b80000ea8843a1fc..0a54d792cb08c779478003d1ba440c1114fc997d 100644 (file)
@@ -41,8 +41,7 @@ public class JavacMain {
         break;
       }
       if (compiler == null) {
-        final String message = "Eclipse Batch Compiler was not found in classpath";
-        outConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, message));
+        outConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, "Eclipse Batch Compiler was not found in classpath"));
         return false;
       }
     }
@@ -50,6 +49,10 @@ public class JavacMain {
     final boolean nowUsingJavac;
     if (compiler == null) {
       compiler = ToolProvider.getSystemJavaCompiler();
+      if (compiler == null) {
+        outConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, "System Java Compiler was not found in classpath"));
+        return false;
+      }
       nowUsingJavac = true;
     }
     else {
index 00e3a08cc175ba633111d3e3cf05e505f3532e1d..75f6aee0effce814bfdd4145b796463f439a184c 100644 (file)
@@ -37,10 +37,12 @@ public class JavacServerResponseHandler implements ProtobufResponseHandler{
         final JavacRemoteProto.Message.Response.CompileMessage.Kind messageKind = compileMessage.getKind();
 
         if (messageKind == JavacRemoteProto.Message.Response.CompileMessage.Kind.STD_OUT) {
-          myDiagnosticSink.outputLineAvailable(compileMessage.getText());
+          if (compileMessage.hasText()) {
+            myDiagnosticSink.outputLineAvailable(compileMessage.getText());
+          }
         }
         else {
-          final String sourceUri = compileMessage.getSourceUri();
+          final String sourceUri = compileMessage.hasSourceUri()? compileMessage.getSourceUri() : null;
           final JavaFileObject srcFileObject = sourceUri != null? new DummyJavaFileObject(URI.create(sourceUri)) : null;
           myDiagnosticSink.report(new DummyDiagnostic(convertKind(messageKind), srcFileObject, compileMessage));
         }
@@ -52,11 +54,11 @@ public class JavacServerResponseHandler implements ProtobufResponseHandler{
         final JavacRemoteProto.Message.Response.OutputObject outputObject = response.getOutputObject();
         final JavacRemoteProto.Message.Response.OutputObject.Kind kind = outputObject.getKind();
 
-        final String outputRoot = outputObject.getOutputRoot();
+        final String outputRoot = outputObject.hasOutputRoot()? outputObject.getOutputRoot() : null;
         final File outputRootFile = outputRoot != null? new File(outputRoot) : null;
 
         final OutputFileObject.Content fileObjectContent;
-        final ByteString content = outputObject.getContent();
+        final ByteString content = outputObject.hasContent()? outputObject.getContent() : null;
         if (content != null) {
           final byte[] bytes = content.toByteArray();
           fileObjectContent = new OutputFileObject.Content(bytes, 0, bytes.length);
@@ -65,15 +67,15 @@ public class JavacServerResponseHandler implements ProtobufResponseHandler{
           fileObjectContent = null;
         }
 
-        final String sourceUri = outputObject.getSourceUri();
+        final String sourceUri = outputObject.hasSourceUri()? outputObject.getSourceUri() : null;
         final URI srcUri = sourceUri != null? URI.create(sourceUri) : null;
         final OutputFileObject fileObject = new OutputFileObject(
           null,
           outputRootFile,
-          outputObject.getRelativePath(),
+          outputObject.hasRelativePath()? outputObject.getRelativePath() : null,
           new File(outputObject.getFilePath()),
           convertKind(kind),
-          outputObject.getClassName(),
+          outputObject.hasClassName()? outputObject.getClassName() : null,
           srcUri,
           fileObjectContent
         );
@@ -92,7 +94,9 @@ public class JavacServerResponseHandler implements ProtobufResponseHandler{
       }
 
       if (responseType == JavacRemoteProto.Message.Response.Type.BUILD_COMPLETED) {
-        myTerminatedSuccessfully = response.getCompletionStatus();
+        if (response.hasCompletionStatus()) {
+          myTerminatedSuccessfully = response.getCompletionStatus();
+        }
         return true;
       }
 
@@ -105,7 +109,17 @@ public class JavacServerResponseHandler implements ProtobufResponseHandler{
 
     if (messageType == JavacRemoteProto.Message.Type.FAILURE) {
       final JavacRemoteProto.Message.Failure failure = msg.getFailure();
-      myDiagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, failure.getStacktrace()));
+      final StringBuilder buf = new StringBuilder();
+      if (failure.hasDescription()) {
+        buf.append(failure.getDescription());
+      }
+      if (failure.hasStacktrace()) {
+        if (buf.length() > 0) {
+          buf.append("\n");
+        }
+        buf.append(failure.getStacktrace());
+      }
+      myDiagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, buf.toString()));
       return true;
     }
 
@@ -159,23 +173,23 @@ public class JavacServerResponseHandler implements ProtobufResponseHandler{
     }
 
     public long getPosition() {
-      return myCompileMessage.getProblemLocationOffset();
+      return myCompileMessage.hasProblemLocationOffset()? myCompileMessage.getProblemLocationOffset() : -1;
     }
 
     public long getStartPosition() {
-      return myCompileMessage.getProblemBeginOffset();
+      return myCompileMessage.hasProblemBeginOffset()? myCompileMessage.getProblemBeginOffset() : -1;
     }
 
     public long getEndPosition() {
-      return myCompileMessage.getProblemEndOffset();
+      return myCompileMessage.hasProblemEndOffset()? myCompileMessage.getProblemEndOffset() : -1;
     }
 
     public long getLineNumber() {
-      return myCompileMessage.getLine();
+      return myCompileMessage.hasLine()? myCompileMessage.getLine() : -1;
     }
 
     public long getColumnNumber() {
-      return myCompileMessage.getColumn();
+      return myCompileMessage.hasColumn()? myCompileMessage.getColumn() : -1;
     }
 
     public String getCode() {
@@ -183,7 +197,7 @@ public class JavacServerResponseHandler implements ProtobufResponseHandler{
     }
 
     public String getMessage(Locale locale) {
-      return myCompileMessage.getText();
+      return myCompileMessage.hasText()? myCompileMessage.getText() : null;
     }
   }
 }
index b8dd17b388311bcc03184e276fc7456587405856..0b3e52705513c25c251987e9c1b061276ecbf86e 100644 (file)
@@ -61,14 +61,19 @@ void set_inotify_callback(void (* callback)(char*, int));
 int get_inotify_fd();
 int get_watch_count();
 bool watch_limit_reached();
-int watch(const char* root);
+int watch(const char* root, array* mounts);
 void unwatch(int id);
 bool process_inotify_input();
 void close_inotify();
 
 
 // reads one line from stream, trims trailing carriage return if any
-// returns pointer to the internal buffer (will be overwriten on next call)
+// returns pointer to the internal buffer (will be overwritten on next call)
 char* read_line(FILE* stream);
 
+
+// path comparison
+bool is_parent_path(const char* parent_path, const char* child_path);
+
+
 #endif
index 443c67a13d97be6807e1cb1d067c5ab7244a7966..bfb117d513478a74e5e08d0980978b07b7cf2207 100644 (file)
@@ -216,7 +216,15 @@ static void rm_watch(int wd, bool update_parent) {
 }
 
 
-static int walk_tree(const char* path, watch_node* parent, bool recursive) {
+static int walk_tree(const char* path, watch_node* parent, bool recursive, array* mounts) {
+  for (int j=0; j<array_size(mounts); j++) {
+    char* mount = array_get(mounts, j);
+    if (strncmp(path, mount, strlen(mount)) == 0) {
+      userlog(LOG_DEBUG, "watch path '%s' crossed mount point '%s' - skipping", path, mount);
+      return ERR_IGNORE;
+    }
+  }
+
   DIR* dir = NULL;
   if (recursive) {
     if ((dir = opendir(path)) == NULL) {
@@ -257,7 +265,7 @@ static int walk_tree(const char* path, watch_node* parent, bool recursive) {
 
     strcpy(p, entry->d_name);
 
-    int subdir_id = walk_tree(subdir, table_get(watches, id), recursive);
+    int subdir_id = walk_tree(subdir, table_get(watches, id), recursive, mounts);
     if (subdir_id < 0 && subdir_id != ERR_IGNORE) {
       rm_watch(id, true);
       id = subdir_id;
@@ -270,7 +278,7 @@ static int walk_tree(const char* path, watch_node* parent, bool recursive) {
 }
 
 
-int watch(const char* root) {
+int watch(const char* root, array* mounts) {
   bool recursive = true;
   if (root[0] == '|') {
     root++;
@@ -297,7 +305,7 @@ int watch(const char* root) {
     return ERR_IGNORE;
   }
 
-  return walk_tree(root, NULL, recursive);
+  return walk_tree(root, NULL, recursive, mounts);
 }
 
 
@@ -326,7 +334,7 @@ static bool process_inotify_event(struct inotify_event* event) {
   }
 
   if (is_dir && ((event->mask & IN_CREATE) == IN_CREATE || (event->mask & IN_MOVED_TO) == IN_MOVED_TO)) {
-    int result = walk_tree(path, node, true);
+    int result = walk_tree(path, node, true, NULL);
     if (result < 0 && result != ERR_IGNORE) {
       return false;
     }
index 4bd2727c224c495089a3a6de99a2fc72d5228ec9..381c6826de1e20a2d5c24ef3523f121611ff505b 100644 (file)
@@ -320,23 +320,31 @@ static bool register_roots(array* new_roots, array* unwatchable, array* mounts)
       continue;
     }
 
-    char* skip = NULL;
+    array* inner_mounts = array_create(5);
+    CHECK_NULL(inner_mounts, false);
+
+    bool skip = false;
     for (int j=0; j<array_size(mounts); j++) {
       char* mount = array_get(mounts, j);
-      if (strncmp(mount, unflattened, strlen(mount)) == 0) {
-        userlog(LOG_DEBUG, "path %s is under unwatchable %s - ignoring", unflattened, mount);
-        skip = strdup(unflattened);
-        CHECK_NULL(skip, false);
+      if (is_parent_path(mount, unflattened)) {
+        userlog(LOG_DEBUG, "watch root '%s' is under mount point '%s' - skipping", unflattened, mount);
+        CHECK_NULL(array_push(unwatchable, strdup(unflattened)), false);
+        skip = true;
         break;
       }
+      else if (is_parent_path(unflattened, mount)) {
+        userlog(LOG_DEBUG, "watch root '%s' contains mount point '%s' - partial watch", unflattened, mount);
+        char* copy = strdup(mount);
+        CHECK_NULL(array_push(unwatchable, copy), false);
+        CHECK_NULL(array_push(inner_mounts, copy), false);
+      }
     }
-    if (skip != NULL) {
-      CHECK_NULL(array_push(unwatchable, skip), false);
+    if (skip) {
       continue;
     }
 
-    // todo: consider a mount point under a watch root?
-    int id = watch(new_root);
+    int id = watch(new_root, inner_mounts);
+    array_delete(inner_mounts);
 
     if (id >= 0) {
       watch_root* root = malloc(sizeof(watch_root));
index 9d6ffc01ea8757af566daea044b4162afde2cc70..4dc3657ab7773eaf4373302774ca03c7fcaa3899 100755 (executable)
@@ -4,4 +4,7 @@ clang -m32 -O2 -Wall -std=c99 -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -o fsnotifier ma
 if [ $? -eq 0 ] ; then
   echo "compiling 64-bit version"
   clang -m64 -O2 -Wall -std=c99 -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -o fsnotifier64 main.c inotify.c util.c
+  if [ $? -eq 0 ] ; then
+    chmod 755 fsnotifier fsnotifier64
+  fi
 fi
index 6e09a9053d8090f676ee08691a8c1850bfbc8c23..179b3105a4229b80fcf707892ac79e27006b8b53 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2012 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -188,3 +188,10 @@ char* read_line(FILE* stream) {
   }
   return input_buf;
 }
+
+
+bool is_parent_path(const char* parent_path, const char* child_path) {
+  size_t parent_len = strlen(parent_path);
+  return strncmp(parent_path, child_path, parent_len) == 0 &&
+         (parent_len == strlen(child_path) || child_path[parent_len] == '/');
+}
diff --git a/platform/core-api/src/com/intellij/concurrency/AsyncFuture.java b/platform/core-api/src/com/intellij/concurrency/AsyncFuture.java
new file mode 100644 (file)
index 0000000..914e27b
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.concurrency;
+
+import com.intellij.util.Consumer;
+
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+
+/**
+ * Author: dmitrylomov
+ */
+public interface AsyncFuture<V> extends Future<V> {
+  void addConsumer(Executor executor, ResultConsumer<V> consumer);
+}
diff --git a/platform/core-api/src/com/intellij/concurrency/AsyncFutureFactory.java b/platform/core-api/src/com/intellij/concurrency/AsyncFutureFactory.java
new file mode 100644 (file)
index 0000000..6890660
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.concurrency;
+
+import com.intellij.openapi.components.ServiceManager;
+
+/**
+ * Author: dmitrylomov
+ */
+public abstract class AsyncFutureFactory {
+  public static AsyncFutureFactory getInstance() {
+    return ServiceManager.getService(AsyncFutureFactory.class);
+  }
+
+  public static <V> AsyncFuture<V> wrap(V v) {
+    final AsyncFutureResult<V> result = getInstance().createAsyncFutureResult();
+    result.set(v);
+    return result;
+  }
+
+  public static <V> AsyncFuture<V> wrapException(Exception e) {
+    final AsyncFutureResult<V> result = getInstance().createAsyncFutureResult();
+    result.setException(e);
+    return result;
+  }
+
+  public abstract <V> AsyncFutureResult<V> createAsyncFutureResult();
+}
diff --git a/platform/core-api/src/com/intellij/concurrency/AsyncFutureResult.java b/platform/core-api/src/com/intellij/concurrency/AsyncFutureResult.java
new file mode 100644 (file)
index 0000000..e0a6c44
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.concurrency;
+
+/**
+ * Author: dmitrylomov
+ */
+public interface AsyncFutureResult<V> extends AsyncFuture<V> {
+  void set(V value);
+  void setException(Throwable t);
+}
diff --git a/platform/core-api/src/com/intellij/concurrency/AsyncUtil.java b/platform/core-api/src/com/intellij/concurrency/AsyncUtil.java
new file mode 100644 (file)
index 0000000..74cff15
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.concurrency;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+/**
+ * Author: dmitrylomov
+ */
+public class AsyncUtil {
+  public static <V> V get(Future<V> result) {
+    try {
+      return result.get();
+    }
+    catch (InterruptedException e) {
+      throw new Error(e);
+    }
+    catch (ExecutionException e) {
+      if (e.getCause() instanceof RuntimeException)
+        throw (RuntimeException) e.getCause();
+      else
+        throw new Error(e);
+    }
+
+  }
+}
diff --git a/platform/core-api/src/com/intellij/concurrency/DefaultResultConsumer.java b/platform/core-api/src/com/intellij/concurrency/DefaultResultConsumer.java
new file mode 100644 (file)
index 0000000..7230cd4
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.concurrency;
+
+/**
+ * Author: dmitrylomov
+ */
+public class DefaultResultConsumer<V> implements ResultConsumer<V> {
+  private final AsyncFutureResult<V> myResult;
+
+  public DefaultResultConsumer(AsyncFutureResult<V> result) {
+    myResult = result;
+  }
+
+  @Override
+  public void onSuccess(V value) {
+    myResult.set(value);
+  }
+
+  @Override
+  public void onFailure(Throwable t) {
+    myResult.setException(t);
+  }
+}
diff --git a/platform/core-api/src/com/intellij/concurrency/DoOnce.java b/platform/core-api/src/com/intellij/concurrency/DoOnce.java
new file mode 100644 (file)
index 0000000..6fa505e
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.concurrency;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Executes given runnable exactly once.
+ *
+ * Author: dmitrylomov
+ */
+public class DoOnce {
+  private Runnable myRunnable;
+  private final AtomicBoolean myAlreadyRun;
+
+  public DoOnce(Runnable runnable) {
+    myRunnable = runnable;
+    myAlreadyRun = new AtomicBoolean(false);
+  }
+
+  public void execute() {
+    if (myAlreadyRun.compareAndSet(false, true)) {
+      try {
+        myRunnable.run();
+      } finally {
+        myRunnable = null; // do not leak runnable
+      }
+    }
+  }
+}
diff --git a/platform/core-api/src/com/intellij/concurrency/DoWhile.java b/platform/core-api/src/com/intellij/concurrency/DoWhile.java
new file mode 100644 (file)
index 0000000..15560b0
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.concurrency;
+
+/**
+ * Author: dmitrylomov
+ */
+public abstract class DoWhile  {
+  private AsyncFutureResult<Boolean> myResult;
+
+  public DoWhile() {
+  }
+
+  public AsyncFutureResult<Boolean> getResult() {
+    if (myResult == null) {
+      myResult = AsyncFutureFactory.getInstance().createAsyncFutureResult();
+      body().addConsumer(SameThreadExecutor.INSTANCE, new MyConsumer());
+    }
+    return myResult;
+  }
+
+  protected abstract AsyncFuture<Boolean> body();
+  protected abstract boolean condition();
+
+  private class MyConsumer extends DefaultResultConsumer<Boolean> {
+    public MyConsumer() {
+      super(DoWhile.this.myResult);
+    }
+
+    @Override
+    public void onSuccess(Boolean value) {
+      if (!value.booleanValue()) {
+        myResult.set(false);
+      }
+      else {
+        if(!condition()) {
+          myResult.set(true);
+        }
+        else {
+          body().addConsumer(SameThreadExecutor.INSTANCE, this);
+        }
+      }
+    }
+  }
+
+
+}
diff --git a/platform/core-api/src/com/intellij/concurrency/FinallyFuture.java b/platform/core-api/src/com/intellij/concurrency/FinallyFuture.java
new file mode 100644 (file)
index 0000000..4c99d2e
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.concurrency;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Author: dmitrylomov
+ */
+public class FinallyFuture<V> implements AsyncFuture<V> {
+  private final DoOnce myFinallyBlock;
+  private final AsyncFuture<V> myInner;
+
+  public FinallyFuture(AsyncFuture<V> inner, Runnable finallyBlock) {
+    myInner = inner;
+    myFinallyBlock = new DoOnce(finallyBlock);
+  }
+
+  @Override
+  public boolean cancel(boolean mayInterruptIfRunning) {
+    return myInner.cancel(mayInterruptIfRunning);
+  }
+
+  @Override
+  public boolean isCancelled() {
+    return myInner.isDone();
+  }
+
+  @Override
+  public boolean isDone() {
+    return myInner.isDone();
+  }
+
+  @Override
+  public V get() throws InterruptedException, ExecutionException {
+    try {
+      return myInner.get();
+    }
+    finally {
+      myFinallyBlock.execute();
+    }
+  }
+
+  @Override
+  public void addConsumer(Executor executor, final ResultConsumer<V> consumer) {
+    myInner.addConsumer(executor, new ResultConsumer<V>() {
+      @Override
+      public void onSuccess(V value) {
+        try {
+          myFinallyBlock.execute();
+          consumer.onSuccess(value);
+        } catch (Throwable t) {
+          consumer.onFailure(t);
+        }
+      }
+
+      @Override
+      public void onFailure(Throwable t) {
+        try {
+          myFinallyBlock.execute();
+        } catch (Throwable t1) {
+          t = t1;
+        }
+        consumer.onFailure(t);
+      }
+    });
+  }
+
+  @Override
+  public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+    boolean timeoutOccurred = false;
+    try {
+      try {
+        return myInner.get(timeout, unit);
+      }
+      catch (TimeoutException t) {
+        timeoutOccurred = true;
+        throw t;
+      }
+    } finally {
+      if (!timeoutOccurred)
+        myFinallyBlock.execute();
+    }
+
+  }
+}
diff --git a/platform/core-api/src/com/intellij/concurrency/Iterate.java b/platform/core-api/src/com/intellij/concurrency/Iterate.java
new file mode 100644 (file)
index 0000000..a6fe317
--- /dev/null
@@ -0,0 +1,32 @@
+package com.intellij.concurrency;
+
+import java.util.Iterator;
+
+/**
+ * Author: dmitrylomov
+ */
+public abstract class Iterate<T> extends DoWhile {
+  private final Iterator<T> myIterator;
+  private boolean myIsDone;
+
+  public Iterate(Iterable<T> iterable) {
+    myIterator = iterable.iterator();
+    myIsDone = false;
+  }
+
+  @Override
+  protected final AsyncFuture<Boolean> body() {
+    if (!myIterator.hasNext()) {
+      myIsDone = true;
+      return AsyncFutureFactory.wrap(true);
+    }
+    return process(myIterator.next());
+  }
+
+  protected abstract AsyncFuture<Boolean> process(T t);
+
+  @Override
+  protected boolean condition() {
+    return !myIsDone;
+  }
+}
index b58921bd66f9bfebaf0dc8b6c5ea891d5a97e425..bca6c09278a72e6f4ebbee6166c113b7532055a7 100644 (file)
@@ -50,6 +50,13 @@ public abstract class JobLauncher {
                                                      boolean failFastOnAcquireReadAction,
                                                      @NotNull final Processor<T> thingProcessor) throws ProcessCanceledException;
 
+  public abstract <T> AsyncFuture<Boolean> invokeConcurrentlyUnderProgressAsync(
+                                                              @NotNull List<T> things,
+                                                              ProgressIndicator progress,
+                                                              boolean failFastOnAcquireReadAction,
+                                                              @NotNull final Processor<T> thingProcessor);
+
+
   public abstract Job<Void> submitToJobThread(int priority, @NotNull final Runnable action, @Nullable Consumer<Future> onDoneCallback);
 
   public Job<Void> submitToJobThread(int priority, @NotNull final Runnable action) {
diff --git a/platform/core-api/src/com/intellij/concurrency/ResultConsumer.java b/platform/core-api/src/com/intellij/concurrency/ResultConsumer.java
new file mode 100644 (file)
index 0000000..80618f0
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.concurrency;
+
+/**
+ * Author: dmitrylomov
+ */
+public interface ResultConsumer<V> {
+  void onSuccess(V value);
+  void onFailure(Throwable t);
+}
diff --git a/platform/core-api/src/com/intellij/concurrency/SameThreadExecutor.java b/platform/core-api/src/com/intellij/concurrency/SameThreadExecutor.java
new file mode 100644 (file)
index 0000000..06dfd10
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.concurrency;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Author: dmitrylomov
+ */
+public class SameThreadExecutor implements Executor {
+  public static final Executor INSTANCE = new SameThreadExecutor();
+  @Override
+  public void execute(Runnable command) {
+    command.run();
+  }
+}
index bcdefa175b9187fc0a8cf858ff0b178db2d1c565..84f4b9c84e3c8bfb3a0dd31c60d53e45dc64555a 100644 (file)
@@ -112,6 +112,9 @@ public interface Project extends ComponentManager, AreaInstance {
   @NonNls
   String getLocation();
 
+  /**
+   * Should be invoked under WriteAction.
+   */
   void save();
 
   boolean isOpen();
similarity index 71%
rename from platform/util/src/com/intellij/util/AbstractQuery.java
rename to platform/core-api/src/com/intellij/util/AbstractQuery.java
index c93da2840652ce53efeff6f88f8b89dda1e78eca..fc1df3744aadc4fa498fa2f3cf08ca0cb95fcacd 100644 (file)
  */
 package com.intellij.util;
 
+import com.intellij.concurrency.AsyncFuture;
+import com.intellij.concurrency.AsyncFutureFactory;
+import com.intellij.concurrency.AsyncFutureResult;
+import com.intellij.concurrency.FinallyFuture;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -76,5 +80,27 @@ public abstract class AbstractQuery<Result> implements Query<Result> {
     }
   }
 
+  @Override
+  public AsyncFuture<Boolean> forEachAsync(@NotNull Processor<Result> consumer) {
+    assertNotProcessing();
+    myIsProcessing = true;
+    return new FinallyFuture<Boolean>(processResultsAsync(consumer), new Runnable() {
+      @Override
+      public void run() {
+        myIsProcessing = false;
+      }
+    });
+  }
+
   protected abstract boolean processResults(@NotNull Processor<Result> consumer);
+
+  protected AsyncFuture<Boolean> processResultsAsync(@NotNull Processor<Result> consumer) {
+    final AsyncFutureResult<Boolean> result = AsyncFutureFactory.getInstance().createAsyncFutureResult();
+    try {
+      result.set(processResults(consumer));
+    } catch (Throwable t) {
+      result.setException(t);
+    }
+    return result;
+  }
 }
similarity index 74%
rename from platform/util/src/com/intellij/util/ArrayQuery.java
rename to platform/core-api/src/com/intellij/util/ArrayQuery.java
index ef1502b92094b0b50150035d21855abc506fef28..df8dcad7fd12c345a1efa079101d87330690675e 100644 (file)
@@ -16,6 +16,9 @@
 
 package com.intellij.util;
 
+import com.intellij.concurrency.AsyncFuture;
+import com.intellij.concurrency.AsyncFutureFactory;
+import com.intellij.concurrency.AsyncFutureResult;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 
@@ -46,6 +49,17 @@ public class ArrayQuery<T> implements Query<T> {
     return ContainerUtil.process(myArray, consumer);
   }
 
+  public AsyncFuture<Boolean> forEachAsync(@NotNull final Processor<T> consumer) {
+    final AsyncFutureResult<Boolean> result = AsyncFutureFactory.getInstance().createAsyncFutureResult();
+    try {
+      result.set(forEach(consumer));
+    } catch (Throwable t){
+      result.setException(t);
+    }
+    return result;
+  }
+
+
   public T[] toArray(final T[] a) {
     return myArray;
   }
similarity index 76%
rename from platform/util/src/com/intellij/util/CollectionQuery.java
rename to platform/core-api/src/com/intellij/util/CollectionQuery.java
index 09d5758a25b745819d6c992edd995328604509d4..38db8f57070757ac5cf3f073733cc8d1bec7a4a6 100644 (file)
@@ -16,6 +16,9 @@
 
 package com.intellij.util;
 
+import com.intellij.concurrency.AsyncFuture;
+import com.intellij.concurrency.AsyncFutureFactory;
+import com.intellij.concurrency.AsyncFutureResult;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 
@@ -49,6 +52,17 @@ public class CollectionQuery<T> implements Query<T> {
     return ContainerUtil.process(myCollection, consumer);
   }
 
+  @Override
+  public AsyncFuture<Boolean> forEachAsync(@NotNull Processor<T> consumer) {
+    AsyncFutureResult<Boolean>  result = AsyncFutureFactory.getInstance().createAsyncFutureResult();
+    try {
+      result.set(forEach(consumer));
+    } catch (Throwable t) {
+      result.setException(t);
+    }
+    return result;
+  }
+
   @Override
   public T[] toArray(final T[] a) {
     return findAll().toArray(a);
similarity index 85%
rename from platform/util/src/com/intellij/util/EmptyQuery.java
rename to platform/core-api/src/com/intellij/util/EmptyQuery.java
index f28ce27dafbe18bcf4e374eea786f2dc6677e81e..7d48cd9a43d74a97758d6a7ccc47101e327cce72 100644 (file)
@@ -15,6 +15,8 @@
  */
 package com.intellij.util;
 
+import com.intellij.concurrency.AsyncFuture;
+import com.intellij.concurrency.AsyncFutureFactory;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Collection;
@@ -40,6 +42,11 @@ public class EmptyQuery<R> implements Query<R> {
     return true;
   }
 
+  @Override
+  public AsyncFuture<Boolean> forEachAsync(@NotNull Processor<R> consumer) {
+    return AsyncFutureFactory.wrap(true);
+  }
+
   public R[] toArray(final R[] a) {
     return findAll().toArray(a);
   }
similarity index 75%
rename from platform/util/src/com/intellij/util/FilteredQuery.java
rename to platform/core-api/src/com/intellij/util/FilteredQuery.java
index 8bb540caeadf516a01860ef005f2b0d65c66c5ba..108d4a1bc871125182378f430af7a481f5b9a6b0 100644 (file)
@@ -16,6 +16,7 @@
 
 package com.intellij.util;
 
+import com.intellij.concurrency.AsyncFuture;
 import com.intellij.openapi.util.Condition;
 import org.jetbrains.annotations.NotNull;
 
@@ -43,17 +44,15 @@ public class FilteredQuery<T> implements Query<T> {
 
   @Override
   public boolean forEach(@NotNull final Processor<T> consumer) {
-    myOriginal.forEach(new Processor<T>() {
-      @Override
-      public boolean process(final T t) {
-        return !myFilter.value(t) || consumer.process(t);
-      }
-    });
-
+    myOriginal.forEach(new MyProcessor(consumer));
     return true;
   }
 
   @Override
+  public AsyncFuture<Boolean> forEachAsync(@NotNull Processor<T> consumer) {
+    return myOriginal.forEachAsync(new MyProcessor(consumer));
+  }
+
   @NotNull
   public Collection<T> findAll() {
     CommonProcessors.CollectProcessor<T> processor = new CommonProcessors.CollectProcessor<T>();
@@ -70,4 +69,19 @@ public class FilteredQuery<T> implements Query<T> {
   public Iterator<T> iterator() {
     return findAll().iterator();
   }
+
+  private class MyProcessor implements Processor<T> {
+    private final Processor<T> myConsumer;
+
+    public MyProcessor(Processor<T> consumer) {
+      myConsumer = consumer;
+    }
+
+    public boolean process(final T t) {
+      if (!myFilter.value(t)) return true;
+      if (!myConsumer.process(t)) return false;
+
+      return true;
+    }
+  }
 }
similarity index 74%
rename from platform/util/src/com/intellij/util/InstanceofQuery.java
rename to platform/core-api/src/com/intellij/util/InstanceofQuery.java
index 72b9fe5b9c294110a62aac003a035d2580bc4b31..6d1e5042e1ba8882aa374fa85d87f3ae8eeae199 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.intellij.util;
 
+import com.intellij.concurrency.AsyncFuture;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
@@ -51,16 +52,12 @@ public class InstanceofQuery<T> implements Query<T> {
   }
 
   public boolean forEach(@NotNull final Processor<T> consumer) {
-    return myDelegate.forEach(new Processor() {
-      public boolean process(Object o) {
-        for (Class aClass : myClasses) {
-          if (aClass.isInstance(o)) {
-            return consumer.process(((T)o));
-          }
-        }
-        return true;
-      }
-    });
+    return myDelegate.forEach(new MyProcessor(consumer));
+  }
+
+  @Override
+  public AsyncFuture<Boolean> forEachAsync(@NotNull Processor<T> consumer) {
+    return myDelegate.forEachAsync(new MyProcessor(consumer));
   }
 
   public T[] toArray(T[] a) {
@@ -71,4 +68,21 @@ public class InstanceofQuery<T> implements Query<T> {
   public Iterator<T> iterator() {
     return new UnmodifiableIterator<T>(findAll().iterator());
   }
+
+  private class MyProcessor<T> implements Processor<T> {
+    private final Processor<T> myConsumer;
+
+    public MyProcessor(Processor<T> consumer) {
+      myConsumer = consumer;
+    }
+
+    public boolean process(T o) {
+      for (Class aClass : myClasses) {
+        if (aClass.isInstance(o)) {
+          return myConsumer.process(((T)o));
+        }
+      }
+      return true;
+    }
+  }
 }
similarity index 66%
rename from platform/util/src/com/intellij/util/MergeQuery.java
rename to platform/core-api/src/com/intellij/util/MergeQuery.java
index 1f221aa3e10da1e3687e3840c0702afd758ff1b4..242e9ba51ae4dfc8941ab2d6b007c3c6072fab65 100644 (file)
@@ -19,6 +19,7 @@
  */
 package com.intellij.util;
 
+import com.intellij.concurrency.*;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
@@ -52,6 +53,27 @@ public class MergeQuery<T> implements Query<T>{
     return processSubQuery(consumer, myQuery1) && processSubQuery(consumer, myQuery2);
   }
 
+  public AsyncFuture<Boolean> forEachAsync(@NotNull final Processor<T> consumer) {
+    final AsyncFutureResult<Boolean> result = AsyncFutureFactory.getInstance().createAsyncFutureResult();
+
+    final AsyncFuture<Boolean> fq = processSubQueryAsync(consumer, myQuery1);
+
+    fq.addConsumer(SameThreadExecutor.INSTANCE, new DefaultResultConsumer<Boolean>(result) {
+      @Override
+      public void onSuccess(Boolean value) {
+        if (!value.booleanValue()) {
+          result.set(false);
+        }
+        else {
+          final AsyncFuture<Boolean> fq2 = processSubQueryAsync(consumer, myQuery2);
+          fq2.addConsumer(SameThreadExecutor.INSTANCE, new DefaultResultConsumer<Boolean>(result));
+        }
+      }
+    });
+    return result;
+  }
+
+
   private <V extends T> boolean processSubQuery(final Processor<T> consumer, Query<V> query1) {
     return query1.forEach(new Processor<V>() {
       public boolean process(final V t) {
@@ -60,6 +82,14 @@ public class MergeQuery<T> implements Query<T>{
     });
   }
 
+  private <V extends T> AsyncFuture<Boolean> processSubQueryAsync(final Processor<T> consumer, Query<V> query1) {
+    return query1.forEachAsync(new Processor<V>() {
+      public boolean process(final V t) {
+        return consumer.process(t);
+      }
+    });
+  }
+
   public T[] toArray(final T[] a) {
     final Collection<T> results = findAll();
     return results.toArray(a);
similarity index 93%
rename from platform/util/src/com/intellij/util/Query.java
rename to platform/core-api/src/com/intellij/util/Query.java
index 01f084ebc31782a3c7a30e1e3cc7cf65e91354fa..555b285db12ed2e1bb7be6d2f8d4861544da1ae2 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.intellij.util;
 
+import com.intellij.concurrency.AsyncFuture;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -46,5 +47,7 @@ public interface Query<Result> extends Iterable<Result> {
    */
   boolean forEach(@NotNull Processor<Result> consumer);
 
+  AsyncFuture<Boolean> forEachAsync(@NotNull Processor<Result> consumer);
+
   Result[] toArray(Result[] a);
 }
similarity index 72%
rename from platform/util/src/com/intellij/util/UniqueResultsQuery.java
rename to platform/core-api/src/com/intellij/util/UniqueResultsQuery.java
index e4d98866d8090f09251fbb5eb06145b20afb0524..44cce85e70278abd227264b03553b1662c682b99 100644 (file)
@@ -16,6 +16,7 @@
 
 package com.intellij.util;
 
+import com.intellij.concurrency.AsyncFuture;
 import gnu.trove.THashSet;
 import gnu.trove.TObjectHashingStrategy;
 import org.jetbrains.annotations.NotNull;
@@ -54,14 +55,20 @@ public class UniqueResultsQuery<T, M> implements Query<T> {
     return process(consumer, Collections.synchronizedSet(new THashSet<M>(myHashingStrategy)));
   }
 
+  @Override
+  public AsyncFuture<Boolean> forEachAsync(@NotNull Processor<T> consumer) {
+    return processAsync(consumer, Collections.synchronizedSet(new THashSet<M>(myHashingStrategy)));
+  }
+
   private boolean process(final Processor<T> consumer, final Set<M> processedElements) {
-    return myOriginal.forEach(new Processor<T>() {
-      public boolean process(final T t) {
-        return !processedElements.add(myMapper.fun(t)) || consumer.process(t);
-      }
-    });
+    return myOriginal.forEach(new MyProcessor(processedElements, consumer));
+  }
+
+  private AsyncFuture<Boolean> processAsync(final Processor<T> consumer, final Set<M> processedElements) {
+    return myOriginal.forEachAsync(new MyProcessor(processedElements, consumer));
   }
 
+
   @NotNull
   public Collection<T> findAll() {
     if (myMapper == Function.ID) {
@@ -84,4 +91,18 @@ public class UniqueResultsQuery<T, M> implements Query<T> {
   public Iterator<T> iterator() {
     return findAll().iterator();
   }
+
+  private class MyProcessor implements Processor<T> {
+    private final Set<M> myProcessedElements;
+    private final Processor<T> myConsumer;
+
+    public MyProcessor(Set<M> processedElements, Processor<T> consumer) {
+      myProcessedElements = processedElements;
+      myConsumer = consumer;
+    }
+
+    public boolean process(final T t) {
+      return !myProcessedElements.add(myMapper.fun(t)) || myConsumer.process(t);
+    }
+  }
 }
index 2ae9c19faf54e1d95d1262aba81d0b8e7953a5fc..8abd1d29d9e04f63d87acfe4130fb34a8edc8fbf 100644 (file)
@@ -15,8 +15,7 @@
  */
 package com.intellij.core;
 
-import com.intellij.concurrency.Job;
-import com.intellij.concurrency.JobLauncher;
+import com.intellij.concurrency.*;
 import com.intellij.lang.*;
 import com.intellij.lang.impl.PsiBuilderFactoryImpl;
 import com.intellij.mock.MockApplication;
@@ -136,7 +135,12 @@ public class CoreApplicationEnvironment {
 
     ProgressIndicatorProvider.ourInstance = createProgressIndicatorProvider();
 
-    myApplication.registerService(JobLauncher.class, new JobLauncher() {
+    myApplication.registerService(JobLauncher.class, createJobLauncher());
+
+  }
+
+  protected JobLauncher createJobLauncher() {
+    return new JobLauncher() {
       @Override
       public <T> boolean invokeConcurrentlyUnderProgress(@NotNull List<T> things,
                                                          ProgressIndicator progress,
@@ -149,6 +153,21 @@ public class CoreApplicationEnvironment {
         return true;
       }
 
+      @Override
+      public <T> AsyncFuture<Boolean> invokeConcurrentlyUnderProgressAsync(@NotNull List<T> things,
+                                                                           ProgressIndicator progress,
+                                                                           boolean failFastOnAcquireReadAction,
+                                                                           @NotNull Processor<T> thingProcessor) {
+        final AsyncFutureResult<Boolean> asyncFutureResult = AsyncFutureFactory.getInstance().createAsyncFutureResult();
+        try {
+          final boolean result = invokeConcurrentlyUnderProgress(things, progress, failFastOnAcquireReadAction, thingProcessor);
+          asyncFutureResult.set(result);
+        } catch (Throwable t) {
+          asyncFutureResult.setException(t);
+        }
+        return asyncFutureResult;
+      }
+
       @Override
       public Job<Void> submitToJobThread(int priority, @NotNull Runnable action, Consumer<Future> onDoneCallback) {
         action.run();
@@ -181,8 +200,7 @@ public class CoreApplicationEnvironment {
           });
         return null;
       }
-    });
-
+    };
   }
 
   protected ProgressIndicatorProvider createProgressIndicatorProvider() {
diff --git a/platform/icons/src/actions/checkOut_dark.png b/platform/icons/src/actions/checkOut_dark.png
new file mode 100644 (file)
index 0000000..81f15cd
Binary files /dev/null and b/platform/icons/src/actions/checkOut_dark.png differ
diff --git a/platform/icons/src/actions/commit_dark.png b/platform/icons/src/actions/commit_dark.png
new file mode 100644 (file)
index 0000000..8ab3fb0
Binary files /dev/null and b/platform/icons/src/actions/commit_dark.png differ
diff --git a/platform/icons/src/actions/compile_dark.png b/platform/icons/src/actions/compile_dark.png
new file mode 100644 (file)
index 0000000..608d1a4
Binary files /dev/null and b/platform/icons/src/actions/compile_dark.png differ
diff --git a/platform/icons/src/actions/copy_dark.png b/platform/icons/src/actions/copy_dark.png
new file mode 100644 (file)
index 0000000..349878a
Binary files /dev/null and b/platform/icons/src/actions/copy_dark.png differ
diff --git a/platform/icons/src/actions/menu-cut_dark.png b/platform/icons/src/actions/menu-cut_dark.png
new file mode 100644 (file)
index 0000000..a901c04
Binary files /dev/null and b/platform/icons/src/actions/menu-cut_dark.png differ
diff --git a/platform/icons/src/actions/menu-replace_dark.png b/platform/icons/src/actions/menu-replace_dark.png
new file mode 100644 (file)
index 0000000..1e702e4
Binary files /dev/null and b/platform/icons/src/actions/menu-replace_dark.png differ
diff --git a/platform/icons/src/actions/preview_dark.png b/platform/icons/src/actions/preview_dark.png
new file mode 100644 (file)
index 0000000..df710dd
Binary files /dev/null and b/platform/icons/src/actions/preview_dark.png differ
diff --git a/platform/icons/src/actions/profileMemory_dark.png b/platform/icons/src/actions/profileMemory_dark.png
new file mode 100644 (file)
index 0000000..ccedded
Binary files /dev/null and b/platform/icons/src/actions/profileMemory_dark.png differ
diff --git a/platform/icons/src/actions/replace_dark.png b/platform/icons/src/actions/replace_dark.png
new file mode 100644 (file)
index 0000000..1e702e4
Binary files /dev/null and b/platform/icons/src/actions/replace_dark.png differ
diff --git a/platform/icons/src/actions/startDebugger_dark.png b/platform/icons/src/actions/startDebugger_dark.png
new file mode 100644 (file)
index 0000000..27b35cb
Binary files /dev/null and b/platform/icons/src/actions/startDebugger_dark.png differ
index aea776ca384c12c15052a9ccd01c5493643e98a0..25ed7f2fe6ba7f35fe97ef18c82d724190149d36 100644 (file)
Binary files a/platform/icons/src/debugger/evaluateExpression.png and b/platform/icons/src/debugger/evaluateExpression.png differ
index 52149e3c5d7185d8c8835232ed349ef6dfd5d18a..be45594064963aa8ed66a1ec754b250bf25caf24 100644 (file)
Binary files a/platform/icons/src/debugger/restoreLayout.png and b/platform/icons/src/debugger/restoreLayout.png differ
index dd1ae5208318ef773bcb93cb351d1c9e8eb3c4d6..efc6a6230bb3dee70db006cf5d5e9ff73e1b6579 100644 (file)
Binary files a/platform/icons/src/debugger/stackFrame.png and b/platform/icons/src/debugger/stackFrame.png differ
index 30567586455cb0118200f2a9fadd83176df04eb2..7f1e1ffb7961cc3064d5c9e999484024a4cf2e09 100644 (file)
Binary files a/platform/icons/src/general/runWithCoverage.png and b/platform/icons/src/general/runWithCoverage.png differ
diff --git a/platform/icons/src/hierarchy/subtypes_dark.png b/platform/icons/src/hierarchy/subtypes_dark.png
new file mode 100644 (file)
index 0000000..6151a4e
Binary files /dev/null and b/platform/icons/src/hierarchy/subtypes_dark.png differ
diff --git a/platform/icons/src/hierarchy/supertypes_dark.png b/platform/icons/src/hierarchy/supertypes_dark.png
new file mode 100644 (file)
index 0000000..093dc45
Binary files /dev/null and b/platform/icons/src/hierarchy/supertypes_dark.png differ
diff --git a/platform/icons/src/toolbarDecorator/mac/addRemoteDatasource.png b/platform/icons/src/toolbarDecorator/mac/addRemoteDatasource.png
new file mode 100644 (file)
index 0000000..bcdc401
Binary files /dev/null and b/platform/icons/src/toolbarDecorator/mac/addRemoteDatasource.png differ
diff --git a/platform/icons/src/toolbarDecorator/mac/addRemoteDatasource_dark.png b/platform/icons/src/toolbarDecorator/mac/addRemoteDatasource_dark.png
new file mode 100644 (file)
index 0000000..8cf9f1e
Binary files /dev/null and b/platform/icons/src/toolbarDecorator/mac/addRemoteDatasource_dark.png differ
diff --git a/platform/icons/src/vcs/not_equal_dark.png b/platform/icons/src/vcs/not_equal_dark.png
new file mode 100644 (file)
index 0000000..27d593d
Binary files /dev/null and b/platform/icons/src/vcs/not_equal_dark.png differ
index eb2a85468c4ef19e72998e4b244125642f01546d..dbbb27085fae9dd92cfb63490c9c193b1b14d585 100644 (file)
@@ -15,6 +15,8 @@
  */
 package com.intellij.psi.search;
 
+import com.intellij.concurrency.AsyncFuture;
+import com.intellij.concurrency.AsyncFutureResult;
 import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.project.Project;
@@ -157,12 +159,22 @@ public interface PsiSearchHelper {
 
   boolean processRequests(@NotNull SearchRequestCollector request, @NotNull Processor<PsiReference> processor);
 
+  AsyncFuture<Boolean> processRequestsAsync(@NotNull SearchRequestCollector request, @NotNull Processor<PsiReference> processor);
+
   boolean processElementsWithWord(@NotNull TextOccurenceProcessor processor,
                                   @NotNull SearchScope searchScope,
                                   @NotNull String text,
                                   short searchContext,
                                   boolean caseSensitive);
 
+  AsyncFuture<Boolean> processElementsWithWordAsync(
+                                       @NotNull TextOccurenceProcessor processor,
+                                       @NotNull SearchScope searchScope,
+                                       @NotNull String text,
+                                       short searchContext,
+                                       boolean caseSensitive);
+
+
   SearchCostResult isCheapEnoughToSearch(@NotNull String name,
                                          @NotNull GlobalSearchScope scope,
                                          @Nullable PsiFile fileToIgnoreOccurencesIn,
index b9f31565a372d451e2fa11797bf350319f12ce57..c51e984fba9b167bc5d12830915ee376ec92e249 100644 (file)
@@ -1,5 +1,6 @@
 package com.intellij.psi.search;
 
+import com.intellij.concurrency.AsyncFuture;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.PsiReference;
 import com.intellij.util.AbstractQuery;
@@ -18,6 +19,11 @@ public class SearchRequestQuery extends AbstractQuery<PsiReference> {
     myRequests = requests;
   }
 
+  @Override
+  protected AsyncFuture<Boolean> processResultsAsync(@NotNull Processor<PsiReference> consumer) {
+    return PsiSearchHelper.SERVICE.getInstance(myProject).processRequestsAsync(myRequests, consumer);
+  }
+
   @Override
   protected boolean processResults(@NotNull Processor<PsiReference> consumer) {
     return PsiSearchHelper.SERVICE.getInstance(myProject).processRequests(myRequests, consumer);
index cb94bbe4bd323304e15444ff25e11b9ed6c62f46..4714408b1b7cca7ac3d4a1a90359111d08bc3b73 100644 (file)
@@ -16,7 +16,7 @@
 
 package com.intellij.psi.impl.search;
 
-import com.intellij.concurrency.JobLauncher;
+import com.intellij.concurrency.*;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.ReadAction;
 import com.intellij.openapi.application.ReadActionProcessor;
@@ -48,6 +48,7 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.*;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -111,39 +112,51 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
   }
 
   @Override
-  public boolean processElementsWithWord(@NotNull final TextOccurenceProcessor processor,
+  public boolean processElementsWithWord(@NotNull TextOccurenceProcessor processor,
+                                         @NotNull SearchScope searchScope,
+                                         @NotNull String text,
+                                         short searchContext,
+                                         boolean caseSensitive) {
+    final AsyncFuture<Boolean> result =
+      processElementsWithWordAsync(processor, searchScope, text, searchContext, caseSensitive);
+    return AsyncUtil.get(result);
+  }
+
+  @Override
+  public AsyncFuture<Boolean> processElementsWithWordAsync(@NotNull final TextOccurenceProcessor processor,
                                          @NotNull SearchScope searchScope,
                                          @NotNull final String text,
                                          short searchContext,
                                          final boolean caseSensitively) {
     if (text.isEmpty()) {
-      throw new IllegalArgumentException("Cannot search for elements with empty text");
+      return AsyncFutureFactory.wrapException(new IllegalArgumentException("Cannot search for elements with empty text"));
     }
     final ProgressIndicator progress = ProgressIndicatorProvider.getGlobalProgressIndicator();
     if (searchScope instanceof GlobalSearchScope) {
       StringSearcher searcher = new StringSearcher(text, caseSensitively, true);
 
-      return processElementsWithTextInGlobalScope(processor,
-                                                  (GlobalSearchScope)searchScope,
-                                                  searcher,
-                                                  searchContext, caseSensitively, progress);
+      return processElementsWithTextInGlobalScopeAsync(processor,
+                                                       (GlobalSearchScope)searchScope,
+                                                       searcher,
+                                                       searchContext, caseSensitively, progress);
     }
     else {
       LocalSearchScope scope = (LocalSearchScope)searchScope;
       PsiElement[] scopeElements = scope.getScope();
       final boolean ignoreInjectedPsi = scope.isIgnoreInjectedPsi();
 
-      return JobLauncher.getInstance().invokeConcurrentlyUnderProgress(Arrays.asList(scopeElements), progress, false,
-                                                                       new Processor<PsiElement>() {
-                                                                         @Override
-                                                                         public boolean process(PsiElement scopeElement) {
-                                                                           return processElementsWithWordInScopeElement(scopeElement,
-                                                                                                                        processor, text,
-                                                                                                                        caseSensitively,
-                                                                                                                        ignoreInjectedPsi,
-                                                                                                                        progress);
-                                                                         }
-                                                                       });
+      return JobLauncher.getInstance().invokeConcurrentlyUnderProgressAsync(Arrays.asList(scopeElements), progress, false,
+                                                                            new Processor<PsiElement>() {
+                                                                              @Override
+                                                                              public boolean process(PsiElement scopeElement) {
+                                                                                return processElementsWithWordInScopeElement(scopeElement,
+                                                                                                                             processor,
+                                                                                                                             text,
+                                                                                                                             caseSensitively,
+                                                                                                                             ignoreInjectedPsi,
+                                                                                                                             progress);
+                                                                              }
+                                                                            });
     }
   }
 
@@ -163,13 +176,14 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
     }).booleanValue();
   }
 
-  private boolean processElementsWithTextInGlobalScope(@NotNull final TextOccurenceProcessor processor,
+  private AsyncFuture<Boolean> processElementsWithTextInGlobalScopeAsync(@NotNull final TextOccurenceProcessor processor,
                                                        @NotNull final GlobalSearchScope scope,
                                                        @NotNull final StringSearcher searcher,
                                                        final short searchContext,
                                                        final boolean caseSensitively,
                                                        final ProgressIndicator progress) {
-    LOG.assertTrue(!Thread.holdsLock(PsiLock.LOCK), "You must not run search from within updating PSI activity. Please consider invokeLatering it instead.");
+    LOG.assertTrue(!Thread.holdsLock(PsiLock.LOCK),
+                   "You must not run search from within updating PSI activity. Please consider invokeLatering it instead.");
     if (progress != null) {
       progress.pushState();
       progress.setText(PsiBundle.message("psi.scanning.files.progress"));
@@ -182,32 +196,33 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
       progress.setText(PsiBundle.message("psi.search.for.word.progress", text));
     }
 
-    try {
-      return processPsiFileRoots(fileSet, new Processor<PsiElement>() {
+      final AsyncFuture<Boolean> result = processPsiFileRootsAsync(fileSet, new Processor<PsiElement>() {
         @Override
         public boolean process(PsiElement psiRoot) {
           return LowLevelSearchUtil.processElementsContainingWordInElement(processor, psiRoot, searcher, true, progress);
         }
       }, progress);
-    }
-    finally {
-      if (progress != null) {
-        progress.popState();
-      }
-    }
+      return new FinallyFuture<Boolean>(result, new Runnable() {
+        @Override
+        public void run() {
+          if (progress != null) {
+            progress.popState();
+          }
+        }
+      });
   }
 
-  private boolean processPsiFileRoots(@NotNull List<VirtualFile> files,
+  private AsyncFuture<Boolean> processPsiFileRootsAsync(@NotNull List<VirtualFile> files,
                                       @NotNull final Processor<PsiElement> psiRootProcessor,
                                       final ProgressIndicator progress) {
     myManager.startBatchFilesProcessingMode();
-    try {
       final AtomicInteger counter = new AtomicInteger(0);
       final AtomicBoolean canceled = new AtomicBoolean(false);
       final AtomicBoolean pceThrown = new AtomicBoolean(false);
 
       final int size = files.size();
-      boolean completed = JobLauncher.getInstance().invokeConcurrentlyUnderProgress(files, progress, false, new Processor<VirtualFile>() {
+      AsyncFuture<Boolean>
+        completed = JobLauncher.getInstance().invokeConcurrentlyUnderProgressAsync(files, progress, false, new Processor<VirtualFile>() {
         @Override
         public boolean process(final VirtualFile vfile) {
           final PsiFile file = ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
@@ -259,15 +274,29 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
         }
       });
 
-      if (pceThrown.get()) {
-        throw new ProcessCanceledException();
-      }
+      final AsyncFutureResult<Boolean> ourResult = AsyncFutureFactory.getInstance().createAsyncFutureResult();
+      completed.addConsumer(SameThreadExecutor.INSTANCE, new DefaultResultConsumer<Boolean>(ourResult) {
+        @Override
+        public void onSuccess(Boolean value) {
+          if (pceThrown.get())
+            ourResult.setException(new ProcessCanceledException());
+          else
+            ourResult.set(value);
+        }
 
-      return completed;
-    }
-    finally {
-      myManager.finishBatchFilesProcessingMode();
-    }
+        @Override
+        public void onFailure(Throwable t) {
+          ourResult.setException(t);
+        }
+      });
+
+
+      return new FinallyFuture<Boolean>(ourResult, new Runnable() {
+        @Override
+        public void run() {
+          myManager.finishBatchFilesProcessingMode();
+        }
+      });
   }
 
   @NotNull
@@ -323,8 +352,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
   @Override
   @NotNull
   public PsiFile[] findFilesWithPlainTextWords(@NotNull String word) {
-    return CacheManager.SERVICE.getInstance(myManager.getProject()).getFilesWithWord(word,
-                                                                                     UsageSearchContext.IN_PLAIN_TEXT,
+    return CacheManager.SERVICE.getInstance(myManager.getProject()).getFilesWithWord(word, UsageSearchContext.IN_PLAIN_TEXT,
                                                                                      GlobalSearchScope.projectScope(myManager.getProject()),
                                                                                      true);
   }
@@ -482,37 +510,72 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
   }
 
   @Override
-  public boolean processRequests(@NotNull SearchRequestCollector collector, @NotNull Processor<PsiReference> processor) {
-    Map<SearchRequestCollector, Processor<PsiReference>> collectors = ContainerUtil.newHashMap();
+  public boolean processRequests(@NotNull SearchRequestCollector request, @NotNull Processor<PsiReference> processor) {
+    return AsyncUtil.get(processRequestsAsync(request, processor));
+  }
+
+  @Override
+  public AsyncFuture<Boolean> processRequestsAsync(@NotNull SearchRequestCollector collector, @NotNull Processor<PsiReference> processor) {
+    final Map<SearchRequestCollector, Processor<PsiReference>> collectors = ContainerUtil.newHashMap();
     collectors.put(collector, processor);
 
     appendCollectorsFromQueryRequests(collectors);
 
-    ProgressIndicator progress = ProgressIndicatorProvider.getGlobalProgressIndicator();
-    do {
-      MultiMap<Set<IdIndexEntry>, RequestWithProcessor> globals = new MultiMap<Set<IdIndexEntry>, RequestWithProcessor>();
-      List<Computable<Boolean>> customs = ContainerUtil.newArrayList();
-      Set<RequestWithProcessor> locals = ContainerUtil.newLinkedHashSet();
-      distributePrimitives(collectors, locals, globals, customs);
-
-      if (!processGlobalRequestsOptimized(globals, progress)) {
-        return false;
-      }
+    final ProgressIndicator progress = ProgressIndicatorProvider.getGlobalProgressIndicator();
+    final DoWhile doWhile = new DoWhile() {
 
-      for (RequestWithProcessor local : locals) {
-        if (!processSingleRequest(local.request, local.refProcessor)) {
-          return false;
-        }
+      @Override
+      protected AsyncFuture<Boolean> body() {
+        final AsyncFutureResult<Boolean> result = AsyncFutureFactory.getInstance().createAsyncFutureResult();
+        MultiMap<Set<IdIndexEntry>, RequestWithProcessor> globals = new MultiMap<Set<IdIndexEntry>, RequestWithProcessor>();
+        final List<Computable<Boolean>> customs = ContainerUtil.newArrayList();
+        final Set<RequestWithProcessor> locals = ContainerUtil.newLinkedHashSet();
+        distributePrimitives(collectors, locals, globals, customs);
+        processGlobalRequestsOptimizedAsync(globals, progress)
+          .addConsumer(SameThreadExecutor.INSTANCE, new DefaultResultConsumer<Boolean>(result) {
+            @Override
+            public void onSuccess(Boolean value) {
+              if (!value.booleanValue()) {
+                result.set(value);
+              }
+              else {
+                final Iterate<RequestWithProcessor> iterate = new Iterate<RequestWithProcessor>(locals) {
+                  @Override
+                  protected AsyncFuture<Boolean> process(RequestWithProcessor local) {
+                    return processSingleRequestAsync(local.request, local.refProcessor);
+                  }
+                };
+
+                iterate.getResult()
+                  .addConsumer(SameThreadExecutor.INSTANCE, new DefaultResultConsumer<Boolean>(result) {
+                    @Override
+                    public void onSuccess(Boolean value) {
+                      if (!value.booleanValue()) {
+                        result.set(false);
+                        return;
+                      }
+                      for (Computable<Boolean> custom : customs) {
+                        if (!custom.compute()) {
+                          result.set(false);
+                          return;
+                        }
+                      }
+                      result.set(true);
+                    }
+                  });
+              }
+            }
+          });
+        return result;
       }
 
-      for (Computable<Boolean> custom : customs) {
-        if (!custom.compute()) {
-          return false;
-        }
+      @Override
+      protected boolean condition() {
+        return appendCollectorsFromQueryRequests(collectors);
       }
-    } while (appendCollectorsFromQueryRequests(collectors));
+    };
 
-    return true;
+    return doWhile.getResult();
   }
 
   private static boolean appendCollectorsFromQueryRequests(Map<SearchRequestCollector, Processor<PsiReference>> collectors) {
@@ -530,17 +593,17 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
     return changed;
   }
 
-  private boolean processGlobalRequestsOptimized(@NotNull MultiMap<Set<IdIndexEntry>, RequestWithProcessor> singles,
+  private AsyncFuture<Boolean> processGlobalRequestsOptimizedAsync(MultiMap<Set<IdIndexEntry>, RequestWithProcessor> singles,
                                                  final ProgressIndicator progress) {
     if (singles.isEmpty()) {
-      return true;
+      return AsyncFutureFactory.wrap(true);
     }
 
     if (singles.size() == 1) {
       final Collection<RequestWithProcessor> requests = singles.get(singles.keySet().iterator().next());
       if (requests.size() == 1) {
         final RequestWithProcessor theOnly = requests.iterator().next();
-        return processSingleRequest(theOnly.request, theOnly.refProcessor);
+        return processSingleRequestAsync(theOnly.request, theOnly.refProcessor);
       }
     }
 
@@ -551,53 +614,61 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
 
     final MultiMap<VirtualFile, RequestWithProcessor> candidateFiles = collectFiles(singles, progress);
 
-    try {
-      if (candidateFiles.isEmpty()) {
-        return true;
-      }
+    if (candidateFiles.isEmpty()) {
+      return AsyncFutureFactory.wrap(true);
+    }
 
-      final Map<RequestWithProcessor, StringSearcher> searchers = new HashMap<RequestWithProcessor, StringSearcher>();
-      final Set<String> allWords = new TreeSet<String>();
-      for (RequestWithProcessor singleRequest : candidateFiles.values()) {
-        searchers.put(singleRequest, new StringSearcher(singleRequest.request.word, singleRequest.request.caseSensitive, true));
-        allWords.add(singleRequest.request.word);
-      }
+    final Map<RequestWithProcessor, StringSearcher> searchers = new HashMap<RequestWithProcessor, StringSearcher>();
+    final Set<String> allWords = new TreeSet<String>();
+    for (RequestWithProcessor singleRequest : candidateFiles.values()) {
+      searchers.put(singleRequest, new StringSearcher(singleRequest.request.word, singleRequest.request.caseSensitive, true));
+      allWords.add(singleRequest.request.word);
+    }
 
-      if (progress != null) {
-        final StringBuilder result = new StringBuilder();
-        for (String string : allWords) {
-          if (string != null && !string.isEmpty()) {
-            if (result.length() > 50) {
-              result.append("...");
-              break;
+    if (progress != null) {
+      progress.setText(PsiBundle.message("psi.search.for.word.progress", getPresentableWordsDescription(allWords)));
+    }
+
+    final AsyncFuture<Boolean> result =
+      processPsiFileRootsAsync(new ArrayList<VirtualFile>(candidateFiles.keySet()), new Processor<PsiElement>() {
+        @Override
+        public boolean process(PsiElement psiRoot) {
+          final VirtualFile vfile = psiRoot.getContainingFile().getVirtualFile();
+          for (final RequestWithProcessor singleRequest : candidateFiles.get(vfile)) {
+            StringSearcher searcher = searchers.get(singleRequest);
+            TextOccurenceProcessor adapted = adaptProcessor(singleRequest.request, singleRequest.refProcessor);
+            if (!LowLevelSearchUtil.processElementsContainingWordInElement(adapted, psiRoot, searcher, true, progress)) {
+              return false;
             }
-            if (result.length() != 0) result.append(", ");
-            result.append(string);
           }
+          return true;
+        }
+      }, progress);
+
+    return new FinallyFuture<Boolean>(result, new Runnable() {
+      @Override
+      public void run() {
+        if (progress != null) {
+          progress.popState();
         }
-        progress.setText(PsiBundle.message("psi.search.for.word.progress", result.toString()));
+
       }
+    });
+  }
 
-      return processPsiFileRoots(new ArrayList<VirtualFile>(candidateFiles.keySet()), new Processor<PsiElement>() {
-                                   @Override
-                                   public boolean process(PsiElement psiRoot) {
-                                     final VirtualFile vfile = psiRoot.getContainingFile().getVirtualFile();
-                                     for (final RequestWithProcessor singleRequest : candidateFiles.get(vfile)) {
-                                       StringSearcher searcher = searchers.get(singleRequest);
-                                       TextOccurenceProcessor adapted = adaptProcessor(singleRequest.request, singleRequest.refProcessor);
-                                       if (!LowLevelSearchUtil.processElementsContainingWordInElement(adapted, psiRoot, searcher, true, progress)) {
-                                         return false;
-                                       }
-                                     }
-                                     return true;
-                                   }
-                                 }, progress);
-    }
-    finally {
-      if (progress != null) {
-        progress.popState();
+  private String getPresentableWordsDescription(Set<String> allWords) {
+    final StringBuilder result = new StringBuilder();
+    for (String string : allWords) {
+        if (string != null && !string.isEmpty()) {
+        if (result.length() > 50) {
+          result.append("...");
+          break;
+        }
+        if (result.length() != 0) result.append(", ");
+        result.append(string);
       }
     }
+    return result.toString();
   }
 
   @NotNull
@@ -759,8 +830,13 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
     collection.add(newValue);
   }
 
-  private boolean processSingleRequest(@NotNull PsiSearchRequest single, @NotNull Processor<PsiReference> consumer) {
-    return processElementsWithWord(adaptProcessor(single, consumer), single.searchScope, single.word, single.searchContext, single.caseSensitive);
+  private boolean processSingleRequest(PsiSearchRequest single, Processor<PsiReference> consumer) {
+    return AsyncUtil.get(processSingleRequestAsync(single, consumer));
+  }
+
+  private AsyncFuture<Boolean> processSingleRequestAsync(PsiSearchRequest single, Processor<PsiReference> consumer) {
+    return processElementsWithWordAsync(adaptProcessor(single, consumer), single.searchScope, single.word, single.searchContext,
+                                        single.caseSensitive);
   }
 
   @Override
index 2c7ef880192905e3e2fbf188b776503661b8d977..5df38fa518642ea238fdc5d43f2eac142009170e 100644 (file)
@@ -284,7 +284,7 @@ public class InitialConfigurationDialog extends DialogWrapper {
   private static boolean matchesPlatform(Keymap keymap) {
     final String name = keymap.getName();
     if (KeymapManager.DEFAULT_IDEA_KEYMAP.equals(name)) {
-      return !SystemInfo.isMac && !SystemInfo.isLinux;
+      return SystemInfo.isWindows;
     }
     else if (KeymapManager.MAC_OS_X_KEYMAP.equals(name) || "Mac OS X 10.5+".equals(name)) {
       return SystemInfo.isMac;
index e4191a92403134518ea834fb11f1f4e4e3dcf88c..eed611df289103702f6569b6faea299b6875adf3 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.intellij.application.options.codeStyle.arrangement;
 
+import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchingRulesControl;
 import com.intellij.openapi.actionSystem.DataKey;
 import com.intellij.util.Consumer;
 import com.intellij.util.NotNullFunction;
@@ -26,12 +27,14 @@ import org.jetbrains.annotations.NonNls;
  */
 public class ArrangementConstants {
 
-  @NonNls public static final String ACTION_GROUP_RULE_EDITOR_CONTEXT_MENU = "Arrangement.RuleEditor.Context.Menu";
-  @NonNls public static final String ACTION_GROUP_RULE_EDITOR_TOOL_WINDOW  = "Arrangement.RuleEditor.ToolWIndow";
+  public static final DataKey<ArrangementMatchingRulesControl> MATCHING_RULES_CONTROL_KEY = DataKey.create("Arrangement.RuleEditor");
 
-  @NonNls public static final String RULE_EDITOR_PLACE             = "Arrangement.RuleEditor.Place";
-  @NonNls public static final String RULE_EDITOR_TOOL_WINDOW_PLACE = "Arrangement.RuleEditor.ToolWindow.Place";
-  @NonNls public static final String RULE_TREE_PLACE               = "Arrangement.RuleTree.Place";
+  @NonNls public static final String ACTION_GROUP_MATCHING_RULES_CONTEXT_MENU    = "Arrangement.Rule.Match.Control.Context.Menu";
+  @NonNls public static final String ACTION_GROUP_MATCHING_RULES_CONTROL_TOOLBAR = "Arrangement.Rule.Match.Control.ToolBar";
+
+  @NonNls public static final String RULE_EDITOR_PLACE                    = "Arrangement.RuleEditor.Place";
+  @NonNls public static final String MATCHING_RULES_CONTROL_TOOLBAR_PLACE = "Arrangement.Rule.Match.Control.ToolBar.Place";
+  @NonNls public static final String MATCHING_RULES_CONTROL_PLACE         = "Arrangement.Rule.Match.Control.Place";
 
   public static final int HORIZONTAL_PADDING    = 8;
   public static final int VERTICAL_PADDING      = 4;
@@ -45,9 +48,6 @@ public class ArrangementConstants {
 
   public static final boolean LOG_RULE_MODIFICATION = Boolean.parseBoolean(System.getProperty("log.arrangement.rule.modification"));
 
-  public static final DataKey<Runnable> NEW_RULE_FUNCTION_KEY = DataKey.create("Arrangement.Rule.Function.New");
-  public static final DataKey<Runnable> REMOVE_RULE_FUNCTION_KEY = DataKey.create("Arrangement.Rule.Function.Remove");
-
   public static final DataKey<NotNullFunction<Boolean/* move up? */, Boolean/* is enabled */>> UPDATE_MOVE_RULE_FUNCTION_KEY
     = DataKey.create("Arrangement.Rule.Function.Update.Move");
   public static final DataKey<Consumer<Boolean/* move up? */>> MOVE_RULE_FUNCTION_KEY = DataKey.create("Arrangement.Rule.Function.Move");