From 0a393b13481c66c6c08a3dd2c232f00c154aed89 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 23 Jul 2012 20:21:36 +0200 Subject: [PATCH 01/35] temp workaround for ubunty selection --- .../platform-api/src/com/intellij/ui/treeStructure/Tree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java index b67783afd0a3..5c29f06bb730 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java @@ -96,7 +96,7 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith public void setUI(final TreeUI ui) { TreeUI actualUI = ui; if (!isCustomUI()) { - if (!(ui instanceof WideSelectionTreeUI) /*&& UIUtil.isUnderAquaBasedLookAndFeel()*/) { + if (!(ui instanceof WideSelectionTreeUI) && (UIUtil.isUnderAquaBasedLookAndFeel() || SystemInfo.isWindows)) { //todo[kb] fix on ubunty actualUI = new WideSelectionTreeUI(isMacWideSelection(), !isFileColorsEnabled()); } } From e94e2ba4935fb35a4c5f869ed2c68effa4a22fef Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 23 Jul 2012 18:13:04 +0200 Subject: [PATCH 02/35] show update confirmation as balloon; register in event log --- .../updateSettings/impl/UpdateChecker.java | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java index 7ae2704d4156..5990ab296dce 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java @@ -19,16 +19,12 @@ import com.intellij.ide.IdeBundle; import com.intellij.ide.plugins.*; import com.intellij.ide.reporter.ConnectionException; import com.intellij.ide.util.PropertiesComponent; -import com.intellij.notification.Notification; -import com.intellij.notification.NotificationType; -import com.intellij.notification.Notifications; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationInfo; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.PathManager; +import com.intellij.notification.*; +import com.intellij.openapi.application.*; import com.intellij.openapi.application.ex.ApplicationInfoEx; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.PluginId; +import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; @@ -40,6 +36,8 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.IdeFrame; +import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.util.PlatformUtils; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.UrlConnectionUtil; @@ -54,6 +52,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.HyperlinkEvent; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; @@ -451,10 +450,24 @@ public final class UpdateChecker { dialog.setModal(alwaysShowResults); dialog.show(); } - else if (updatedPlugins != null || alwaysShowResults) { + else if (updatedPlugins != null) { NoUpdatesDialog dialog = new NoUpdatesDialog(true, updatedPlugins, enableLink); dialog.setShowConfirmation(showConfirmation); dialog.show(); + } else if (alwaysShowResults) { + final String title = IdeBundle.message("updates.info.dialog.title"); + final String message = "You already have the latest version of " + ApplicationInfo.getInstance().getVersionName() + " installed.
" + + "To configure automatic update settings, see the Updates dialog of your IDE settings"; + NotificationGroup.balloonGroup("update.available.group") + .createNotification(title, message, NotificationType.INFORMATION, new NotificationListener() { + @Override + public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { + notification.expire(); + final UpdateSettingsConfigurable configurable = new UpdateSettingsConfigurable(); + IdeFrame ideFrame = WindowManagerEx.getInstanceEx().findFrameFor(null); + ShowSettingsUtil.getInstance().editConfigurable((JFrame)ideFrame, configurable); + } + }).notify(null); } } From 816dfdcb817087b805f0be2a0b66e3973692f2b3 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 23 Jul 2012 20:04:08 +0200 Subject: [PATCH 03/35] cancel started rename: restore old name before proceed (IDEA-89001) --- .../refactoring/rename/inplace/InplaceRefactoring.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java index f1c897706ff5..233d8a417664 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java @@ -104,7 +104,7 @@ public abstract class InplaceRefactoring { protected String myAdvertisementText; private ArrayList myHighlighters; protected String myInitialName; - protected final String myOldName; + protected String myOldName; protected RangeMarker myBeforeRevert = null; protected String myInsertedName; protected LinkedHashSet myNameSuggestions; @@ -273,6 +273,14 @@ public abstract class InplaceRefactoring { return true; } else { + + if (!ourRenamersStack.isEmpty() && ourRenamersStack.peek() == this) { + ourRenamersStack.pop(); + if (!ourRenamersStack.empty()) { + myOldName = ourRenamersStack.peek().myOldName; + } + } + revertState(); final TemplateState templateState = TemplateManagerImpl.getTemplateState(InjectedLanguageUtil.getTopLevelEditor(myEditor)); if (templateState != null) { From a122a404cee0ddaeb251084972c0a863586d883c Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 23 Jul 2012 21:15:35 +0200 Subject: [PATCH 04/35] IDEA-89158: testng status updated --- .../src/com/theoryinpractice/testng/ui/TestNGResults.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/testng/src/com/theoryinpractice/testng/ui/TestNGResults.java b/plugins/testng/src/com/theoryinpractice/testng/ui/TestNGResults.java index f7e30de3c33f..aabc01b98742 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/ui/TestNGResults.java +++ b/plugins/testng/src/com/theoryinpractice/testng/ui/TestNGResults.java @@ -368,9 +368,15 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn public void run() { animator.stopMovie(); updateStatusLine(); - if (total > count) { + if (total > count || myStatus == MessageHelper.SKIPPED_TEST) { myStatusLine.setStatusColor(ColorProgressBar.YELLOW); } + else if (myStatus == MessageHelper.FAILED_TEST) { + myStatusLine.setStatusColor(ColorProgressBar.RED); + } + else { + myStatusLine.setStatusColor(ColorProgressBar.GREEN); + } rootNode.setInProgress(false); if (TestNGConsoleProperties.SELECT_FIRST_DEFECT.value(myProperties)) { selectTest(rootNode.getFirstDefect()); From b4591256ab0ea44bf70cc6565e4ac7e0c827e389 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 24 Jul 2012 07:43:46 +0200 Subject: [PATCH 05/35] fix selection on Mac --- .../util/ui/tree/WideSelectionTreeUI.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java b/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java index 917a503c6a5a..6ab5d652a07e 100644 --- a/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java +++ b/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java @@ -283,15 +283,17 @@ public class WideSelectionTreeUI extends BasicTreeUI { } } else { - //Color bg = tree.hasFocus() ? UIUtil.getTreeSelectionBackground() : UIUtil.getTreeUnfocusedSelectionBackground(); - //if (!selected) { - // bg = background; - //} + if (UIUtil.isUnderAquaBasedLookAndFeel()) { + Color bg = tree.hasFocus() ? UIUtil.getTreeSelectionBackground() : UIUtil.getTreeUnfocusedSelectionBackground(); + if (!selected) { + bg = background; + } - //if (/*myAlwaysPaintRowBackground || */selected) { - // rowGraphics.setColor(bg); - // rowGraphics.fillRect(xOffset, bounds.y, containerWidth, bounds.height - 1); - //} + if (myAlwaysPaintRowBackground || selected) { + rowGraphics.setColor(bg); + rowGraphics.fillRect(xOffset, bounds.y, containerWidth, bounds.height - 1); + } + } } if (shouldPaintExpandControl(path, row, isExpanded, hasBeenExpanded, isLeaf)) { @@ -308,7 +310,7 @@ public class WideSelectionTreeUI extends BasicTreeUI { @Override public void paint(Graphics g, JComponent c) { - if (myAlwaysPaintRowBackground && myWideSelection) { + if (myAlwaysPaintRowBackground && myWideSelection && !UIUtil.isUnderAquaBasedLookAndFeel()) { paintSelectedRows(g, ((JTree)c)); } if (myWideSelection) { From 6f3abb799d47a02753f8f19b602136f0f73fa0c5 Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 24 Jul 2012 10:43:02 +0400 Subject: [PATCH 06/35] new project model: artifacts added --- .../impl/artifacts/ArtifactManagerImpl.java | 3 + .../ArtifactManagerStateSplitter.java | 1 + .../impl/artifacts/InvalidArtifact.java | 1 + .../impl/elements/ArchiveElementType.java | 4 +- .../jetbrains/jps/cmdline/BuildSession.java | 13 +- .../jps/incremental/AllProjectScope.java | 4 +- .../jps/incremental/CompileScope.java | 10 +- .../jps/incremental/ModulesAndFilesScope.java | 4 +- .../jps/incremental/ModulesScope.java | 4 +- .../artifacts/ArtifactSourceFilesState.java | 10 +- .../artifacts/ArtifactsBuildData.java | 8 +- .../artifacts/IncArtifactBuilder.java | 32 ++-- .../builders/LayoutElementBuilderService.java | 4 +- .../LayoutElementBuildersRegistry.java | 121 ++++++++------- .../artifacts/impl/ArtifactSorter.java | 143 ++++++++---------- .../artifacts/impl/JpsArtifactUtil.java | 30 ++++ .../jetbrains/ether/IncrementalTestCase.java | 8 +- .../rebuild/JpsRebuildTestCase.groovy | 6 +- .../ArtifactBuilderOverwriteTest.java | 16 +- .../artifacts/ArtifactBuilderTest.java | 50 +++--- .../artifacts/ArtifactBuilderTestCase.java | 52 ++++--- .../IncrementalArtifactBuildingTest.java | 26 ++-- .../artifacts/LayoutElementTestUtil.java | 60 +++----- .../model/artifact/DirectoryArtifactType.java | 8 + .../jps/model/artifact/JarArtifactType.java | 8 + .../jps/model/artifact/JpsArtifact.java | 30 ++++ .../model/artifact/JpsArtifactReference.java | 16 ++ .../model/artifact/JpsArtifactService.java | 27 ++++ .../jps/model/artifact/JpsArtifactType.java | 14 ++ .../elements/JpsArchivePackagingElement.java | 10 ++ .../JpsArtifactOutputPackagingElement.java | 12 ++ .../elements/JpsArtifactRootElement.java | 7 + .../elements/JpsComplexPackagingElement.java | 10 ++ .../JpsCompositePackagingElement.java | 15 ++ .../JpsDirectoryCopyPackagingElement.java | 10 ++ .../JpsDirectoryPackagingElement.java | 11 ++ ...JpsExtractedDirectoryPackagingElement.java | 14 ++ .../elements/JpsFileCopyPackagingElement.java | 15 ++ .../JpsLibraryFilesPackagingElement.java | 12 ++ .../JpsModuleOutputPackagingElement.java | 16 ++ .../elements/JpsPackagingElement.java | 9 ++ .../elements/JpsPackagingElementFactory.java | 43 ++++++ .../model/java/JpsJavaExtensionService.java | 7 + ...roductionModuleOutputPackagingElement.java | 9 ++ .../JpsTestModuleOutputPackagingElement.java | 9 ++ .../jps/model/library/JpsLibrary.java | 3 + ...ains.jps.model.artifact.JpsArtifactService | 1 + ...tifact.elements.JpsPackagingElementFactory | 1 + .../src/org/jetbrains/jps/JpsPathUtil.java | 3 +- .../model/artifact/impl/JpsArtifactImpl.java | 74 +++++++++ .../model/artifact/impl/JpsArtifactKind.java | 17 +++ .../impl/JpsArtifactReferenceImpl.java | 39 +++++ .../artifact/impl/JpsArtifactServiceImpl.java | 36 +++++ .../JpsArchivePackagingElementImpl.java | 40 +++++ ...JpsArtifactOutputPackagingElementImpl.java | 56 +++++++ .../elements/JpsArtifactRootElementImpl.java | 22 +++ .../JpsComplexPackagingElementBase.java | 17 +++ .../JpsCompositePackagingElementBase.java | 38 +++++ .../JpsDirectoryCopyPackagingElementImpl.java | 30 ++++ .../JpsDirectoryPackagingElementImpl.java | 39 +++++ ...xtractedDirectoryPackagingElementImpl.java | 43 ++++++ .../JpsFileCopyPackagingElementBase.java | 34 +++++ .../JpsFileCopyPackagingElementImpl.java | 42 +++++ .../JpsLibraryFilesPackagingElementImpl.java | 61 ++++++++ .../JpsModuleOutputPackagingElementBase.java | 43 ++++++ .../JpsPackagingElementFactoryImpl.java | 95 ++++++++++++ .../impl/JpsJavaExtensionServiceImpl.java | 13 ++ ...ctionModuleOutputPackagingElementImpl.java | 33 ++++ ...sTestModuleOutputPackagingElementImpl.java | 33 ++++ .../model/library/impl/JpsLibraryImpl.java | 42 +++++ .../JpsModelLoaderExtension.java | 11 ++ .../model/serialization/JpsModuleLoader.java | 2 +- .../model/serialization/JpsProjectLoader.java | 31 +++- .../artifact}/ArtifactManagerState.java | 2 +- .../artifact}/ArtifactPropertiesState.java | 2 +- .../artifact}/ArtifactState.java | 4 +- .../artifact/JpsArtifactLoader.java | 136 +++++++++++++++++ .../artifact/JpsPackagingElementLoader.java | 21 +++ .../java/JpsJavaModelLoaderExtension.java | 33 ++++ jps/model/jps-model.iml | 1 + .../src/org/jetbrains/jps/Project.groovy | 2 - .../src/org/jetbrains/jps/ProjectPaths.java | 47 +----- .../jetbrains/jps/artifacts/Artifact.groovy | 15 -- .../jps/artifacts/ArtifactProperties.groovy | 7 - .../ArtifactPropertiesProviderService.groovy | 16 -- .../jps/artifacts/ComplexLayoutElement.groovy | 79 ---------- .../artifacts/CompositeLayoutElement.groovy | 46 ------ .../jps/artifacts/LayoutElement.groovy | 49 ------ .../jps/artifacts/LayoutElementFactory.groovy | 18 --- .../artifacts/LayoutElementTypeService.java | 23 --- .../jetbrains/jps/idea/ArtifactLoader.groovy | 125 --------------- .../jps/idea/IdeaProjectLoader.groovy | 25 --- 92 files changed, 1714 insertions(+), 758 deletions(-) create mode 100644 jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactUtil.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/DirectoryArtifactType.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/JarArtifactType.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifact.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactReference.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactService.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactType.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArchivePackagingElement.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactOutputPackagingElement.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactRootElement.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsComplexPackagingElement.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsCompositePackagingElement.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryCopyPackagingElement.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryPackagingElement.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsExtractedDirectoryPackagingElement.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsFileCopyPackagingElement.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsLibraryFilesPackagingElement.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsModuleOutputPackagingElement.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElement.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElementFactory.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/java/JpsProductionModuleOutputPackagingElement.java create mode 100644 jps/model-api/src/org/jetbrains/jps/model/java/JpsTestModuleOutputPackagingElement.java create mode 100644 jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.JpsArtifactService create mode 100644 jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.elements.JpsPackagingElementFactory rename jps/{model => model-impl}/src/org/jetbrains/jps/JpsPathUtil.java (95%) create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactImpl.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactKind.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactReferenceImpl.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactServiceImpl.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArchivePackagingElementImpl.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactOutputPackagingElementImpl.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactRootElementImpl.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsComplexPackagingElementBase.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsCompositePackagingElementBase.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryCopyPackagingElementImpl.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryPackagingElementImpl.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsExtractedDirectoryPackagingElementImpl.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementBase.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementImpl.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsLibraryFilesPackagingElementImpl.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsModuleOutputPackagingElementBase.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsPackagingElementFactoryImpl.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsProductionModuleOutputPackagingElementImpl.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsTestModuleOutputPackagingElementImpl.java rename {java/compiler/impl/src/com/intellij/packaging/impl/artifacts => jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact}/ArtifactManagerState.java (95%) rename {java/compiler/impl/src/com/intellij/packaging/impl/artifacts => jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact}/ArtifactPropertiesState.java (95%) rename {java/compiler/impl/src/com/intellij/packaging/impl/artifacts => jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact}/ArtifactState.java (95%) create mode 100644 jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactLoader.java create mode 100644 jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsPackagingElementLoader.java delete mode 100644 jps/model/src/org/jetbrains/jps/artifacts/Artifact.groovy delete mode 100644 jps/model/src/org/jetbrains/jps/artifacts/ArtifactProperties.groovy delete mode 100644 jps/model/src/org/jetbrains/jps/artifacts/ArtifactPropertiesProviderService.groovy delete mode 100644 jps/model/src/org/jetbrains/jps/artifacts/ComplexLayoutElement.groovy delete mode 100644 jps/model/src/org/jetbrains/jps/artifacts/CompositeLayoutElement.groovy delete mode 100644 jps/model/src/org/jetbrains/jps/artifacts/LayoutElement.groovy delete mode 100644 jps/model/src/org/jetbrains/jps/artifacts/LayoutElementFactory.groovy delete mode 100644 jps/model/src/org/jetbrains/jps/artifacts/LayoutElementTypeService.java delete mode 100644 jps/model/src/org/jetbrains/jps/idea/ArtifactLoader.groovy diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerImpl.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerImpl.java index 3e7011576e30..c3896a82a472 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerImpl.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerImpl.java @@ -38,6 +38,9 @@ import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.serialization.artifact.ArtifactManagerState; +import org.jetbrains.jps.model.serialization.artifact.ArtifactPropertiesState; +import org.jetbrains.jps.model.serialization.artifact.ArtifactState; import java.util.*; diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerStateSplitter.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerStateSplitter.java index 7525b85843f2..90ee240c0a04 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerStateSplitter.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerStateSplitter.java @@ -21,6 +21,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.text.UniqueNameGenerator; import org.jdom.Element; +import org.jetbrains.jps.model.serialization.artifact.ArtifactState; import java.util.ArrayList; import java.util.List; diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/InvalidArtifact.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/InvalidArtifact.java index 6f25a287f881..c6df02ec5188 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/InvalidArtifact.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/InvalidArtifact.java @@ -16,6 +16,7 @@ package com.intellij.packaging.impl.artifacts; import com.intellij.packaging.elements.PackagingElementFactory; +import org.jetbrains.jps.model.serialization.artifact.ArtifactState; /** * @author nik diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ArchiveElementType.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ArchiveElementType.java index e1ddd27d7cb8..0dca4cba3191 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ArchiveElementType.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ArchiveElementType.java @@ -18,9 +18,9 @@ package com.intellij.packaging.impl.elements; import com.intellij.openapi.compiler.CompilerBundle; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.packaging.elements.CompositePackagingElement; import com.intellij.packaging.elements.CompositePackagingElementType; +import com.intellij.packaging.impl.artifacts.ArtifactUtil; import com.intellij.packaging.impl.ui.properties.ArchiveElementPropertiesPanel; import com.intellij.packaging.ui.ArtifactEditorContext; import com.intellij.packaging.ui.PackagingElementPropertiesPanel; @@ -53,7 +53,7 @@ class ArchiveElementType extends CompositePackagingElementType= 4 && name.charAt(name.length() - 4) == '.' && StringUtil.endsWithIgnoreCase(name, "ar")) { + if (ArtifactUtil.isArchiveName(name)) { return new ArchiveElementPropertiesPanel(element, context); } return null; diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java index e43cf4700b6a..d6c876de3856 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java @@ -17,7 +17,6 @@ import org.jetbrains.ether.dependencyView.Callbacks; import org.jetbrains.jps.JpsPathUtil; import org.jetbrains.jps.Project; import org.jetbrains.jps.api.*; -import org.jetbrains.jps.artifacts.Artifact; import org.jetbrains.jps.idea.IdeaProjectLoader; import org.jetbrains.jps.idea.SystemOutErrorReporter; import org.jetbrains.jps.incremental.*; @@ -29,6 +28,8 @@ import org.jetbrains.jps.incremental.storage.ProjectTimestamps; import org.jetbrains.jps.incremental.storage.Timestamps; import org.jetbrains.jps.model.JpsElementFactory; import org.jetbrains.jps.model.JpsModel; +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.artifact.JpsArtifactService; import org.jetbrains.jps.model.java.JpsJavaLibraryType; import org.jetbrains.jps.model.library.JpsLibrary; import org.jetbrains.jps.model.library.JpsOrderRootType; @@ -596,15 +597,13 @@ final class BuildSession implements Runnable, CanceledStatus { Collection artifactNames, Collection paths) throws Exception { final Timestamps timestamps = pd.timestamps.getStorage(); - Set artifacts = new HashSet(); + Set artifacts = new HashSet(); if (artifactNames.isEmpty() && buildType == BuildType.PROJECT_REBUILD) { - artifacts.addAll(pd.project.getArtifacts().values()); + artifacts.addAll(JpsArtifactService.getInstance().getArtifacts(pd.jpsProject)); } else { - final Map artifactMap = pd.project.getArtifacts(); - for (String name : artifactNames) { - final Artifact artifact = artifactMap.get(name); - if (artifact != null && !StringUtil.isEmpty(artifact.getOutputPath())) { + for (JpsArtifact artifact : JpsArtifactService.getInstance().getArtifacts(pd.jpsProject)) { + if (artifactNames.contains(artifact.getName()) && !StringUtil.isEmpty(artifact.getOutputPath())) { artifacts.add(artifact); } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/AllProjectScope.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/AllProjectScope.java index 2262090321dc..2506a5b293e8 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/AllProjectScope.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/AllProjectScope.java @@ -2,8 +2,8 @@ package org.jetbrains.jps.incremental; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.Project; -import org.jetbrains.jps.artifacts.Artifact; import org.jetbrains.jps.model.JpsProject; +import org.jetbrains.jps.model.artifact.JpsArtifact; import java.io.File; import java.util.Set; @@ -16,7 +16,7 @@ public class AllProjectScope extends CompileScope { private final boolean myIsForcedCompilation; - public AllProjectScope(Project project, JpsProject jpsProject, Set artifacts, boolean forcedCompilation) { + public AllProjectScope(Project project, JpsProject jpsProject, Set artifacts, boolean forcedCompilation) { super(project, jpsProject, artifacts); myIsForcedCompilation = forcedCompilation; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScope.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScope.java index a99c364b3587..f76334f75a12 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScope.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScope.java @@ -3,8 +3,8 @@ package org.jetbrains.jps.incremental; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.ModuleChunk; import org.jetbrains.jps.Project; -import org.jetbrains.jps.artifacts.Artifact; import org.jetbrains.jps.model.JpsProject; +import org.jetbrains.jps.model.artifact.JpsArtifact; import org.jetbrains.jps.model.module.JpsModule; import java.io.File; @@ -18,15 +18,15 @@ public abstract class CompileScope { @NotNull private final Project myProject; private final JpsProject myJpsProject; - private final Set myArtifacts; + private final Set myArtifacts; - protected CompileScope(@NotNull Project project, JpsProject jpsProject, Set artifacts) { + protected CompileScope(@NotNull Project project, JpsProject jpsProject, Set artifacts) { myProject = project; myJpsProject = jpsProject; myArtifacts = artifacts; } - public boolean isAffected(Artifact artifact) { + public boolean isAffected(JpsArtifact artifact) { return myArtifacts.contains(artifact); } @@ -45,7 +45,7 @@ public abstract class CompileScope { return false; } - public Set getArtifacts() { + public Set getArtifacts() { return myArtifacts; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModulesAndFilesScope.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModulesAndFilesScope.java index e3bebc8de50b..f46be3c90a17 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModulesAndFilesScope.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModulesAndFilesScope.java @@ -2,8 +2,8 @@ package org.jetbrains.jps.incremental; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.Project; -import org.jetbrains.jps.artifacts.Artifact; import org.jetbrains.jps.model.JpsProject; +import org.jetbrains.jps.model.artifact.JpsArtifact; import org.jetbrains.jps.model.module.JpsModule; import java.io.File; @@ -23,7 +23,7 @@ public class ModulesAndFilesScope extends CompileScope { private final boolean myForcedCompilation; public ModulesAndFilesScope(Project project, JpsProject jpsProject, Collection modules, Map> files, - Set artifacts, boolean isForcedCompilation) { + Set artifacts, boolean isForcedCompilation) { super(project, jpsProject, artifacts); myFiles = files; myForcedCompilation = isForcedCompilation; diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModulesScope.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModulesScope.java index e9dac3d97f5b..b00ec3522bdf 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModulesScope.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModulesScope.java @@ -2,8 +2,8 @@ package org.jetbrains.jps.incremental; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.Project; -import org.jetbrains.jps.artifacts.Artifact; import org.jetbrains.jps.model.JpsProject; +import org.jetbrains.jps.model.artifact.JpsArtifact; import org.jetbrains.jps.model.module.JpsModule; import java.io.File; @@ -19,7 +19,7 @@ public class ModulesScope extends CompileScope { private final Set myModules; private final boolean myForcedCompilation; - public ModulesScope(Project project, JpsProject jpsProject, Set modules, Set artifacts, boolean isForcedCompilation) { + public ModulesScope(Project project, JpsProject jpsProject, Set modules, Set artifacts, boolean isForcedCompilation) { super(project, jpsProject, artifacts); myModules = new HashSet(); for (JpsModule module : modules) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactSourceFilesState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactSourceFilesState.java index 16b97cee32cf..16424cd10169 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactSourceFilesState.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactSourceFilesState.java @@ -6,8 +6,6 @@ import com.intellij.util.containers.IntArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.Project; import org.jetbrains.jps.ProjectPaths; -import org.jetbrains.jps.artifacts.Artifact; -import org.jetbrains.jps.artifacts.LayoutElement; import org.jetbrains.jps.incremental.ModuleRootsIndex; import org.jetbrains.jps.incremental.artifacts.builders.LayoutElementBuildersRegistry; import org.jetbrains.jps.incremental.artifacts.instructions.*; @@ -15,6 +13,8 @@ import org.jetbrains.jps.incremental.storage.BuildDataManager; import org.jetbrains.jps.incremental.storage.CompositeStorageOwner; import org.jetbrains.jps.incremental.storage.StorageOwner; import org.jetbrains.jps.model.JpsModel; +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement; import java.io.File; import java.io.IOException; @@ -25,7 +25,7 @@ import java.util.*; */ public class ArtifactSourceFilesState extends CompositeStorageOwner { private final Project myProject; - private final Artifact myArtifact; + private final JpsArtifact myArtifact; private final int myArtifactId; private final JpsModel myModel; private final ModuleRootsIndex myRootsIndex; @@ -38,7 +38,7 @@ public class ArtifactSourceFilesState extends CompositeStorageOwner { private final File mySrcOutMappingsFile; private File myOutSrcMappingsFile; - public ArtifactSourceFilesState(Artifact artifact, int artifactId, Project project, + public ArtifactSourceFilesState(JpsArtifact artifact, int artifactId, Project project, JpsModel model, ModuleRootsIndex rootsIndex, ArtifactSourceTimestampStorage timestampStorage, File mappingsDir) { @@ -147,7 +147,7 @@ public class ArtifactSourceFilesState extends CompositeStorageOwner { } private ArtifactInstructionsBuilder computeInstructions() { - final LayoutElement rootElement = myArtifact.getRootElement(); + final JpsCompositePackagingElement rootElement = myArtifact.getRootElement(); ArtifactInstructionsBuilderContext context = new ArtifactInstructionsBuilderContextImpl(myProject, myModel, myRootsIndex, new ProjectPaths(myModel.getProject())); final ArtifactInstructionsBuilderImpl instructionsBuilder = new ArtifactInstructionsBuilderImpl(myRootsIndex, myProject.getIgnoredFilePatterns()); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactsBuildData.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactsBuildData.java index b86f841ac7ff..a9fbbab4efe0 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactsBuildData.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactsBuildData.java @@ -3,11 +3,11 @@ package org.jetbrains.jps.incremental.artifacts; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.jps.Project; -import org.jetbrains.jps.artifacts.Artifact; import org.jetbrains.jps.incremental.ModuleRootsIndex; import org.jetbrains.jps.incremental.storage.CompositeStorageOwner; import org.jetbrains.jps.incremental.storage.StorageOwner; import org.jetbrains.jps.model.JpsModel; +import org.jetbrains.jps.model.artifact.JpsArtifact; import java.io.File; import java.io.IOException; @@ -19,14 +19,14 @@ import java.util.Map; * @author nik */ public class ArtifactsBuildData extends CompositeStorageOwner { - private Map myArtifactState; + private Map myArtifactState; private final ArtifactSourceTimestampStorage myTimestampStorage; private ArtifactCompilerPersistentData myPersistentData; private final File myMappingsDir; public ArtifactsBuildData(File artifactsDataDir) throws IOException { myTimestampStorage = new ArtifactSourceTimestampStorage(new File(artifactsDataDir, "timestamps")); - myArtifactState = new HashMap(); + myArtifactState = new HashMap(); myPersistentData = new ArtifactCompilerPersistentData(artifactsDataDir); myMappingsDir = new File(artifactsDataDir, "mappings"); if (myPersistentData.isVersionChanged()) { @@ -36,7 +36,7 @@ public class ArtifactsBuildData extends CompositeStorageOwner { } } - public ArtifactSourceFilesState getOrCreateState(Artifact artifact, Project project, JpsModel model, ModuleRootsIndex index) { + public ArtifactSourceFilesState getOrCreateState(JpsArtifact artifact, Project project, JpsModel model, ModuleRootsIndex index) { ArtifactSourceFilesState state = myArtifactState.get(artifact); if (state == null) { final int artifactId = myPersistentData.getId(artifact.getName()); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java index b818ddf0136b..19023797f523 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java @@ -6,7 +6,6 @@ import com.intellij.util.containers.IntArrayList; import com.intellij.util.containers.MultiMap; import gnu.trove.THashSet; import gnu.trove.TIntObjectHashMap; -import org.jetbrains.jps.artifacts.Artifact; import org.jetbrains.jps.cmdline.ProjectDescriptor; import org.jetbrains.jps.incremental.CompileContext; import org.jetbrains.jps.incremental.ProjectBuildException; @@ -18,6 +17,8 @@ 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.incremental.messages.UptoDateFilesSavedEvent; +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.artifact.JpsArtifactService; import java.io.File; import java.io.IOException; @@ -35,32 +36,27 @@ public class IncArtifactBuilder extends ProjectLevelBuilder { @Override public void build(CompileContext context) throws ProjectBuildException { - Set affected = new HashSet(); - for (Artifact artifact : context.getProjectDescriptor().project.getArtifacts().values()) { + Set affected = new HashSet(); + for (JpsArtifact artifact : JpsArtifactService.getInstance().getArtifacts(context.getProjectDescriptor().jpsProject)) { if (context.getScope().isAffected(artifact)) { affected.add(artifact); } } - final Set toBuild = ArtifactSorter.addIncludedArtifacts(affected, context.getProjectDescriptor().project, context.getProjectDescriptor().jpsModel); - Map artifactsMap = new HashMap(); - for (Artifact artifact : toBuild) { - artifactsMap.put(artifact.getName(), artifact); - } + final Set toBuild = ArtifactSorter.addIncludedArtifacts(affected, context.getProjectDescriptor().project, context.getProjectDescriptor().jpsModel); - final ArtifactSorter sorter = new ArtifactSorter(context.getProjectDescriptor().project, context.getProjectDescriptor().jpsModel); - final Map selfIncludingNameMap = sorter.getArtifactToSelfIncludingNameMap(); - for (String artifactName : sorter.getArtifactsSortedByInclusion()) { + final ArtifactSorter sorter = new ArtifactSorter(context.getProjectDescriptor().jpsModel); + final Map selfIncludingNameMap = sorter.getArtifactToSelfIncludingNameMap(); + for (JpsArtifact artifact : sorter.getArtifactsSortedByInclusion()) { context.checkCanceled(); - final Artifact artifact = artifactsMap.get(artifactName); - if (artifact != null) { - final String selfIncluding = selfIncludingNameMap.get(artifactName); + if (toBuild.contains(artifact)) { + final JpsArtifact selfIncluding = selfIncludingNameMap.get(artifact); if (selfIncluding != null) { - String name = selfIncluding.equals(artifact.getName()) ? "it" : "'" + selfIncluding + "' artifact"; - context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Cannot build '" + artifactName + "' artifact: " + name + " includes itself in the output layout")); + String name = selfIncluding.equals(artifact) ? "it" : "'" + selfIncluding.getName() + "' artifact"; + context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Cannot build '" + artifact.getName() + "' artifact: " + name + " includes itself in the output layout")); break; } if (StringUtil.isEmpty(artifact.getOutputPath())) { - context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Cannot build '" + artifactName + "' artifact: output path is not specified")); + context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Cannot build '" + artifact.getName() + "' artifact: output path is not specified")); break; } buildArtifact(artifact, context); @@ -68,7 +64,7 @@ public class IncArtifactBuilder extends ProjectLevelBuilder { } } - private static void buildArtifact(Artifact artifact, final CompileContext context) throws ProjectBuildException { + private static void buildArtifact(JpsArtifact artifact, final CompileContext context) throws ProjectBuildException { final ProjectDescriptor pd = context.getProjectDescriptor(); try { final ArtifactSourceFilesState state = pd.dataManager.getArtifactsBuildData().getOrCreateState(artifact, pd.project, pd.jpsModel, pd.rootsIndex); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuilderService.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuilderService.java index 2fd66a13b354..df1322c2b2ad 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuilderService.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuilderService.java @@ -1,13 +1,13 @@ package org.jetbrains.jps.incremental.artifacts.builders; -import org.jetbrains.jps.artifacts.LayoutElement; import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactCompilerInstructionCreator; import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactInstructionsBuilderContext; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; /** * @author nik */ -public abstract class LayoutElementBuilderService { +public abstract class LayoutElementBuilderService { private final Class myElementClass; protected LayoutElementBuilderService(Class elementClass) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java index ed042641aa4a..c06efc0be481 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java @@ -4,11 +4,14 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ClassMap; -import org.jetbrains.jps.artifacts.*; +import org.jetbrains.jps.JpsPathUtil; import org.jetbrains.jps.idea.OwnServiceLoader; import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactCompilerInstructionCreator; import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactInstructionsBuilderContext; -import org.jetbrains.jps.model.module.JpsModule; +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.artifact.elements.*; +import org.jetbrains.jps.model.java.JpsProductionModuleOutputPackagingElement; +import org.jetbrains.jps.model.java.JpsTestModuleOutputPackagingElement; import java.io.File; import java.util.List; @@ -44,94 +47,90 @@ public class LayoutElementBuildersRegistry { } } - public void generateInstructions(LayoutElement layoutElement, ArtifactCompilerInstructionCreator instructionCreator, + public void generateInstructions(JpsPackagingElement layoutElement, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { final LayoutElementBuilderService builder = myBuilders.get(layoutElement.getClass()); - if (builder == null) { + if (builder != null) { + //noinspection unchecked + builder.generateInstructions(layoutElement, instructionCreator, builderContext); + } + else { LOG.error("Builder not found for artifact output layout element of class " + layoutElement.getClass()); } - builder.generateInstructions(layoutElement, instructionCreator, builderContext); } - private void generateChildrenInstructions(CompositeLayoutElement element, ArtifactCompilerInstructionCreator instructionCreator, + private void generateChildrenInstructions(JpsCompositePackagingElement element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { generateInstructions(element.getChildren(), instructionCreator, builderContext); } - private void generateSubstitutionInstructions(ComplexLayoutElement element, + private void generateSubstitutionInstructions(JpsComplexPackagingElement element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { - final List substitution = element.getSubstitution(builderContext.getProject(), builderContext.getJpsModel()); + final List substitution = element.getSubstitution(); if (substitution != null) { generateInstructions(substitution, instructionCreator, builderContext); } } - private void generateInstructions(final List elements, ArtifactCompilerInstructionCreator instructionCreator, + private void generateInstructions(final List elements, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { - for (LayoutElement child : elements) { + for (JpsPackagingElement child : elements) { generateInstructions(child, instructionCreator, builderContext); } } - private static void generateModuleOutputInstructions(String moduleName, - boolean tests, - ArtifactCompilerInstructionCreator creator, - ArtifactInstructionsBuilderContext context) { - final JpsModule module = context.getRootsIndex().getModuleByName(moduleName); - if (module != null) { - final File outputDir = context.getProjectPaths().getModuleOutputDir(module, tests); - if (outputDir != null) { - creator.addDirectoryCopyInstructions(outputDir); - } + private static void generateModuleOutputInstructions(String outputUrl, ArtifactCompilerInstructionCreator creator) { + if (outputUrl != null) { + creator.addDirectoryCopyInstructions(JpsPathUtil.urlToFile(outputUrl)); } } - private class RootElementBuilder extends LayoutElementBuilderService { + private class RootElementBuilder extends LayoutElementBuilderService { public RootElementBuilder() { - super(RootElement.class); + super(JpsArtifactRootElement.class); } @Override - public void generateInstructions(RootElement element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { + public void generateInstructions(JpsArtifactRootElement element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { generateChildrenInstructions(element, instructionCreator, builderContext); } } - private class DirectoryElementBuilder extends LayoutElementBuilderService { + private class DirectoryElementBuilder extends LayoutElementBuilderService { public DirectoryElementBuilder() { - super(DirectoryElement.class); + super(JpsDirectoryPackagingElement.class); } @Override - public void generateInstructions(DirectoryElement element, + public void generateInstructions(JpsDirectoryPackagingElement element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { - generateChildrenInstructions(element, instructionCreator.subFolder(element.getName()), builderContext); + generateChildrenInstructions(element, instructionCreator.subFolder(element.getDirectoryName()), builderContext); } } - private class ArchiveElementBuilder extends LayoutElementBuilderService { + private class ArchiveElementBuilder extends LayoutElementBuilderService { public ArchiveElementBuilder() { - super(ArchiveElement.class); + super(JpsArchivePackagingElement.class); } @Override - public void generateInstructions(ArchiveElement element, ArtifactCompilerInstructionCreator instructionCreator, + public void generateInstructions(JpsArchivePackagingElement element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { - generateChildrenInstructions(element, instructionCreator.archive(element.getName()), builderContext); + generateChildrenInstructions(element, instructionCreator.archive(element.getArchiveName()), builderContext); } } - private static class DirectoryCopyElementBuilder extends LayoutElementBuilderService { + private static class DirectoryCopyElementBuilder extends LayoutElementBuilderService { public DirectoryCopyElementBuilder() { - super(DirectoryCopyElement.class); + super(JpsDirectoryCopyPackagingElement.class); } @Override - public void generateInstructions(DirectoryCopyElement element, ArtifactCompilerInstructionCreator instructionCreator, + public void generateInstructions(JpsDirectoryCopyPackagingElement element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { - final String dirPath = element.getDirPath(); + final String dirPath = element.getDirectoryPath(); if (dirPath != null) { final File directory = new File(FileUtil.toSystemDependentName(dirPath)); if (directory.isDirectory()) { @@ -141,35 +140,35 @@ public class LayoutElementBuildersRegistry { } } - private static class FileCopyElementBuilder extends LayoutElementBuilderService { + private static class FileCopyElementBuilder extends LayoutElementBuilderService { public FileCopyElementBuilder() { - super(FileCopyElement.class); + super(JpsFileCopyPackagingElement.class); } @Override - public void generateInstructions(FileCopyElement element, ArtifactCompilerInstructionCreator instructionCreator, + public void generateInstructions(JpsFileCopyPackagingElement element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { final String filePath = element.getFilePath(); if (filePath != null) { final File file = new File(FileUtil.toSystemDependentName(filePath)); if (file.isFile()) { - final String fileName = element.getOutputFileName(); + final String fileName = element.getRenamedOutputFileName(); instructionCreator.addFileCopyInstruction(file, fileName != null ? fileName : file.getName()); } } } } - private static class ExtractedDirectoryElementBuilder extends LayoutElementBuilderService { + private static class ExtractedDirectoryElementBuilder extends LayoutElementBuilderService { public ExtractedDirectoryElementBuilder() { - super(ExtractedDirectoryElement.class); + super(JpsExtractedDirectoryPackagingElement.class); } @Override - public void generateInstructions(ExtractedDirectoryElement element, + public void generateInstructions(JpsExtractedDirectoryPackagingElement element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { - final String jarPath = element.getJarPath(); + final String jarPath = element.getFilePath(); final String pathInJar = element.getPathInJar(); File jarFile = new File(FileUtil.toSystemDependentName(jarPath)); if (jarFile.isFile()) { @@ -178,55 +177,55 @@ public class LayoutElementBuildersRegistry { } } - private static class ModuleOutputElementBuilder extends LayoutElementBuilderService { + private static class ModuleOutputElementBuilder extends LayoutElementBuilderService { public ModuleOutputElementBuilder() { - super(ModuleOutputElement.class); + super(JpsProductionModuleOutputPackagingElement.class); } @Override - public void generateInstructions(ModuleOutputElement element, + public void generateInstructions(JpsProductionModuleOutputPackagingElement element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { - generateModuleOutputInstructions(element.getModuleName(), false, instructionCreator, builderContext); + generateModuleOutputInstructions(element.getOutputUrl(), instructionCreator); } } - private static class ModuleTestOutputElementBuilder extends LayoutElementBuilderService { + private static class ModuleTestOutputElementBuilder extends LayoutElementBuilderService { public ModuleTestOutputElementBuilder() { - super(ModuleTestOutputElement.class); + super(JpsTestModuleOutputPackagingElement.class); } @Override - public void generateInstructions(ModuleTestOutputElement element, + public void generateInstructions(JpsTestModuleOutputPackagingElement element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { - generateModuleOutputInstructions(element.getModuleName(), true, instructionCreator, builderContext); + generateModuleOutputInstructions(element.getOutputUrl(), instructionCreator); } } - private class ComplexElementBuilder extends LayoutElementBuilderService { + private class ComplexElementBuilder extends LayoutElementBuilderService { public ComplexElementBuilder() { - super(ComplexLayoutElement.class); + super(JpsComplexPackagingElement.class); } @Override - public void generateInstructions(ComplexLayoutElement element, + public void generateInstructions(JpsComplexPackagingElement element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { generateSubstitutionInstructions(element, instructionCreator, builderContext); } } - private class ArtifactOutputElementBuilder extends LayoutElementBuilderService { + private class ArtifactOutputElementBuilder extends LayoutElementBuilderService { public ArtifactOutputElementBuilder() { - super(ArtifactLayoutElement.class); + super(JpsArtifactOutputPackagingElement.class); } @Override - public void generateInstructions(ArtifactLayoutElement element, + public void generateInstructions(JpsArtifactOutputPackagingElement element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { - final Artifact artifact = element.findArtifact(builderContext.getProject()); + final JpsArtifact artifact = element.getArtifactReference().resolve(); if (artifact == null) return; final String outputPath = artifact.getOutputPath(); @@ -235,10 +234,10 @@ public class LayoutElementBuildersRegistry { return; } - final LayoutElement rootElement = artifact.getRootElement(); + final JpsPackagingElement rootElement = artifact.getRootElement(); final File outputDir = new File(FileUtil.toSystemDependentName(outputPath)); - if (rootElement instanceof ArchiveElement) { - final String fileName = ((ArchiveElement)rootElement).getName(); + if (rootElement instanceof JpsArchivePackagingElement) { + final String fileName = ((JpsArchivePackagingElement)rootElement).getArchiveName(); instructionCreator.addFileCopyInstruction(new File(outputDir, fileName), fileName); } else { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/ArtifactSorter.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/ArtifactSorter.java index c77409c13760..c532a31df839 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/ArtifactSorter.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/ArtifactSorter.java @@ -17,18 +17,20 @@ package org.jetbrains.jps.incremental.artifacts.impl; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Consumer; +import com.intellij.util.Processor; import com.intellij.util.graph.CachingSemiGraph; import com.intellij.util.graph.DFSTBuilder; import com.intellij.util.graph.GraphGenerator; import gnu.trove.TIntArrayList; import gnu.trove.TIntProcedure; -import groovy.lang.Closure; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.Project; -import org.jetbrains.jps.artifacts.Artifact; -import org.jetbrains.jps.artifacts.ArtifactLayoutElement; -import org.jetbrains.jps.artifacts.ComplexLayoutElement; import org.jetbrains.jps.model.JpsModel; +import org.jetbrains.jps.model.JpsProject; +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.artifact.JpsArtifactService; +import org.jetbrains.jps.model.artifact.elements.JpsArtifactOutputPackagingElement; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; import java.util.*; @@ -36,55 +38,53 @@ import java.util.*; * @author nik */ public class ArtifactSorter { - private final Project myProject; private final JpsModel myModel; - private Map myArtifactToSelfIncludingName; - private List mySortedArtifacts; + private Map myArtifactToSelfIncludingName; + private List mySortedArtifacts; - public ArtifactSorter(Project project, JpsModel model) { - myProject = project; + public ArtifactSorter(JpsModel model) { myModel = model; } - public Map getArtifactToSelfIncludingNameMap() { + public Map getArtifactToSelfIncludingNameMap() { if (myArtifactToSelfIncludingName == null) { myArtifactToSelfIncludingName = computeArtifactToSelfIncludingNameMap(); } return myArtifactToSelfIncludingName; } - public List getArtifactsSortedByInclusion() { + public List getArtifactsSortedByInclusion() { if (mySortedArtifacts == null) { mySortedArtifacts = doGetSortedArtifacts(); } return mySortedArtifacts; } - private List doGetSortedArtifacts() { - GraphGenerator graph = createArtifactsGraph(); - DFSTBuilder builder = new DFSTBuilder(graph); + private List doGetSortedArtifacts() { + GraphGenerator graph = createArtifactsGraph(); + DFSTBuilder builder = new DFSTBuilder(graph); builder.buildDFST(); - List names = new ArrayList(); + List names = new ArrayList(); names.addAll(graph.getNodes()); Collections.sort(names, builder.comparator()); return names; } - private Map computeArtifactToSelfIncludingNameMap() { - final Map result = new HashMap(); - final GraphGenerator graph = createArtifactsGraph(); - for (String artifactName : graph.getNodes()) { - final Iterator in = graph.getIn(artifactName); + private Map computeArtifactToSelfIncludingNameMap() { + final Map result = new HashMap(); + final GraphGenerator graph = createArtifactsGraph(); + for (JpsArtifact artifact : graph.getNodes()) { + final Iterator in = graph.getIn(artifact); while (in.hasNext()) { - String next = in.next(); - if (next.equals(artifactName)) { - result.put(artifactName, artifactName); + JpsArtifact next = in.next(); + if (next.equals(artifact)) { + result.put(artifact, artifact); break; } } } - final DFSTBuilder builder = new DFSTBuilder(graph); + final DFSTBuilder builder = new DFSTBuilder(graph); builder.buildDFST(); if (builder.isAcyclic() && result.isEmpty()) return Collections.emptyMap(); @@ -94,8 +94,8 @@ public class ArtifactSorter { public boolean execute(int size) { if (size > 1) { for (int j = 0; j < size; j++) { - final String artifactName = builder.getNodeByTNumber(myTNumber + j); - result.put(artifactName, artifactName); + final JpsArtifact artifact = builder.getNodeByTNumber(myTNumber + j); + result.put(artifact, artifact); } } myTNumber += size; @@ -104,13 +104,13 @@ public class ArtifactSorter { }); for (int i = 0; i < graph.getNodes().size(); i++) { - final String artifactName = builder.getNodeByTNumber(i); - if (!result.containsKey(artifactName)) { - final Iterator in = graph.getIn(artifactName); + final JpsArtifact artifact = builder.getNodeByTNumber(i); + if (!result.containsKey(artifact)) { + final Iterator in = graph.getIn(artifact); while (in.hasNext()) { - final String name = result.get(in.next()); - if (name != null) { - result.put(artifactName, name); + final JpsArtifact next = result.get(in.next()); + if (next != null) { + result.put(artifact, next); } } } @@ -120,19 +120,19 @@ public class ArtifactSorter { } @NotNull - public static Set addIncludedArtifacts(@NotNull Collection artifacts, @NotNull Project project, JpsModel model) { - Set result = new HashSet(); - for (Artifact artifact : artifacts) { - collectIncludedArtifacts(artifact, project, model, new HashSet(), result, true); + public static Set addIncludedArtifacts(@NotNull Collection artifacts, @NotNull Project project, JpsModel model) { + Set result = new HashSet(); + for (JpsArtifact artifact : artifacts) { + collectIncludedArtifacts(artifact, project, model, new HashSet(), result, true); } return result; } - private static void collectIncludedArtifacts(Artifact artifact, + private static void collectIncludedArtifacts(JpsArtifact artifact, final Project project, final JpsModel model, - final Set processed, - final Set result, + final Set processed, + final Set result, final boolean withOutputPathOnly) { if (!processed.add(artifact)) { return; @@ -141,31 +141,27 @@ public class ArtifactSorter { result.add(artifact); } - processIncludedArtifacts(artifact, project, model, new Consumer() { + processIncludedArtifacts(artifact, new Consumer() { @Override - public void consume(Artifact included) { + public void consume(JpsArtifact included) { collectIncludedArtifacts(included, project, model, processed, result, withOutputPathOnly); } }); } - private GraphGenerator createArtifactsGraph() { - return GraphGenerator.create(CachingSemiGraph.create(new ArtifactsGraph(myProject, myModel))); + private GraphGenerator createArtifactsGraph() { + return GraphGenerator.create(CachingSemiGraph.create(new ArtifactsGraph(myModel.getProject()))); } - private static void processIncludedArtifacts(Artifact artifact, - final Project project, - JpsModel model, final Consumer consumer) { - artifact.getRootElement().process(project, model, new Closure(consumer) { + private static void processIncludedArtifacts(JpsArtifact artifact, final Consumer consumer) { + JpsArtifactUtil.processPackagingElements(artifact.getRootElement(), new Processor() { @Override - public Object call(Object arguments) { - if (arguments instanceof ArtifactLayoutElement) { - final Artifact includedArtifact = ((ArtifactLayoutElement)arguments).findArtifact(project); - if (includedArtifact != null) { - consumer.consume(includedArtifact); + public boolean process(JpsPackagingElement element) { + if (element instanceof JpsArtifactOutputPackagingElement) { + JpsArtifact included = ((JpsArtifactOutputPackagingElement)element).getArtifactReference().resolve(); + if (included != null) { + consumer.consume(included); } - } - if (arguments instanceof ComplexLayoutElement) { return false; } return true; @@ -173,37 +169,30 @@ public class ArtifactSorter { }); } - private static class ArtifactsGraph implements GraphGenerator.SemiGraph { - private final Set myArtifactNames; - private final Project myProject; - private final JpsModel myModel; + private static class ArtifactsGraph implements GraphGenerator.SemiGraph { + private final Set myArtifactNodes; - public ArtifactsGraph(Project project, JpsModel model) { - myProject = project; - myModel = model; - myArtifactNames = new LinkedHashSet(project.getArtifacts().keySet()); + public ArtifactsGraph(final JpsProject project) { + myArtifactNodes = new LinkedHashSet(JpsArtifactService.getInstance().getArtifacts(project)); } @Override - public Collection getNodes() { - return myArtifactNames; + public Collection getNodes() { + return myArtifactNodes; } @Override - public Iterator getIn(String name) { - final Set included = new LinkedHashSet(); - final Artifact artifact = myProject.getArtifacts().get(name); - if (artifact != null) { - final Consumer consumer = new Consumer() { - @Override - public void consume(Artifact artifact) { - if (myArtifactNames.contains(artifact.getName())) { - included.add(artifact.getName()); - } + public Iterator getIn(JpsArtifact artifact) { + final Set included = new LinkedHashSet(); + final Consumer consumer = new Consumer() { + @Override + public void consume(JpsArtifact artifact) { + if (myArtifactNodes.contains(artifact)) { + included.add(artifact); } - }; - processIncludedArtifacts(artifact, myProject, myModel, consumer); - } + } + }; + processIncludedArtifacts(artifact, consumer); return included.iterator(); } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactUtil.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactUtil.java new file mode 100644 index 000000000000..c7a673e3b330 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JpsArtifactUtil.java @@ -0,0 +1,30 @@ +package org.jetbrains.jps.incremental.artifacts.impl; + +import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.artifact.elements.JpsComplexPackagingElement; +import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; + +/** + * @author nik + */ +public class JpsArtifactUtil { + public static boolean processPackagingElements(@NotNull JpsPackagingElement element, @NotNull Processor processor) { + if (!processor.process(element)) { + return false; + } + + if (element instanceof JpsCompositePackagingElement) { + for (JpsPackagingElement child : ((JpsCompositePackagingElement)element).getChildren()) { + processPackagingElements(child, processor); + } + } + else if (element instanceof JpsComplexPackagingElement) { + for (JpsPackagingElement child : ((JpsComplexPackagingElement)element).getSubstitution()) { + processPackagingElements(child, processor); + } + } + return true; + } +} diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java index 307966b088b6..a4812e6b3a9a 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java @@ -19,13 +19,13 @@ import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; -import org.jetbrains.jps.artifacts.Artifact; import org.jetbrains.jps.builders.JpsBuildTestCase; import org.jetbrains.jps.cmdline.ProjectDescriptor; import org.jetbrains.jps.incremental.*; import org.jetbrains.jps.incremental.artifacts.ArtifactBuilderLoggerImpl; import org.jetbrains.jps.incremental.java.JavaBuilderLogger; import org.jetbrains.jps.incremental.messages.BuildMessage; +import org.jetbrains.jps.model.artifact.JpsArtifact; import java.io.*; import java.util.Collections; @@ -182,7 +182,7 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { final ProjectDescriptor projectDescriptor = createProjectDescriptor(new BuildLoggingManager(new ArtifactBuilderLoggerImpl(), javaBuilderLogger)); try { final IncProjectBuilder builder = createBuilder(projectDescriptor); - doBuild(builder, new AllProjectScope(myProject, myJpsProject, Collections.emptySet(), true), false, false, true); + doBuild(builder, new AllProjectScope(myProject, myJpsProject, Collections.emptySet(), true), false, false, true); modify(); @@ -206,7 +206,7 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { makeBuilder.addMessageHandler(handler); - makeBuilder.build(new AllProjectScope(myProject, myJpsProject, Collections.emptySet(), false), true, false, false); + makeBuilder.build(new AllProjectScope(myProject, myJpsProject, Collections.emptySet(), false), true, false, false); final ByteArrayOutputStream makeDump = new ByteArrayOutputStream(); @@ -222,7 +222,7 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { assertEquals(expected, actual); if (!handler.myErrors) { - createBuilder(projectDescriptor).build(new AllProjectScope(myProject, myJpsProject, Collections.emptySet(), true), false, true, false); + createBuilder(projectDescriptor).build(new AllProjectScope(myProject, myJpsProject, Collections.emptySet(), true), false, true, false); final ByteArrayOutputStream rebuildDump = new ByteArrayOutputStream(); diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy index 1097b3b86675..7311a59115c1 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy @@ -1,14 +1,16 @@ package org.jetbrains.jps.builders.rebuild + import com.intellij.openapi.application.ex.PathManagerEx import com.intellij.openapi.util.io.FileUtil import com.intellij.util.io.TestFileSystemBuilder import org.jetbrains.jps.JpsPathUtil -import org.jetbrains.jps.artifacts.Artifact import org.jetbrains.jps.builders.JpsBuildTestCase import org.jetbrains.jps.incremental.AllProjectScope import org.jetbrains.jps.incremental.BuildLoggingManager import org.jetbrains.jps.incremental.artifacts.ArtifactBuilderLoggerImpl import org.jetbrains.jps.incremental.java.JavaBuilderLoggerImpl +import org.jetbrains.jps.model.artifact.JpsArtifact +import org.jetbrains.jps.model.artifact.JpsArtifactService import org.jetbrains.jps.model.java.JpsJavaExtensionService /** * @author nik @@ -49,7 +51,7 @@ abstract class JpsRebuildTestCase extends JpsBuildTestCase { JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myJpsProject).outputUrl = JpsPathUtil.pathToUrl(FileUtil.toSystemIndependentName(getOrCreateOutputDirectory().getAbsolutePath())) def descriptor = createProjectDescriptor(new BuildLoggingManager(new ArtifactBuilderLoggerImpl(), new JavaBuilderLoggerImpl())) try { - def scope = new AllProjectScope(myProject, myJpsProject, new HashSet(myProject.artifacts.values()), true) + def scope = new AllProjectScope(myProject, myJpsProject, new HashSet(JpsArtifactService.getInstance().getArtifacts(myJpsProject)), true) doBuild(createBuilder(descriptor), scope, false, false, true) } finally { diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java index 3476ed99b815..69e973f9ddfc 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java @@ -1,6 +1,6 @@ package org.jetbrains.jps.incremental.artifacts; -import org.jetbrains.jps.artifacts.Artifact; +import org.jetbrains.jps.model.artifact.JpsArtifact; import static com.intellij.util.io.TestFileSystemBuilder.fs; import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.archive; @@ -13,7 +13,7 @@ public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase { public void testOverwriteArchives() { final String aFile = createFile("aaa.txt", "a"); final String bFile = createFile("bbb.txt", "b"); - final Artifact a = addArtifact( + final JpsArtifact a = addArtifact( root() .archive("x.jar").fileCopy(aFile).end() .archive("x.jar") @@ -41,7 +41,7 @@ public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase { public void testOverwriteNestedArchive() { final String cFile = createFile("c.txt", "c"); final String eFile = createFile("e.txt", "e"); - final Artifact a = addArtifact( + final JpsArtifact a = addArtifact( root() .archive("a.jar").archive("b.jar").fileCopy(cFile).end().end() .archive("a.jar").archive("d.jar").fileCopy(eFile)); @@ -65,7 +65,7 @@ public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase { public void testOverwriteFileByArchive() { final String xFile = createFile("x.txt", "1"); final String jarFile = createFile("junit.jar", "123"); - Artifact a = addArtifact(root() + JpsArtifact a = addArtifact(root() .archive("junit.jar").fileCopy(xFile).end() .fileCopy(jarFile)); buildAll(); @@ -88,7 +88,7 @@ public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase { public void testOverwriteArchiveByFile() { final String xFile = createFile("x.txt", "1"); final String jarFile = createFile("jdom.jar", "123"); - Artifact a = addArtifact(root() + JpsArtifact a = addArtifact(root() .fileCopy(jarFile) .archive("jdom.jar").fileCopy(xFile)); buildAll(); @@ -112,7 +112,7 @@ public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase { final String firstFile = createFile("d1/xxx.txt", "first"); final String secondFile = createFile("d2/xxx.txt", "second"); final String fooFile = createFile("d3/xxx.txt", "foo"); - final Artifact a = addArtifact( + final JpsArtifact a = addArtifact( root().dir("ddd") .fileCopy(firstFile) .fileCopy(fooFile) @@ -144,7 +144,7 @@ public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase { public void testDeleteOverwritingFiles() { final String firstFile = createFile("d1/xxx.txt", "1"); final String secondFile = createFile("d2/xxx.txt", "2"); - final Artifact a = addArtifact("a", + final JpsArtifact a = addArtifact("a", root().dir("ddd").fileCopy(firstFile).fileCopy(secondFile).fileCopy(createFile("y.txt")) ); buildAll(); @@ -165,7 +165,7 @@ public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase { public void testUpdateManifest() { final String manifestText1 = "Manifest-Version: 1.0\r\nMain-Class: A\r\n\r\n"; final String manifest = createFile("MANIFEST.MF", manifestText1); - final Artifact a = addArtifact("a", archive("a.jar").dir("META-INF").fileCopy(manifest).fileCopy(createFile("a.txt"))); + final JpsArtifact a = addArtifact("a", archive("a.jar").dir("META-INF").fileCopy(manifest).fileCopy(createFile("a.txt"))); buildAll(); assertOutput(a, fs().archive("a.jar").dir("META-INF").file("MANIFEST.MF", manifestText1).file("a.txt")); diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.java index 6364fda6b6ac..5bfa32ae11c1 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.java @@ -3,7 +3,7 @@ package org.jetbrains.jps.incremental.artifacts; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.PathUtil; import org.jetbrains.jps.JpsPathUtil; -import org.jetbrains.jps.artifacts.Artifact; +import org.jetbrains.jps.model.artifact.JpsArtifact; import org.jetbrains.jps.model.library.JpsLibrary; import org.jetbrains.jps.model.module.JpsModule; @@ -22,13 +22,13 @@ import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.root */ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { public void testFileCopy() { - final Artifact a = addArtifact(root().fileCopy(createFile("file.txt", "foo"))); + final JpsArtifact a = addArtifact(root().fileCopy(createFile("file.txt", "foo"))); buildAll(); assertOutput(a, fs().file("file.txt", "foo")); } public void testDir() { - final Artifact a = addArtifact( + final JpsArtifact a = addArtifact( root() .fileCopy(createFile("abc.txt")) .dir("dir") @@ -43,7 +43,7 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { } public void testArchive() { - final Artifact a = addArtifact( + final JpsArtifact a = addArtifact( root() .archive("xxx.zip") .fileCopy(createFile("X.class", "data")) @@ -62,7 +62,7 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { public void testTwoDirsInArchive() { final String dir1 = PathUtil.getParentPath(PathUtil.getParentPath(createFile("dir1/a/x.txt"))); final String dir2 = PathUtil.getParentPath(PathUtil.getParentPath(createFile("dir2/a/y.txt"))); - final Artifact a = addArtifact( + final JpsArtifact a = addArtifact( root() .archive("a.jar") .dirCopy(dir1) @@ -80,7 +80,7 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { } public void testArchiveInArchive() { - final Artifact a = addArtifact( + final JpsArtifact a = addArtifact( root() .archive("a.jar") .archive("b.jar") @@ -95,10 +95,10 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { } public void testIncludedArtifact() { - final Artifact included = addArtifact("included", + final JpsArtifact included = addArtifact("included", root() .fileCopy(createFile("aaa.txt"))); - final Artifact a = addArtifact( + final JpsArtifact a = addArtifact( root() .dir("dir") .artifact(included) @@ -117,9 +117,9 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { } public void testMergeDirectories() { - final Artifact included = addArtifact("included", + final JpsArtifact included = addArtifact("included", root().dir("dir").fileCopy(createFile("aaa.class"))); - final Artifact a = addArtifact( + final JpsArtifact a = addArtifact( root() .artifact(included) .dir("dir") @@ -134,7 +134,7 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { public void testCopyLibrary() { final JpsLibrary library = addProjectLibrary("lib", getJUnitJarPath()); - final Artifact a = addArtifact(root().lib(library)); + final JpsArtifact a = addArtifact(root().lib(library)); buildAll(); assertOutput(a, fs().file("junit.jar")); } @@ -142,7 +142,7 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { public void testModuleOutput() { final String file = createFile("src/A.java", "public class A {}"); final JpsModule module = addModule("a", PathUtil.getParentPath(file)); - final Artifact artifact = addArtifact(root().module(module)); + final JpsArtifact artifact = addArtifact(root().module(module)); buildArtifacts(artifact); assertOutput(artifact, fs().file("A.class")); @@ -151,7 +151,7 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { public void testIgnoredFile() { final String file = createFile("a/.svn/a.txt"); createFile("a/svn/b.txt"); - final Artifact a = addArtifact(root().dirCopy(PathUtil.getParentPath(PathUtil.getParentPath(file)))); + final JpsArtifact a = addArtifact(root().dirCopy(PathUtil.getParentPath(PathUtil.getParentPath(file)))); buildAll(); assertOutput(a, fs().dir("svn").file("b.txt")); } @@ -159,7 +159,7 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { public void testIgnoredFileInArchive() { final String file = createFile("a/.svn/a.txt"); createFile("a/svn/b.txt"); - final Artifact a = addArtifact(archive("a.jar").dirCopy(PathUtil.getParentPath(PathUtil.getParentPath(file)))); + final JpsArtifact a = addArtifact(archive("a.jar").dirCopy(PathUtil.getParentPath(PathUtil.getParentPath(file)))); buildAll(); assertOutput(a, fs().archive("a.jar").dir("svn").file("b.txt")); } @@ -175,7 +175,7 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { module.getContentRootsList().addUrl(JpsPathUtil.pathToUrl(dir)); module.getExcludeRootsList().addUrl(JpsPathUtil.pathToUrl(excluded)); - final Artifact a = addArtifact(root().dirCopy(excluded)); + final JpsArtifact a = addArtifact(root().dirCopy(excluded)); buildAll(); assertOutput(a, fs().file("a.txt")); } @@ -191,13 +191,13 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { module.getContentRootsList().addUrl(JpsPathUtil.pathToUrl(dir)); module.getExcludeRootsList().addUrl(JpsPathUtil.pathToUrl(PathUtil.getParentPath(file))); - final Artifact a = addArtifact(root().dirCopy(dir)); + final JpsArtifact a = addArtifact(root().dirCopy(dir)); buildAll(); assertOutput(a, fs().file("b.txt")); } public void testExtractDirectory() { - final Artifact a = addArtifact("a", root().dir("dir").extractedDir(getJUnitJarPath(), "/junit/textui/")); + final JpsArtifact a = addArtifact("a", root().dir("dir").extractedDir(getJUnitJarPath(), "/junit/textui/")); buildAll(); assertOutput(a, fs().dir("dir") .file("ResultPrinter.class") @@ -205,7 +205,7 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { } public void testPackExtractedDirectory() { - final Artifact a = addArtifact("a", root().archive("a.jar").extractedDir(getJUnitJarPath(), "/junit/textui/")); + final JpsArtifact a = addArtifact("a", root().archive("a.jar").extractedDir(getJUnitJarPath(), "/junit/textui/")); buildAll(); assertOutput(a, fs().archive("a.jar") .file("ResultPrinter.class") @@ -213,14 +213,14 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { } public void testSelfIncludingArtifact() { - final Artifact a = addArtifact("a", root()); + final JpsArtifact a = addArtifact("a", root()); LayoutElementTestUtil.addArtifactToLayout(a, a); assertBuildFailed(a); } public void testCircularInclusion() { - final Artifact a = addArtifact("a", root()); - final Artifact b = addArtifact("b", root()); + final JpsArtifact a = addArtifact("a", root()); + final JpsArtifact b = addArtifact("b", root()); LayoutElementTestUtil.addArtifactToLayout(a, b); LayoutElementTestUtil.addArtifactToLayout(b, a); assertBuildFailed(a); @@ -228,10 +228,10 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { } public void testArtifactContainingSelfIncludingArtifact() { - Artifact c = addArtifact("c", root()); - final Artifact a = addArtifact("a", root().artifact(c)); + JpsArtifact c = addArtifact("c", root()); + final JpsArtifact a = addArtifact("a", root().artifact(c)); LayoutElementTestUtil.addArtifactToLayout(a, a); - final Artifact b = addArtifact("b", root().artifact(a)); + final JpsArtifact b = addArtifact("b", root().artifact(a)); buildArtifacts(c); assertBuildFailed(b); @@ -243,7 +243,7 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { final String firstFile = createFile("src/A.txt"); final String manifestFile = createFile("src/MANIFEST.MF"); final String lastFile = createFile("src/Z.txt"); - final Artifact a = addArtifact(archive("a.jar").dir("META-INF") + final JpsArtifact a = addArtifact(archive("a.jar").dir("META-INF") .fileCopy(firstFile).fileCopy(manifestFile).fileCopy(lastFile)); buildArtifacts(a); final String jarPath = a.getOutputPath() + "/a.jar"; diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java index bb56fcaba8bf..4128284bfae2 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java @@ -21,7 +21,6 @@ import com.intellij.util.io.TestFileSystemBuilder; import com.intellij.util.text.UniqueNameGenerator; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.JpsPathUtil; -import org.jetbrains.jps.artifacts.Artifact; import org.jetbrains.jps.builders.JpsBuildTestCase; import org.jetbrains.jps.cmdline.ProjectDescriptor; import org.jetbrains.jps.incremental.AllProjectScope; @@ -29,6 +28,9 @@ import org.jetbrains.jps.incremental.BuildLoggingManager; import org.jetbrains.jps.incremental.CompileScope; import org.jetbrains.jps.incremental.IncProjectBuilder; import org.jetbrains.jps.incremental.java.JavaBuilderLoggerImpl; +import org.jetbrains.jps.model.artifact.DirectoryArtifactType; +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.artifact.JpsArtifactService; import org.jetbrains.jps.model.java.*; import org.jetbrains.jps.model.library.JpsLibrary; import org.jetbrains.jps.model.library.JpsOrderRootType; @@ -58,8 +60,11 @@ public abstract class ArtifactBuilderTestCase extends JpsBuildTestCase { @Override protected void tearDown() throws Exception { - for (Artifact artifact : myProject.getArtifacts().values()) { - FileUtil.delete(new File(FileUtil.toSystemDependentName(artifact.getOutputPath()))); + for (JpsArtifact artifact : JpsArtifactService.getInstance().getArtifacts(myJpsProject)) { + String outputPath = artifact.getOutputPath(); + if (outputPath != null) { + FileUtil.delete(new File(FileUtil.toSystemDependentName(outputPath))); + } } myDescriptor.release(); myProjectDir = null; @@ -81,11 +86,20 @@ public abstract class ArtifactBuilderTestCase extends JpsBuildTestCase { } } - protected Artifact addArtifact(LayoutElementTestUtil.LayoutElementCreator root) { - final String name = UniqueNameGenerator.generateUniqueName("a", myProject.getArtifacts().keySet()); + protected JpsArtifact addArtifact(LayoutElementTestUtil.LayoutElementCreator root) { + Set usedNames = getArtifactNames(); + final String name = UniqueNameGenerator.generateUniqueName("a", usedNames); return addArtifact(name, root); } - + + private Set getArtifactNames() { + Set usedNames = new HashSet(); + for (JpsArtifact artifact : JpsArtifactService.getInstance().getArtifacts(myJpsProject)) { + usedNames.add(artifact.getName()); + } + return usedNames; + } + private File getOrCreateProjectDir() { if (myProjectDir == null) { try { @@ -98,14 +112,10 @@ public abstract class ArtifactBuilderTestCase extends JpsBuildTestCase { return myProjectDir; } - protected Artifact addArtifact(String name, LayoutElementTestUtil.LayoutElementCreator root) { - assertFalse("Artifact " + name + " already exists", myProject.getArtifacts().containsKey(name)); - Artifact artifact = new Artifact(); - artifact.setName(name); - artifact.setRootElement(root.buildElement()); - + protected JpsArtifact addArtifact(String name, LayoutElementTestUtil.LayoutElementCreator root) { + assertFalse("JpsArtifact " + name + " already exists", getArtifactNames().contains(name)); + JpsArtifact artifact = JpsArtifactService.getInstance().addArtifact(myJpsProject, name, root.buildElement(), DirectoryArtifactType.INSTANCE); artifact.setOutputPath(getAbsolutePath("out/artifacts/" + name)); - myProject.getArtifacts().put(name, artifact); return artifact; } @@ -138,15 +148,15 @@ public abstract class ArtifactBuilderTestCase extends JpsBuildTestCase { } protected void buildAll() { - Collection artifacts = myProject.getArtifacts().values(); - buildArtifacts(artifacts.toArray(new Artifact[artifacts.size()])); + Collection artifacts = JpsArtifactService.getInstance().getArtifacts(myJpsProject); + buildArtifacts(artifacts.toArray(new JpsArtifact[artifacts.size()])); } - protected void buildArtifacts(Artifact... artifact) { + protected void buildArtifacts(JpsArtifact... artifact) { doBuild(false, false, artifact); } - private void doBuild(boolean force, final boolean shouldFail, Artifact... artifacts) { + private void doBuild(boolean force, final boolean shouldFail, JpsArtifact... artifacts) { if (myDescriptor == null) { myDescriptor = createProjectDescriptor(new BuildLoggingManager(myArtifactBuilderLogger, new JavaBuilderLoggerImpl())); myDescriptor.incUsageCounter(); @@ -154,7 +164,7 @@ public abstract class ArtifactBuilderTestCase extends JpsBuildTestCase { myArtifactBuilderLogger.clear(); IncProjectBuilder builder = createBuilder(myDescriptor); final CompileScope scope = new AllProjectScope(myDescriptor.project, myDescriptor.jpsProject, - new HashSet(Arrays.asList(artifacts)), force); + new HashSet(Arrays.asList(artifacts)), force); doBuild(builder, scope, shouldFail, !force, false); } @@ -164,11 +174,11 @@ public abstract class ArtifactBuilderTestCase extends JpsBuildTestCase { return FileUtil.toSystemIndependentName(file.getAbsolutePath()); } - protected static void assertEmptyOutput(Artifact a1) { + protected static void assertEmptyOutput(JpsArtifact a1) { assertOutput(a1, fs()); } - protected void assertBuildFailed(Artifact a) { + protected void assertBuildFailed(JpsArtifact a) { doBuild(false, true, a); } @@ -208,7 +218,7 @@ public abstract class ArtifactBuilderTestCase extends JpsBuildTestCase { assertSameElements(myArtifactBuilderLogger.myCopiedFilePaths, copiedPaths); } - protected static void assertOutput(Artifact a, TestFileSystemBuilder expected) { + protected static void assertOutput(JpsArtifact a, TestFileSystemBuilder expected) { expected.build().assertDirectoryEqual(new File(FileUtil.toSystemDependentName(a.getOutputPath()))); } diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/IncrementalArtifactBuildingTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/IncrementalArtifactBuildingTest.java index 3b2af9f18b8a..b59c2603c9b4 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/IncrementalArtifactBuildingTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/IncrementalArtifactBuildingTest.java @@ -16,7 +16,7 @@ package org.jetbrains.jps.incremental.artifacts; import com.intellij.util.PathUtil; -import org.jetbrains.jps.artifacts.Artifact; +import org.jetbrains.jps.model.artifact.JpsArtifact; import static com.intellij.util.io.TestFileSystemItem.fs; import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.archive; @@ -29,7 +29,7 @@ public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase { public void testCopyChangedFile() { String file1 = createFile("a.txt", "aaa"); String file2 = createFile("b.txt", "bbb"); - final Artifact a = addArtifact(root().fileCopy(file1).fileCopy(file2)); + final JpsArtifact a = addArtifact(root().fileCopy(file1).fileCopy(file2)); buildAll(); assertOutput(a, fs().file("a.txt", "aaa").file("b.txt", "bbb")); @@ -45,7 +45,7 @@ public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase { public void testRemoveDeletedFile() { String file1 = createFile("a.txt"); String file2 = createFile("b.txt"); - final Artifact a = addArtifact("a", root().fileCopy(file1).fileCopy(file2)); + final JpsArtifact a = addArtifact("a", root().fileCopy(file1).fileCopy(file2)); buildAll(); assertOutput(a, fs().file("a.txt").file("b.txt")); @@ -59,7 +59,7 @@ public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase { public void testPackChangedFile() { String file1 = createFile("a.txt", "aaa"); String file2 = createFile("b.txt", "bbb"); - final Artifact a = addArtifact(archive("a.jar").fileCopy(file1).fileCopy(file2)); + final JpsArtifact a = addArtifact(archive("a.jar").fileCopy(file1).fileCopy(file2)); buildAll(); assertOutput(a, fs().archive("a.jar").file("a.txt", "aaa").file("b.txt", "bbb")); buildAllAndAssertUpToDate(); @@ -74,7 +74,7 @@ public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase { public void testRemoveDeletedFileFromArchive() { String file1 = createFile("a.txt"); String file2 = createFile("b.txt"); - final Artifact a = addArtifact("a", archive("a.jar").fileCopy(file1).fileCopy(file2)); + final JpsArtifact a = addArtifact("a", archive("a.jar").fileCopy(file1).fileCopy(file2)); buildAll(); assertOutput(a, fs().archive("a.jar").file("a.txt").file("b.txt")); @@ -87,8 +87,8 @@ public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase { public void testOneFileInTwoArtifacts() { final String file = createFile("file.txt"); - final Artifact a1 = addArtifact("a1", root().dir("dir").fileCopy(file)); - final Artifact a2 = addArtifact("a2", root().dir("dir2").fileCopy(file)); + final JpsArtifact a1 = addArtifact("a1", root().dir("dir").fileCopy(file)); + final JpsArtifact a2 = addArtifact("a2", root().dir("dir2").fileCopy(file)); buildAll(); buildArtifacts(a1); assertUpToDate(); @@ -120,7 +120,7 @@ public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase { public void testRenameFile() throws Exception { final String file = createFile("a/a.txt"); - final Artifact a = addArtifact(root().dirCopy(PathUtil.getParentPath(file))); + final JpsArtifact a = addArtifact(root().dirCopy(PathUtil.getParentPath(file))); buildAll(); assertOutput(a, fs().file("a.txt")); @@ -132,7 +132,7 @@ public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase { //IDEADEV-25840 public void testUpdateFileIfCaseOfLetterInNameChanged() throws Exception { final String file = createFile("a/a.txt"); - final Artifact a = addArtifact("a", root().dirCopy(PathUtil.getParentPath(file))); + final JpsArtifact a = addArtifact("a", root().dirCopy(PathUtil.getParentPath(file))); buildAll(); assertOutput(a, fs().file("a.txt")); @@ -144,8 +144,8 @@ public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase { //IDEADEV-41556 public void testDeleteFilesFromSelectedArtifactsOnly() throws Exception { final String file = createFile("a/a.txt"); - final Artifact a1 = addArtifact("a1", root().dirCopy(PathUtil.getParentPath(file))); - final Artifact a2 = addArtifact("a2", root().dirCopy(PathUtil.getParentPath(file))); + final JpsArtifact a1 = addArtifact("a1", root().dirCopy(PathUtil.getParentPath(file))); + final JpsArtifact a2 = addArtifact("a2", root().dirCopy(PathUtil.getParentPath(file))); buildAll(); assertOutput(a1, fs().file("a.txt")); @@ -165,8 +165,8 @@ public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase { public void testTwoArtifactsWithSameOutput() throws Exception { final String res1 = PathUtil.getParentPath(createFile("res1/a.txt", "1")); final String res2 = PathUtil.getParentPath(createFile("res2/a.txt", "2")); - final Artifact a1 = addArtifact("a1", root().dirCopy(res1)); - final Artifact a2 = addArtifact("a2", root().dirCopy(res2)); + final JpsArtifact a1 = addArtifact("a1", root().dirCopy(res1)); + final JpsArtifact a2 = addArtifact("a2", root().dirCopy(res2)); a2.setOutputPath(a1.getOutputPath()); assertEquals(a1.getOutputPath(), a2.getOutputPath()); diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/LayoutElementTestUtil.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/LayoutElementTestUtil.java index e8159c432807..a2db2b5bec5b 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/LayoutElementTestUtil.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/LayoutElementTestUtil.java @@ -16,48 +16,48 @@ package org.jetbrains.jps.incremental.artifacts; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jps.artifacts.*; +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.artifact.elements.*; +import org.jetbrains.jps.model.java.JpsJavaExtensionService; import org.jetbrains.jps.model.library.JpsLibrary; import org.jetbrains.jps.model.module.JpsModule; -import java.util.Collections; - /** * @author nik */ public class LayoutElementTestUtil { public static LayoutElementCreator root() { - return new LayoutElementCreator(new RootElement(Collections.emptyList()), null); + return new LayoutElementCreator(JpsPackagingElementFactory.getInstance().createArtifactRoot(), null); } public static LayoutElementCreator archive(String name) { - return new LayoutElementCreator(new ArchiveElement(name, Collections.emptyList()), null); + return new LayoutElementCreator(JpsPackagingElementFactory.getInstance().createArchive(name), null); } - public static void addArtifactToLayout(Artifact main, Artifact included) { - final ArtifactLayoutElement element = new ArtifactLayoutElement(); - element.setArtifactName(included.getName()); - ((CompositeLayoutElement)main.getRootElement()).getChildren().add(element); + public static void addArtifactToLayout(JpsArtifact main, JpsArtifact included) { + main.getRootElement().addChild(JpsPackagingElementFactory.getInstance().createArtifactOutput(included.createReference())); } public static class LayoutElementCreator { - private CompositeLayoutElement myElement; + private JpsPackagingElementFactory myFactory; + private JpsCompositePackagingElement myElement; private LayoutElementCreator myParent; - public LayoutElementCreator(CompositeLayoutElement element, LayoutElementCreator parent) { + public LayoutElementCreator(JpsCompositePackagingElement element, LayoutElementCreator parent) { myElement = element; myParent = parent; + myFactory = JpsPackagingElementFactory.getInstance(); } public LayoutElementCreator dir(String name) { - DirectoryElement dir = new DirectoryElement(name, Collections.emptyList()); - myElement.getChildren().add(dir); + JpsDirectoryPackagingElement dir = myFactory.createDirectory(name); + myElement.addChild(dir); return new LayoutElementCreator(dir, this); } public LayoutElementCreator archive(String name) { - ArchiveElement archive = new ArchiveElement(name, Collections.emptyList()); - myElement.getChildren().add(archive); + JpsArchivePackagingElement archive = myFactory.createArchive(name); + myElement.addChild(archive); return new LayoutElementCreator(archive, this); } @@ -66,49 +66,39 @@ public class LayoutElementTestUtil { } public LayoutElementCreator fileCopy(String filePath, @Nullable String outputFileName) { - return element(new FileCopyElement(filePath, outputFileName)); + return element(myFactory.createFileCopy(filePath, outputFileName)); } public LayoutElementCreator dirCopy(String dirPath) { - return element(new DirectoryCopyElement(dirPath)); + return element(myFactory.createDirectoryCopy(dirPath)); } public LayoutElementCreator module(JpsModule module) { - final ModuleOutputElement element = new ModuleOutputElement(); - element.setModuleName(module.getName()); - return element(element); + return element(JpsJavaExtensionService.getInstance().createProductionModuleOutput(module.createReference())); } - public LayoutElementCreator element(LayoutElement element) { - myElement.getChildren().add(element); + public LayoutElementCreator element(JpsPackagingElement element) { + myElement.addChild(element); return this; } public LayoutElementCreator lib(JpsLibrary library) { - final LibraryFilesElement element = new LibraryFilesElement(); - element.setLibraryName(library.getName()); - element.setLibraryLevel(LibraryFilesElement.PROJECT_LEVEL); - return element(element); + return element(myFactory.createLibraryElement(library.createReference())); } public LayoutElementCreator extractedDir(String jarPath, String pathInJar) { - ExtractedDirectoryElement dir = new ExtractedDirectoryElement(); - dir.setJarPath(jarPath); - dir.setPathInJar(pathInJar); - return element(dir); + return element(myFactory.createExtractedDirectory(jarPath, pathInJar)); } - public LayoutElementCreator artifact(Artifact included) { - final ArtifactLayoutElement element = new ArtifactLayoutElement(); - element.setArtifactName(included.getName()); - return element(element); + public LayoutElementCreator artifact(JpsArtifact included) { + return element(myFactory.createArtifactOutput(included.createReference())); } public LayoutElementCreator end() { return myParent; } - public CompositeLayoutElement buildElement() { + public JpsCompositePackagingElement buildElement() { if (myParent != null) { return myParent.buildElement(); } diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/DirectoryArtifactType.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/DirectoryArtifactType.java new file mode 100644 index 000000000000..0a606c3490d5 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/DirectoryArtifactType.java @@ -0,0 +1,8 @@ +package org.jetbrains.jps.model.artifact; + +/** + * @author nik + */ +public class DirectoryArtifactType extends JpsArtifactType { + public static final DirectoryArtifactType INSTANCE = new DirectoryArtifactType(); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/JarArtifactType.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/JarArtifactType.java new file mode 100644 index 000000000000..75552f36bf71 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/JarArtifactType.java @@ -0,0 +1,8 @@ +package org.jetbrains.jps.model.artifact; + +/** + * @author nik + */ +public class JarArtifactType extends JpsArtifactType { + public static final JarArtifactType INSTANCE = new JarArtifactType(); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifact.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifact.java new file mode 100644 index 000000000000..0fbf491a99d3 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifact.java @@ -0,0 +1,30 @@ +package org.jetbrains.jps.model.artifact; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.JpsCompositeElement; +import org.jetbrains.jps.model.JpsNamedElement; +import org.jetbrains.jps.model.JpsReferenceableElement; +import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement; + +/** + * @author nik + */ +public interface JpsArtifact extends JpsNamedElement, JpsReferenceableElement, JpsCompositeElement { + @NotNull + JpsArtifactType getArtifactType(); + + @Nullable + String getOutputPath(); + + void setOutputPath(@Nullable String outputPath); + + @NotNull + JpsCompositePackagingElement getRootElement(); + + void setRootElement(@NotNull JpsCompositePackagingElement rootElement); + + @NotNull + @Override + JpsArtifactReference createReference(); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactReference.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactReference.java new file mode 100644 index 000000000000..27ed4a107b36 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactReference.java @@ -0,0 +1,16 @@ +package org.jetbrains.jps.model.artifact; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.JpsElementReference; +import org.jetbrains.jps.model.JpsModel; + +/** + * @author nik + */ +public interface JpsArtifactReference extends JpsElementReference { + @NotNull + String getArtifactName(); + + @Override + JpsArtifactReference asExternal(@NotNull JpsModel model); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactService.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactService.java new file mode 100644 index 000000000000..46fd347ed472 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactService.java @@ -0,0 +1,27 @@ +package org.jetbrains.jps.model.artifact; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.JpsProject; +import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement; +import org.jetbrains.jps.service.JpsServiceManager; + +import java.util.List; + +/** + * @author nik + */ +public abstract class JpsArtifactService { + + public static JpsArtifactService getInstance() { + return JpsServiceManager.getInstance().getService(JpsArtifactService.class); + } + + public abstract List getArtifacts(@NotNull JpsProject project); + + public abstract JpsArtifact addArtifact(@NotNull JpsProject project, + @NotNull String name, + @NotNull JpsCompositePackagingElement rootElement, + @NotNull JpsArtifactType type); + + public abstract JpsArtifactReference createReference(@NotNull String artifactName); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactType.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactType.java new file mode 100644 index 000000000000..811e1c0156b5 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/JpsArtifactType.java @@ -0,0 +1,14 @@ +package org.jetbrains.jps.model.artifact; + +import org.jetbrains.jps.model.DummyJpsElementProperties; +import org.jetbrains.jps.model.JpsElementType; + +/** + * @author nik + */ +public abstract class JpsArtifactType extends JpsElementType { + @Override + public DummyJpsElementProperties createCopy(DummyJpsElementProperties properties) { + return DummyJpsElementProperties.INSTANCE; + } +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArchivePackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArchivePackagingElement.java new file mode 100644 index 000000000000..8b7395602db5 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArchivePackagingElement.java @@ -0,0 +1,10 @@ +package org.jetbrains.jps.model.artifact.elements; + +/** + * @author nik + */ +public interface JpsArchivePackagingElement extends JpsCompositePackagingElement { + String getArchiveName(); + + void setArchiveName(String directoryName); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactOutputPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactOutputPackagingElement.java new file mode 100644 index 000000000000..cd9441f81839 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactOutputPackagingElement.java @@ -0,0 +1,12 @@ +package org.jetbrains.jps.model.artifact.elements; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.artifact.JpsArtifactReference; + +/** + * @author nik + */ +public interface JpsArtifactOutputPackagingElement extends JpsComplexPackagingElement { + @NotNull + JpsArtifactReference getArtifactReference(); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactRootElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactRootElement.java new file mode 100644 index 000000000000..3a189d26d480 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsArtifactRootElement.java @@ -0,0 +1,7 @@ +package org.jetbrains.jps.model.artifact.elements; + +/** + * @author nik + */ +public interface JpsArtifactRootElement extends JpsCompositePackagingElement { +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsComplexPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsComplexPackagingElement.java new file mode 100644 index 000000000000..5fa1b3ff5b3c --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsComplexPackagingElement.java @@ -0,0 +1,10 @@ +package org.jetbrains.jps.model.artifact.elements; + +import java.util.List; + +/** + * @author nik + */ +public interface JpsComplexPackagingElement extends JpsPackagingElement { + List getSubstitution(); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsCompositePackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsCompositePackagingElement.java new file mode 100644 index 000000000000..32f5cf37657a --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsCompositePackagingElement.java @@ -0,0 +1,15 @@ +package org.jetbrains.jps.model.artifact.elements; + +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * @author nik + */ +public interface JpsCompositePackagingElement extends JpsPackagingElement { + @NotNull + List getChildren(); + + E addChild(@NotNull E child); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryCopyPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryCopyPackagingElement.java new file mode 100644 index 000000000000..718379984123 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryCopyPackagingElement.java @@ -0,0 +1,10 @@ +package org.jetbrains.jps.model.artifact.elements; + +/** + * @author nik + */ +public interface JpsDirectoryCopyPackagingElement extends JpsPackagingElement { + String getDirectoryPath(); + + void setDirectoryPath(String path); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryPackagingElement.java new file mode 100644 index 000000000000..3f4e0b832fd2 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsDirectoryPackagingElement.java @@ -0,0 +1,11 @@ +package org.jetbrains.jps.model.artifact.elements; + +/** + * @author nik + */ +public interface JpsDirectoryPackagingElement extends JpsCompositePackagingElement { + + String getDirectoryName(); + + void setDirectoryName(String directoryName); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsExtractedDirectoryPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsExtractedDirectoryPackagingElement.java new file mode 100644 index 000000000000..51ddb695717b --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsExtractedDirectoryPackagingElement.java @@ -0,0 +1,14 @@ +package org.jetbrains.jps.model.artifact.elements; + +/** + * @author nik + */ +public interface JpsExtractedDirectoryPackagingElement extends JpsPackagingElement { + String getFilePath(); + + void setFilePath(String path); + + String getPathInJar(); + + void setPathInJar(String pathInJar); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsFileCopyPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsFileCopyPackagingElement.java new file mode 100644 index 000000000000..d1ca3199c882 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsFileCopyPackagingElement.java @@ -0,0 +1,15 @@ +package org.jetbrains.jps.model.artifact.elements; + +/** + * @author nik + */ +public interface JpsFileCopyPackagingElement extends JpsPackagingElement { + + String getFilePath(); + + void setFilePath(String filePath); + + String getRenamedOutputFileName(); + + void setRenamedOutputFileName(String renamedOutputFileName); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsLibraryFilesPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsLibraryFilesPackagingElement.java new file mode 100644 index 000000000000..3916f43d74fb --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsLibraryFilesPackagingElement.java @@ -0,0 +1,12 @@ +package org.jetbrains.jps.model.artifact.elements; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.library.JpsLibraryReference; + +/** + * @author nik + */ +public interface JpsLibraryFilesPackagingElement extends JpsPackagingElement { + @NotNull + JpsLibraryReference getLibraryReference(); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsModuleOutputPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsModuleOutputPackagingElement.java new file mode 100644 index 000000000000..645a3a8b76aa --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsModuleOutputPackagingElement.java @@ -0,0 +1,16 @@ +package org.jetbrains.jps.model.artifact.elements; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.module.JpsModuleReference; + +/** + * @author nik + */ +public interface JpsModuleOutputPackagingElement extends JpsPackagingElement { + @NotNull + JpsModuleReference getModuleReference(); + + @Nullable + String getOutputUrl(); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElement.java new file mode 100644 index 000000000000..961fde54783f --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElement.java @@ -0,0 +1,9 @@ +package org.jetbrains.jps.model.artifact.elements; + +import org.jetbrains.jps.model.JpsElement; + +/** + * @author nik + */ +public interface JpsPackagingElement extends JpsElement { +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElementFactory.java b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElementFactory.java new file mode 100644 index 000000000000..9ea13f9adfbd --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/artifact/elements/JpsPackagingElementFactory.java @@ -0,0 +1,43 @@ +package org.jetbrains.jps.model.artifact.elements; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.artifact.JpsArtifactReference; +import org.jetbrains.jps.model.library.JpsLibraryReference; +import org.jetbrains.jps.service.JpsServiceManager; + +/** + * @author nik + */ +public abstract class JpsPackagingElementFactory { + public static JpsPackagingElementFactory getInstance() { + return JpsServiceManager.getInstance().getService(JpsPackagingElementFactory.class); + } + + @NotNull + public abstract JpsDirectoryCopyPackagingElement createDirectoryCopy(@NotNull String directoryPath); + + public abstract JpsPackagingElement createParentDirectories(String path, JpsPackagingElement element); + + @NotNull + public abstract JpsFileCopyPackagingElement createFileCopy(@NotNull String filePath, @Nullable String outputFileName); + + @NotNull + public abstract JpsExtractedDirectoryPackagingElement createExtractedDirectory(@NotNull String jarPath, @NotNull String pathInJar); + + @NotNull + public abstract JpsDirectoryPackagingElement createDirectory(@NotNull String directoryName); + + @NotNull + public abstract JpsArchivePackagingElement createArchive(@NotNull String archiveName); + + @NotNull + public abstract JpsArtifactRootElement createArtifactRoot(); + + @NotNull + public abstract JpsLibraryFilesPackagingElement createLibraryElement(@NotNull JpsLibraryReference reference); + + @NotNull + public abstract JpsArtifactOutputPackagingElement createArtifactOutput(@NotNull JpsArtifactReference reference); + +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaExtensionService.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaExtensionService.java index 1f040a4050cf..32d2bb317fe4 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaExtensionService.java +++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsJavaExtensionService.java @@ -6,6 +6,7 @@ import org.jetbrains.jps.model.JpsElementKind; import org.jetbrains.jps.model.JpsProject; import org.jetbrains.jps.model.module.JpsDependencyElement; import org.jetbrains.jps.model.module.JpsModule; +import org.jetbrains.jps.model.module.JpsModuleReference; import org.jetbrains.jps.service.JpsServiceManager; import java.util.List; @@ -14,6 +15,12 @@ import java.util.List; * @author nik */ public abstract class JpsJavaExtensionService { + @NotNull + public abstract JpsProductionModuleOutputPackagingElement createProductionModuleOutput(@NotNull JpsModuleReference moduleReference); + + @NotNull + public abstract JpsTestModuleOutputPackagingElement createTestModuleOutput(@NotNull JpsModuleReference moduleReference); + public static JpsJavaExtensionService getInstance() { return JpsServiceManager.getInstance().getService(JpsJavaExtensionService.class); } diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsProductionModuleOutputPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsProductionModuleOutputPackagingElement.java new file mode 100644 index 000000000000..8dcb5e7b9df1 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsProductionModuleOutputPackagingElement.java @@ -0,0 +1,9 @@ +package org.jetbrains.jps.model.java; + +import org.jetbrains.jps.model.artifact.elements.JpsModuleOutputPackagingElement; + +/** + * @author nik + */ +public interface JpsProductionModuleOutputPackagingElement extends JpsModuleOutputPackagingElement { +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsTestModuleOutputPackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsTestModuleOutputPackagingElement.java new file mode 100644 index 000000000000..54fd07929fac --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsTestModuleOutputPackagingElement.java @@ -0,0 +1,9 @@ +package org.jetbrains.jps.model.java; + +import org.jetbrains.jps.model.artifact.elements.JpsModuleOutputPackagingElement; + +/** + * @author nik + */ +public interface JpsTestModuleOutputPackagingElement extends JpsModuleOutputPackagingElement { +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibrary.java b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibrary.java index 77d4c35772e7..6fea6b3f42c9 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibrary.java +++ b/jps/model-api/src/org/jetbrains/jps/model/library/JpsLibrary.java @@ -5,6 +5,7 @@ import org.jetbrains.jps.model.JpsElementProperties; import org.jetbrains.jps.model.JpsNamedElement; import org.jetbrains.jps.model.JpsReferenceableElement; +import java.io.File; import java.util.List; /** @@ -31,4 +32,6 @@ public interface JpsLibrary extends JpsNamedElement, JpsReferenceableElement getFiles(final JpsOrderRootType rootType); } diff --git a/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.JpsArtifactService b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.JpsArtifactService new file mode 100644 index 000000000000..0313eb7ef3a3 --- /dev/null +++ b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.JpsArtifactService @@ -0,0 +1 @@ +org.jetbrains.jps.model.artifact.impl.JpsArtifactServiceImpl \ No newline at end of file diff --git a/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.elements.JpsPackagingElementFactory b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.elements.JpsPackagingElementFactory new file mode 100644 index 000000000000..bbc28002f730 --- /dev/null +++ b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.artifact.elements.JpsPackagingElementFactory @@ -0,0 +1 @@ +org.jetbrains.jps.model.artifact.impl.elements.JpsPackagingElementFactoryImpl \ No newline at end of file diff --git a/jps/model/src/org/jetbrains/jps/JpsPathUtil.java b/jps/model-impl/src/org/jetbrains/jps/JpsPathUtil.java similarity index 95% rename from jps/model/src/org/jetbrains/jps/JpsPathUtil.java rename to jps/model-impl/src/org/jetbrains/jps/JpsPathUtil.java index 6c111f0a7d6e..39b45108f72d 100644 --- a/jps/model/src/org/jetbrains/jps/JpsPathUtil.java +++ b/jps/model-impl/src/org/jetbrains/jps/JpsPathUtil.java @@ -1,6 +1,7 @@ package org.jetbrains.jps; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; @@ -59,7 +60,7 @@ public class JpsPathUtil { } public static File urlToFile(String url) { - return new File(FileUtil.toSystemDependentName(urlToPath(url))); + return new File(FileUtilRt.toSystemDependentName(urlToPath(url))); } public static String urlToPath(String url) { diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactImpl.java new file mode 100644 index 000000000000..ff86c36ae079 --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactImpl.java @@ -0,0 +1,74 @@ +package org.jetbrains.jps.model.artifact.impl; + +import com.intellij.openapi.util.Comparing; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.DummyJpsElementProperties; +import org.jetbrains.jps.model.JpsElementKind; +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.artifact.JpsArtifactType; +import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement; +import org.jetbrains.jps.model.impl.JpsElementKindBase; +import org.jetbrains.jps.model.impl.JpsNamedCompositeElementBase; +import org.jetbrains.jps.model.impl.JpsTypedDataImpl; +import org.jetbrains.jps.model.impl.JpsTypedDataKind; + +/** + * @author nik + */ +public class JpsArtifactImpl extends JpsNamedCompositeElementBase implements JpsArtifact { + private static final JpsElementKind ROOT_ELEMENT_KIND = new JpsElementKindBase("root element"); + private static final JpsTypedDataKind TYPED_DATA_KIND = new JpsTypedDataKind(); + private String myOutputPath; + + public JpsArtifactImpl(@NotNull String name, @NotNull JpsCompositePackagingElement rootElement, @NotNull JpsArtifactType type) { + super(name); + myContainer.setChild(ROOT_ELEMENT_KIND, rootElement); + myContainer.setChild(TYPED_DATA_KIND, new JpsTypedDataImpl(type, DummyJpsElementProperties.INSTANCE)); + } + + private JpsArtifactImpl(JpsArtifactImpl original) { + super(original); + myOutputPath = original.myOutputPath; + } + + @NotNull + @Override + public JpsArtifactImpl createCopy() { + return new JpsArtifactImpl(this); + } + + public String getOutputPath() { + return myOutputPath; + } + + public void setOutputPath(@Nullable String outputPath) { + if (!Comparing.equal(myOutputPath, outputPath)) { + myOutputPath = outputPath; + fireElementChanged(); + } + } + + @NotNull + @Override + public JpsArtifactType getArtifactType() { + return myContainer.getChild(TYPED_DATA_KIND).getType(); + } + + @NotNull + @Override + public JpsArtifactReferenceImpl createReference() { + return new JpsArtifactReferenceImpl(getName()); + } + + @NotNull + @Override + public JpsCompositePackagingElement getRootElement() { + return myContainer.getChild(ROOT_ELEMENT_KIND); + } + + @Override + public void setRootElement(@NotNull JpsCompositePackagingElement rootElement) { + myContainer.setChild(ROOT_ELEMENT_KIND, rootElement); + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactKind.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactKind.java new file mode 100644 index 000000000000..4a26f23bcfe2 --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactKind.java @@ -0,0 +1,17 @@ +package org.jetbrains.jps.model.artifact.impl; + +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.impl.JpsElementCollectionKind; +import org.jetbrains.jps.model.impl.JpsElementKindBase; + +/** +* @author nik +*/ +public class JpsArtifactKind extends JpsElementKindBase { + public static final JpsArtifactKind INSTANCE = new JpsArtifactKind(); + public static final JpsElementCollectionKind ARTIFACT_COLLECTION_KIND = new JpsElementCollectionKind(INSTANCE); + + public JpsArtifactKind() { + super("artifact"); + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactReferenceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactReferenceImpl.java new file mode 100644 index 000000000000..e792f0bdea76 --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactReferenceImpl.java @@ -0,0 +1,39 @@ +package org.jetbrains.jps.model.artifact.impl; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.JpsElementFactory; +import org.jetbrains.jps.model.JpsModel; +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.artifact.JpsArtifactReference; +import org.jetbrains.jps.model.impl.JpsNamedElementReferenceBase; + +/** + * @author nik + */ +public class JpsArtifactReferenceImpl extends JpsNamedElementReferenceBase implements JpsArtifactReference { + public JpsArtifactReferenceImpl(@NotNull String artifactName) { + super(JpsArtifactKind.ARTIFACT_COLLECTION_KIND, artifactName, JpsElementFactory.getInstance().createProjectReference()); + } + + private JpsArtifactReferenceImpl(JpsArtifactReferenceImpl original) { + super(original); + } + + @NotNull + @Override + public JpsArtifactReferenceImpl createCopy() { + return new JpsArtifactReferenceImpl(this); + } + + @NotNull + @Override + public String getArtifactName() { + return myElementName; + } + + @Override + public JpsArtifactReferenceImpl asExternal(@NotNull JpsModel model) { + model.registerExternalReference(this); + return this; + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactServiceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactServiceImpl.java new file mode 100644 index 000000000000..257280671159 --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactServiceImpl.java @@ -0,0 +1,36 @@ +package org.jetbrains.jps.model.artifact.impl; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.JpsProject; +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.artifact.JpsArtifactReference; +import org.jetbrains.jps.model.artifact.JpsArtifactService; +import org.jetbrains.jps.model.artifact.JpsArtifactType; +import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement; +import org.jetbrains.jps.model.impl.JpsElementCollectionImpl; + +import java.util.Collections; +import java.util.List; + +/** + * @author nik + */ +public class JpsArtifactServiceImpl extends JpsArtifactService { + @Override + public List getArtifacts(@NotNull JpsProject project) { + JpsElementCollectionImpl collection = project.getContainer().getChild(JpsArtifactKind.ARTIFACT_COLLECTION_KIND); + return collection != null ? collection.getElements() : Collections.emptyList(); + } + + @Override + public JpsArtifact addArtifact(@NotNull JpsProject project, @NotNull String name, @NotNull JpsCompositePackagingElement rootElement, + @NotNull JpsArtifactType type) { + JpsArtifact artifact = new JpsArtifactImpl(name, rootElement, type); + return project.getContainer().getOrSetChild(JpsArtifactKind.ARTIFACT_COLLECTION_KIND).addChild(artifact); + } + + @Override + public JpsArtifactReference createReference(@NotNull String artifactName) { + return new JpsArtifactReferenceImpl(artifactName); + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArchivePackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArchivePackagingElementImpl.java new file mode 100644 index 000000000000..a5ecd991224c --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArchivePackagingElementImpl.java @@ -0,0 +1,40 @@ +package org.jetbrains.jps.model.artifact.impl.elements; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.artifact.elements.JpsArchivePackagingElement; + +/** + * @author nik + */ +public class JpsArchivePackagingElementImpl extends JpsCompositePackagingElementBase + implements JpsArchivePackagingElement { + private String myArchiveName; + + public JpsArchivePackagingElementImpl(String archiveName) { + myArchiveName = archiveName; + } + + private JpsArchivePackagingElementImpl(JpsArchivePackagingElementImpl original) { + super(original); + myArchiveName = original.myArchiveName; + } + + @NotNull + @Override + public JpsArchivePackagingElementImpl createCopy() { + return new JpsArchivePackagingElementImpl(this); + } + + @Override + public String getArchiveName() { + return myArchiveName; + } + + @Override + public void setArchiveName(String directoryName) { + if (!myArchiveName.equals(directoryName)) { + myArchiveName = directoryName; + fireElementChanged(); + } + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactOutputPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactOutputPackagingElementImpl.java new file mode 100644 index 000000000000..1e6b6be891d6 --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactOutputPackagingElementImpl.java @@ -0,0 +1,56 @@ +package org.jetbrains.jps.model.artifact.impl.elements; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.JpsElementKind; +import org.jetbrains.jps.model.artifact.JpsArtifact; +import org.jetbrains.jps.model.artifact.JpsArtifactReference; +import org.jetbrains.jps.model.artifact.elements.JpsArtifactOutputPackagingElement; +import org.jetbrains.jps.model.artifact.elements.JpsArtifactRootElement; +import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; +import org.jetbrains.jps.model.impl.JpsElementKindBase; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author nik + */ +public class JpsArtifactOutputPackagingElementImpl extends JpsComplexPackagingElementBase + implements JpsArtifactOutputPackagingElement { + private static final JpsElementKind ARTIFACT_REFERENCE_KIND = new JpsElementKindBase("artifact reference"); + + public JpsArtifactOutputPackagingElementImpl(@NotNull JpsArtifactReference reference) { + myContainer.setChild(ARTIFACT_REFERENCE_KIND, reference); + } + + private JpsArtifactOutputPackagingElementImpl(JpsArtifactOutputPackagingElementImpl original) { + super(original); + } + + @NotNull + @Override + public JpsArtifactOutputPackagingElementImpl createCopy() { + return new JpsArtifactOutputPackagingElementImpl(this); + } + + @Override + @NotNull + public JpsArtifactReference getArtifactReference() { + return myContainer.getChild(ARTIFACT_REFERENCE_KIND); + } + + @Override + public List getSubstitution() { + JpsArtifact artifact = getArtifactReference().resolve(); + if (artifact == null) return Collections.emptyList(); + JpsCompositePackagingElement rootElement = artifact.getRootElement(); + if (rootElement instanceof JpsArtifactRootElement) { + return new ArrayList(rootElement.getChildren()); + } + else { + return Collections.singletonList(rootElement); + } + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactRootElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactRootElementImpl.java new file mode 100644 index 000000000000..940a5d4967aa --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsArtifactRootElementImpl.java @@ -0,0 +1,22 @@ +package org.jetbrains.jps.model.artifact.impl.elements; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.artifact.elements.JpsArtifactRootElement; + +/** + * @author nik + */ +public class JpsArtifactRootElementImpl extends JpsCompositePackagingElementBase implements JpsArtifactRootElement { + public JpsArtifactRootElementImpl() { + } + + private JpsArtifactRootElementImpl(JpsArtifactRootElementImpl original) { + super(original); + } + + @NotNull + @Override + public JpsArtifactRootElementImpl createCopy() { + return new JpsArtifactRootElementImpl(); + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsComplexPackagingElementBase.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsComplexPackagingElementBase.java new file mode 100644 index 000000000000..c1274c42ea27 --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsComplexPackagingElementBase.java @@ -0,0 +1,17 @@ +package org.jetbrains.jps.model.artifact.impl.elements; + +import org.jetbrains.jps.model.artifact.elements.JpsComplexPackagingElement; +import org.jetbrains.jps.model.impl.JpsCompositeElementBase; + +/** + * @author nik + */ +public abstract class JpsComplexPackagingElementBase> extends JpsCompositeElementBase implements + JpsComplexPackagingElement { + protected JpsComplexPackagingElementBase() { + } + + protected JpsComplexPackagingElementBase(JpsComplexPackagingElementBase original) { + super(original); + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsCompositePackagingElementBase.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsCompositePackagingElementBase.java new file mode 100644 index 000000000000..3b0ca80b33c0 --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsCompositePackagingElementBase.java @@ -0,0 +1,38 @@ +package org.jetbrains.jps.model.artifact.impl.elements; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; +import org.jetbrains.jps.model.impl.JpsCompositeElementBase; +import org.jetbrains.jps.model.impl.JpsElementCollectionKind; +import org.jetbrains.jps.model.impl.JpsElementKindBase; + +import java.util.List; + +/** + * @author nik + */ +public abstract class JpsCompositePackagingElementBase> extends JpsCompositeElementBase + implements JpsCompositePackagingElement { + private static final JpsElementCollectionKind CHILDREN_KIND = new JpsElementCollectionKind(new JpsElementKindBase("child")); + + protected JpsCompositePackagingElementBase() { + myContainer.setChild(CHILDREN_KIND); + } + + protected JpsCompositePackagingElementBase(JpsCompositePackagingElementBase original) { + super(original); + } + + @NotNull + @Override + public List getChildren() { + return myContainer.getChild(CHILDREN_KIND).getElements(); + } + + + @Override + public E addChild(@NotNull E child) { + return myContainer.getChild(CHILDREN_KIND).addChild(child); + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryCopyPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryCopyPackagingElementImpl.java new file mode 100644 index 000000000000..81dcb44edb3a --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryCopyPackagingElementImpl.java @@ -0,0 +1,30 @@ +package org.jetbrains.jps.model.artifact.impl.elements; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.artifact.elements.JpsDirectoryCopyPackagingElement; + +/** + * @author nik + */ +public class JpsDirectoryCopyPackagingElementImpl extends JpsFileCopyPackagingElementBase + implements JpsDirectoryCopyPackagingElement { + public JpsDirectoryCopyPackagingElementImpl(String directoryPath) { + super(directoryPath); + } + + @NotNull + @Override + public JpsDirectoryCopyPackagingElementImpl createCopy() { + return new JpsDirectoryCopyPackagingElementImpl(myFilePath); + } + + @Override + public String getDirectoryPath() { + return getFilePath(); + } + + @Override + public void setDirectoryPath(String path) { + setFilePath(path); + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryPackagingElementImpl.java new file mode 100644 index 000000000000..04ffa3b5544d --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsDirectoryPackagingElementImpl.java @@ -0,0 +1,39 @@ +package org.jetbrains.jps.model.artifact.impl.elements; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.artifact.elements.JpsDirectoryPackagingElement; + +/** + * @author nik + */ +public class JpsDirectoryPackagingElementImpl extends JpsCompositePackagingElementBase implements JpsDirectoryPackagingElement { + private String myDirectoryName; + + public JpsDirectoryPackagingElementImpl(String directoryName) { + myDirectoryName = directoryName; + } + + private JpsDirectoryPackagingElementImpl(JpsDirectoryPackagingElementImpl original) { + super(original); + myDirectoryName = original.myDirectoryName; + } + + @NotNull + @Override + public JpsDirectoryPackagingElementImpl createCopy() { + return new JpsDirectoryPackagingElementImpl(this); + } + + @Override + public String getDirectoryName() { + return myDirectoryName; + } + + @Override + public void setDirectoryName(String directoryName) { + if (!myDirectoryName.equals(directoryName)) { + myDirectoryName = directoryName; + fireElementChanged(); + } + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsExtractedDirectoryPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsExtractedDirectoryPackagingElementImpl.java new file mode 100644 index 000000000000..ff3f4ca9bc7a --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsExtractedDirectoryPackagingElementImpl.java @@ -0,0 +1,43 @@ +package org.jetbrains.jps.model.artifact.impl.elements; + +import com.intellij.openapi.util.Comparing; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.artifact.elements.JpsExtractedDirectoryPackagingElement; + +/** + * @author nik + */ +public class JpsExtractedDirectoryPackagingElementImpl extends JpsFileCopyPackagingElementBase + implements JpsExtractedDirectoryPackagingElement { + private String myPathInJar; + + public JpsExtractedDirectoryPackagingElementImpl(String filePath, String pathInJar) { + super(filePath); + myPathInJar = pathInJar; + } + + @NotNull + @Override + public JpsExtractedDirectoryPackagingElementImpl createCopy() { + return new JpsExtractedDirectoryPackagingElementImpl(myFilePath, myPathInJar); + } + + @Override + public void applyChanges(@NotNull JpsExtractedDirectoryPackagingElementImpl modified) { + super.applyChanges(modified); + setPathInJar(modified.myPathInJar); + } + + @Override + public String getPathInJar() { + return myPathInJar; + } + + @Override + public void setPathInJar(String pathInJar) { + if (!Comparing.equal(myPathInJar, pathInJar)) { + myPathInJar = pathInJar; + fireElementChanged(); + } + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementBase.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementBase.java new file mode 100644 index 000000000000..e81ba2ce656b --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementBase.java @@ -0,0 +1,34 @@ +package org.jetbrains.jps.model.artifact.impl.elements; + +import com.intellij.openapi.util.Comparing; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; +import org.jetbrains.jps.model.impl.JpsElementBase; + +/** + * @author nik + */ +public abstract class JpsFileCopyPackagingElementBase> extends JpsElementBase implements + JpsPackagingElement { + protected String myFilePath; + + public JpsFileCopyPackagingElementBase(String filePath) { + myFilePath = filePath; + } + + @Override + public void applyChanges(@NotNull Self modified) { + setFilePath(modified.myFilePath); + } + + public String getFilePath() { + return myFilePath; + } + + public void setFilePath(String filePath) { + if (!Comparing.equal(myFilePath, filePath)) { + myFilePath = filePath; + fireElementChanged(); + } + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementImpl.java new file mode 100644 index 000000000000..4b188a1ecb94 --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsFileCopyPackagingElementImpl.java @@ -0,0 +1,42 @@ +package org.jetbrains.jps.model.artifact.impl.elements; + +import com.intellij.openapi.util.Comparing; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.artifact.elements.JpsFileCopyPackagingElement; + +/** + * @author nik + */ +public class JpsFileCopyPackagingElementImpl extends JpsFileCopyPackagingElementBase implements JpsFileCopyPackagingElement { + private String myRenamedOutputFileName; + + public JpsFileCopyPackagingElementImpl(String filePath, String renamedOutputFileName) { + super(filePath); + myRenamedOutputFileName = renamedOutputFileName; + } + + @NotNull + @Override + public JpsFileCopyPackagingElementImpl createCopy() { + return new JpsFileCopyPackagingElementImpl(myFilePath, myRenamedOutputFileName); + } + + @Override + public void applyChanges(@NotNull JpsFileCopyPackagingElementImpl modified) { + super.applyChanges(modified); + setRenamedOutputFileName(modified.myRenamedOutputFileName); + } + + @Override + public String getRenamedOutputFileName() { + return myRenamedOutputFileName; + } + + @Override + public void setRenamedOutputFileName(String renamedOutputFileName) { + if (!Comparing.equal(myRenamedOutputFileName, renamedOutputFileName)) { + myRenamedOutputFileName = renamedOutputFileName; + fireElementChanged(); + } + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsLibraryFilesPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsLibraryFilesPackagingElementImpl.java new file mode 100644 index 000000000000..3900ae7874a7 --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsLibraryFilesPackagingElementImpl.java @@ -0,0 +1,61 @@ +package org.jetbrains.jps.model.artifact.impl.elements; + +import com.intellij.openapi.util.io.FileUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.JpsElementKind; +import org.jetbrains.jps.model.artifact.elements.JpsLibraryFilesPackagingElement; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElementFactory; +import org.jetbrains.jps.model.impl.JpsElementKindBase; +import org.jetbrains.jps.model.library.JpsLibrary; +import org.jetbrains.jps.model.library.JpsLibraryReference; +import org.jetbrains.jps.model.library.JpsOrderRootType; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author nik + */ +public class JpsLibraryFilesPackagingElementImpl extends JpsComplexPackagingElementBase implements JpsLibraryFilesPackagingElement { + private static final JpsElementKind LIBRARY_REFERENCE_KIND = new JpsElementKindBase("library reference"); + + public JpsLibraryFilesPackagingElementImpl(@NotNull JpsLibraryReference reference) { + myContainer.setChild(LIBRARY_REFERENCE_KIND, reference); + } + + private JpsLibraryFilesPackagingElementImpl(JpsLibraryFilesPackagingElementImpl original) { + super(original); + } + + @NotNull + @Override + public JpsLibraryFilesPackagingElementImpl createCopy() { + return new JpsLibraryFilesPackagingElementImpl(this); + } + + @Override + @NotNull + public JpsLibraryReference getLibraryReference() { + return myContainer.getChild(LIBRARY_REFERENCE_KIND); + } + + @Override + public List getSubstitution() { + JpsLibrary library = getLibraryReference().resolve(); + if (library == null) return Collections.emptyList(); + List result = new ArrayList(); + for (File file : library.getFiles(JpsOrderRootType.COMPILED)) { + String path = FileUtil.toSystemIndependentName(file.getAbsolutePath()); + if (file.isDirectory()) { + result.add(JpsPackagingElementFactory.getInstance().createDirectoryCopy(path)); + } + else { + result.add(JpsPackagingElementFactory.getInstance().createFileCopy(path, null)); + } + } + return result; + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsModuleOutputPackagingElementBase.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsModuleOutputPackagingElementBase.java new file mode 100644 index 000000000000..8e4a1c27523b --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsModuleOutputPackagingElementBase.java @@ -0,0 +1,43 @@ +package org.jetbrains.jps.model.artifact.impl.elements; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.JpsElementKind; +import org.jetbrains.jps.model.artifact.elements.JpsModuleOutputPackagingElement; +import org.jetbrains.jps.model.impl.JpsCompositeElementBase; +import org.jetbrains.jps.model.impl.JpsElementKindBase; +import org.jetbrains.jps.model.module.JpsModule; +import org.jetbrains.jps.model.module.JpsModuleReference; + +/** + * @author nik + */ +public abstract class JpsModuleOutputPackagingElementBase> extends JpsCompositeElementBase implements + JpsModuleOutputPackagingElement { + private static final JpsElementKind MODULE_REFERENCE_KIND = new JpsElementKindBase("module reference"); + + public JpsModuleOutputPackagingElementBase(JpsModuleReference moduleReference) { + myContainer.setChild(MODULE_REFERENCE_KIND, moduleReference); + } + + public JpsModuleOutputPackagingElementBase(JpsModuleOutputPackagingElementBase original) { + super(original); + } + + @Override + @NotNull + public JpsModuleReference getModuleReference() { + return myContainer.getChild(MODULE_REFERENCE_KIND); + } + + @Override + @Nullable + public String getOutputUrl() { + JpsModule module = getModuleReference().resolve(); + if (module == null) return null; + return getOutputUrl(module); + } + + @Nullable + protected abstract String getOutputUrl(@NotNull JpsModule module); +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsPackagingElementFactoryImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsPackagingElementFactoryImpl.java new file mode 100644 index 000000000000..62c0de6379cc --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/elements/JpsPackagingElementFactoryImpl.java @@ -0,0 +1,95 @@ +package org.jetbrains.jps.model.artifact.impl.elements; + +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.artifact.JpsArtifactReference; +import org.jetbrains.jps.model.artifact.elements.*; +import org.jetbrains.jps.model.library.JpsLibraryReference; + +/** + * @author nik + */ +public class JpsPackagingElementFactoryImpl extends JpsPackagingElementFactory { + + @Override + @NotNull + public JpsDirectoryCopyPackagingElement createDirectoryCopy(@NotNull String directoryPath) { + return new JpsDirectoryCopyPackagingElementImpl(directoryPath); + } + + @Override + public JpsPackagingElement createParentDirectories(String relativeOutputPath, JpsPackagingElement element) { + relativeOutputPath = StringUtil.trimStart(relativeOutputPath, "/"); + if (relativeOutputPath.length() == 0) { + return element; + } + int slash = relativeOutputPath.indexOf('/'); + if (slash == -1) slash = relativeOutputPath.length(); + String rootName = relativeOutputPath.substring(0, slash); + String pathTail = relativeOutputPath.substring(slash); + final JpsDirectoryPackagingElement root = createDirectory(rootName); + final JpsCompositePackagingElement last = getOrCreateDirectoryOrArchive(root, pathTail, true); + last.addChild(element); + return root; + } + + @NotNull + private JpsCompositePackagingElement getOrCreateDirectoryOrArchive(@NotNull JpsCompositePackagingElement root, + @NotNull @NonNls String path, final boolean directory) { + path = StringUtil.trimStart(StringUtil.trimEnd(path, "/"), "/"); + if (path.length() == 0) { + return root; + } + int index = path.lastIndexOf('/'); + String lastName = path.substring(index + 1); + String parentPath = index != -1 ? path.substring(0, index) : ""; + + final JpsCompositePackagingElement parent = getOrCreateDirectoryOrArchive(root, parentPath, true); + final JpsCompositePackagingElement last = directory ? createDirectory(lastName) : createArchive(lastName); + return parent.addChild(last); + } + + @Override + @NotNull + public JpsFileCopyPackagingElement createFileCopy(@NotNull String filePath, @Nullable String outputFileName) { + return new JpsFileCopyPackagingElementImpl(filePath, outputFileName); + } + + @Override + @NotNull + public JpsExtractedDirectoryPackagingElement createExtractedDirectory(@NotNull String jarPath, @NotNull String pathInJar) { + return new JpsExtractedDirectoryPackagingElementImpl(jarPath, pathInJar); + } + + @Override + @NotNull + public JpsDirectoryPackagingElement createDirectory(@NotNull String directoryName) { + return new JpsDirectoryPackagingElementImpl(directoryName); + } + + @Override + @NotNull + public JpsArchivePackagingElement createArchive(@NotNull String archiveName) { + return new JpsArchivePackagingElementImpl(archiveName); + } + + @Override + @NotNull + public JpsArtifactRootElement createArtifactRoot() { + return new JpsArtifactRootElementImpl(); + } + + @Override + @NotNull + public JpsLibraryFilesPackagingElement createLibraryElement(@NotNull JpsLibraryReference reference) { + return new JpsLibraryFilesPackagingElementImpl(reference); + } + + @Override + @NotNull + public JpsArtifactOutputPackagingElement createArtifactOutput(@NotNull JpsArtifactReference reference) { + return new JpsArtifactOutputPackagingElementImpl(reference); + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaExtensionServiceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaExtensionServiceImpl.java index db46e70af118..d1b084eaa6b0 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaExtensionServiceImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsJavaExtensionServiceImpl.java @@ -8,6 +8,7 @@ import org.jetbrains.jps.model.JpsProject; import org.jetbrains.jps.model.java.*; import org.jetbrains.jps.model.module.JpsDependencyElement; import org.jetbrains.jps.model.module.JpsModule; +import org.jetbrains.jps.model.module.JpsModuleReference; import org.jetbrains.jps.model.module.JpsModuleSourceRoot; import java.util.ArrayList; @@ -123,4 +124,16 @@ public class JpsJavaExtensionServiceImpl extends JpsJavaExtensionService { } return null; } + + @Override + @NotNull + public JpsProductionModuleOutputPackagingElement createProductionModuleOutput(@NotNull JpsModuleReference moduleReference) { + return new JpsProductionModuleOutputPackagingElementImpl(moduleReference); + } + + @Override + @NotNull + public JpsTestModuleOutputPackagingElement createTestModuleOutput(@NotNull JpsModuleReference moduleReference) { + return new JpsTestModuleOutputPackagingElementImpl(moduleReference); + } } diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsProductionModuleOutputPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsProductionModuleOutputPackagingElementImpl.java new file mode 100644 index 000000000000..57b700ce88a8 --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsProductionModuleOutputPackagingElementImpl.java @@ -0,0 +1,33 @@ +package org.jetbrains.jps.model.java.impl; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.artifact.impl.elements.JpsModuleOutputPackagingElementBase; +import org.jetbrains.jps.model.java.JpsJavaExtensionService; +import org.jetbrains.jps.model.java.JpsProductionModuleOutputPackagingElement; +import org.jetbrains.jps.model.module.JpsModule; +import org.jetbrains.jps.model.module.JpsModuleReference; + +/** + * @author nik + */ +public class JpsProductionModuleOutputPackagingElementImpl extends JpsModuleOutputPackagingElementBase + implements JpsProductionModuleOutputPackagingElement { + public JpsProductionModuleOutputPackagingElementImpl(JpsModuleReference moduleReference) { + super(moduleReference); + } + + private JpsProductionModuleOutputPackagingElementImpl(JpsProductionModuleOutputPackagingElementImpl original) { + super(original); + } + + @NotNull + @Override + public JpsProductionModuleOutputPackagingElementImpl createCopy() { + return new JpsProductionModuleOutputPackagingElementImpl(this); + } + + @Override + protected String getOutputUrl(@NotNull JpsModule module) { + return JpsJavaExtensionService.getInstance().getOutputUrl(module, false); + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsTestModuleOutputPackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsTestModuleOutputPackagingElementImpl.java new file mode 100644 index 000000000000..2199ab934210 --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsTestModuleOutputPackagingElementImpl.java @@ -0,0 +1,33 @@ +package org.jetbrains.jps.model.java.impl; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.artifact.impl.elements.JpsModuleOutputPackagingElementBase; +import org.jetbrains.jps.model.java.JpsJavaExtensionService; +import org.jetbrains.jps.model.java.JpsTestModuleOutputPackagingElement; +import org.jetbrains.jps.model.module.JpsModule; +import org.jetbrains.jps.model.module.JpsModuleReference; + +/** + * @author nik + */ +public class JpsTestModuleOutputPackagingElementImpl extends JpsModuleOutputPackagingElementBase + implements JpsTestModuleOutputPackagingElement { + public JpsTestModuleOutputPackagingElementImpl(JpsModuleReference moduleReference) { + super(moduleReference); + } + + private JpsTestModuleOutputPackagingElementImpl(JpsTestModuleOutputPackagingElementImpl original) { + super(original); + } + + @NotNull + @Override + public JpsTestModuleOutputPackagingElementImpl createCopy() { + return new JpsTestModuleOutputPackagingElementImpl(this); + } + + @Override + protected String getOutputUrl(@NotNull JpsModule module) { + return JpsJavaExtensionService.getInstance().getOutputUrl(module, true); + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryImpl.java index fb5b9b14ec20..1c100c760ce7 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryImpl.java @@ -1,10 +1,15 @@ package org.jetbrains.jps.model.library.impl; +import com.intellij.openapi.util.io.FileUtilRt; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.JpsPathUtil; import org.jetbrains.jps.model.*; import org.jetbrains.jps.model.impl.*; import org.jetbrains.jps.model.library.*; +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; @@ -94,4 +99,41 @@ public class JpsLibraryImpl

extends JpsNamedComp ((JpsReferenceableElement)getParent().getParent()).createReference(); return new JpsLibraryReferenceImpl(getName(), parentReference); } + + @Override + public List getFiles(final JpsOrderRootType rootType) { + List files = new ArrayList(); + for (JpsLibraryRoot root : getRoots(rootType)) { + final File file = JpsPathUtil.urlToFile(root.getUrl()); + switch (root.getInclusionOptions()) { + case ROOT_ITSELF: + files.add(file); + break; + case ARCHIVES_UNDER_ROOT: + collectArchives(file, false, files); + break; + case ARCHIVES_UNDER_ROOT_RECURSIVELY: + collectArchives(file, true, files); + break; + } + } + return files; + } + + private static void collectArchives(File file, boolean recursively, Collection result) { + final File[] children = file.listFiles(); + if (children != null) { + for (File child : children) { + final String extension = FileUtilRt.getExtension(child.getName()); + if (child.isDirectory()) { + if (recursively) { + collectArchives(child, recursively, result); + } + } + else if (extension.equals("jar") || extension.equals("zip")) { + result.add(child); + } + } + } + } } diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModelLoaderExtension.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModelLoaderExtension.java index 72cf3483a712..f1a634917e45 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModelLoaderExtension.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModelLoaderExtension.java @@ -6,9 +6,11 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.JpsCompositeElement; import org.jetbrains.jps.model.JpsElementReference; import org.jetbrains.jps.model.JpsProject; +import org.jetbrains.jps.model.artifact.JpsArtifactType; import org.jetbrains.jps.model.library.JpsOrderRootType; import org.jetbrains.jps.model.module.JpsDependencyElement; import org.jetbrains.jps.model.module.JpsModule; +import org.jetbrains.jps.model.serialization.artifact.JpsPackagingElementLoader; import org.jetbrains.jps.model.serialization.facet.JpsModuleExtensionLoader; import java.util.Collections; @@ -57,8 +59,17 @@ public abstract class JpsModelLoaderExtension { return Collections.emptyList(); } + public List> getPackagingElementLoaders() { + return Collections.emptyList(); + } + @Nullable public JpsOrderRootType getSdkRootType(@NotNull String typeId) { return null; } + + @Nullable + public JpsArtifactType getArtifactType(@NotNull String typeId) { + return null; + } } diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModuleLoader.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModuleLoader.java index a7f5289ac162..aae1daef722d 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModuleLoader.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModuleLoader.java @@ -93,7 +93,7 @@ public class JpsModuleLoader { } } - private static JpsElementReference createLibraryTableReference(String level) { + public static JpsElementReference createLibraryTableReference(String level) { JpsElementFactory elementFactory = JpsElementFactory.getInstance(); if (level.equals("project")) { return elementFactory.createProjectReference(); diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java index fac9f2ab232d..59ac7a38c855 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java @@ -2,6 +2,7 @@ package org.jetbrains.jps.model.serialization; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.ArrayUtil; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -12,10 +13,12 @@ import org.jetbrains.jps.model.JpsProject; import org.jetbrains.jps.model.java.JpsJavaModuleType; import org.jetbrains.jps.model.library.JpsSdkType; import org.jetbrains.jps.model.module.JpsModule; +import org.jetbrains.jps.model.serialization.artifact.JpsArtifactLoader; import org.jetbrains.jps.model.serialization.facet.JpsFacetLoader; import org.jetbrains.jps.service.JpsServiceManager; import java.io.File; +import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -68,14 +71,23 @@ public class JpsProjectLoader extends JpsLoaderBase { private void loadFromDirectory(File dir) { JpsSdkType projectSdkType = loadProjectRoot(loadRootElement(new File(dir, "misc.xml"))); loadModules(loadRootElement(new File(dir, "modules.xml")), projectSdkType); - final File[] libraryFiles = new File(dir, "libraries").listFiles(); - if (libraryFiles != null) { - for (File libraryFile : libraryFiles) { - if (isXmlFile(libraryFile)) { - loadProjectLibraries(loadRootElement(libraryFile)); - } - } + for (File libraryFile : listXmlFiles(new File(dir, "libraries"))) { + loadProjectLibraries(loadRootElement(libraryFile)); } + for (File artifactFile : listXmlFiles(new File(dir, "artifacts"))) { + loadArtifacts(loadRootElement(artifactFile)); + } + } + + @NotNull + private static File[] listXmlFiles(final File dir) { + File[] files = dir.listFiles(new FileFilter() { + @Override + public boolean accept(File file) { + return isXmlFile(file); + } + }); + return files != null ? files : ArrayUtil.EMPTY_FILE_ARRAY; } private void loadFromIpr(File iprFile) { @@ -83,6 +95,11 @@ public class JpsProjectLoader extends JpsLoaderBase { JpsSdkType projectSdkType = loadProjectRoot(root); loadModules(root, projectSdkType); loadProjectLibraries(findComponent(root, "libraryTable")); + loadArtifacts(findComponent(root, "ArtifactManager")); + } + + private void loadArtifacts(Element artifactManagerComponent) { + JpsArtifactLoader.loadArtifacts(myProject, artifactManagerComponent); } @Nullable diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerState.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactManagerState.java similarity index 95% rename from java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerState.java rename to jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactManagerState.java index 92b26d1e22ab..d6591845e838 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactManagerState.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactManagerState.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.packaging.impl.artifacts; +package org.jetbrains.jps.model.serialization.artifact; import com.intellij.util.xmlb.annotations.AbstractCollection; import com.intellij.util.xmlb.annotations.Property; diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactPropertiesState.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactPropertiesState.java similarity index 95% rename from java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactPropertiesState.java rename to jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactPropertiesState.java index 597997f52486..7dca3c58f751 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactPropertiesState.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactPropertiesState.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.packaging.impl.artifacts; +package org.jetbrains.jps.model.serialization.artifact; import com.intellij.util.xmlb.annotations.Attribute; import com.intellij.util.xmlb.annotations.Tag; diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactState.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactState.java similarity index 95% rename from java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactState.java rename to jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactState.java index f9e58053b330..2d7c02a5f385 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactState.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/ArtifactState.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.packaging.impl.artifacts; +package org.jetbrains.jps.model.serialization.artifact; import com.intellij.util.xmlb.annotations.Attribute; import com.intellij.util.xmlb.annotations.Tag; @@ -33,7 +33,7 @@ public class ArtifactState { @NonNls public static final String NAME_ATTRIBUTE = "name"; private String myName; private String myOutputPath; - private String myArtifactType = PlainArtifactType.ID; + private String myArtifactType; private boolean myBuildOnMake; private Element myRootElement; private List myPropertiesList = new ArrayList(); diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactLoader.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactLoader.java new file mode 100644 index 000000000000..15534c5fcf35 --- /dev/null +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsArtifactLoader.java @@ -0,0 +1,136 @@ +package org.jetbrains.jps.model.serialization.artifact; + +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.util.xmlb.XmlSerializer; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.JpsCompositeElement; +import org.jetbrains.jps.model.JpsElementFactory; +import org.jetbrains.jps.model.JpsElementReference; +import org.jetbrains.jps.model.JpsProject; +import org.jetbrains.jps.model.artifact.*; +import org.jetbrains.jps.model.artifact.elements.JpsCompositePackagingElement; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElementFactory; +import org.jetbrains.jps.model.serialization.JpsModelLoaderExtension; +import org.jetbrains.jps.model.serialization.JpsModuleLoader; +import org.jetbrains.jps.service.JpsServiceManager; + +import java.util.Arrays; +import java.util.List; + +/** + * @author nik + */ +public class JpsArtifactLoader { + private static List> STANDARD_LOADERS = Arrays.asList(); + + public static void loadArtifacts(@NotNull JpsProject project, @Nullable Element componentElement) { + JpsArtifactService service = JpsArtifactService.getInstance(); + for (Element artifactElement : JDOMUtil.getChildren(componentElement, "artifact")) { + ArtifactState state = XmlSerializer.deserialize(artifactElement, ArtifactState.class); + if (state == null) continue; + JpsArtifactType artifactType = getArtifactType(state.getArtifactType()); + JpsPackagingElement rootElement = loadPackagingElement(state.getRootElement()); + if (rootElement != null) { + JpsArtifact artifact = service.addArtifact(project, state.getName(), (JpsCompositePackagingElement)rootElement, artifactType); + artifact.setOutputPath(state.getOutputPath()); + } + } + } + + @Nullable + private static JpsPackagingElement loadPackagingElement(Element element) { + JpsPackagingElement packagingElement = createPackagingElement(element); + if (packagingElement instanceof JpsCompositePackagingElement) { + for (Element childElement : JDOMUtil.getChildren(element, "element")) { + JpsPackagingElement child = loadPackagingElement(childElement); + if (child != null) { + ((JpsCompositePackagingElement)packagingElement).addChild(child); + } + } + } + return packagingElement; + } + + @Nullable + private static JpsPackagingElement createPackagingElement(Element element) { + String typeId = element.getAttributeValue("id"); + JpsPackagingElementFactory factory = JpsPackagingElementFactory.getInstance(); + if (typeId.equals("root")) { + return factory.createArtifactRoot(); + } + if (typeId.equals("directory")) { + return factory.createDirectory(element.getAttributeValue("name")); + } + if (typeId.equals("archive")) { + return factory.createArchive(element.getAttributeValue("name")); + } + if (typeId.equals("file-copy")) { + return factory.createFileCopy(element.getAttributeValue("path"), + element.getAttributeValue("output-file-name")); + } + if (typeId.equals("dir-copy")) { + return factory.createDirectoryCopy(element.getAttributeValue("path")); + } + if (typeId.equals("extracted-dir")) { + return factory.createExtractedDirectory(element.getAttributeValue("path"), + element.getAttributeValue("path-in-jar")); + } + if (typeId.equals("library")) { + String level = element.getAttributeValue("level"); + String libraryName = element.getAttributeValue("name"); + String moduleName = element.getAttributeValue("module-name"); + JpsElementReference parentReference; + if (moduleName != null) { + parentReference = JpsElementFactory.getInstance().createModuleReference(moduleName); + } + else { + parentReference = JpsModuleLoader.createLibraryTableReference(level); + } + return factory.createLibraryElement(JpsElementFactory.getInstance().createLibraryReference(libraryName, parentReference)); + } + if (typeId.equals("artifact")) { + return factory.createArtifactOutput(JpsArtifactService.getInstance().createReference(element.getAttributeValue("artifact-name"))); + } + JpsPackagingElementLoader loader = findElementLoader(typeId); + if (loader != null) { + return loader.load(element); + } + return null; + } + + private static JpsArtifactType getArtifactType(@Nullable String typeId) { + if (typeId == null || "plain".equals(typeId)) { + return DirectoryArtifactType.INSTANCE; + } + if (typeId.equals("jar")) { + return JarArtifactType.INSTANCE; + } + for (JpsModelLoaderExtension extension : JpsServiceManager.getInstance().getExtensions(JpsModelLoaderExtension.class)) { + JpsArtifactType type = extension.getArtifactType(typeId); + if (type != null) { + return type; + } + } + return DirectoryArtifactType.INSTANCE; + } + + @Nullable + private static JpsPackagingElementLoader findElementLoader(@NotNull String typeId) { + for (JpsPackagingElementLoader loader : STANDARD_LOADERS) { + if (loader.getTypeId().equals(typeId)) { + return loader; + } + } + for (JpsModelLoaderExtension extension : JpsServiceManager.getInstance().getExtensions(JpsModelLoaderExtension.class)) { + for (JpsPackagingElementLoader loader : extension.getPackagingElementLoaders()) { + if (loader.getTypeId().equals(typeId)) { + return loader; + } + } + } + return null; + } +} diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsPackagingElementLoader.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsPackagingElementLoader.java new file mode 100644 index 000000000000..3aca2b9751ab --- /dev/null +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/artifact/JpsPackagingElementLoader.java @@ -0,0 +1,21 @@ +package org.jetbrains.jps.model.serialization.artifact; + +import org.jdom.Element; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; + +/** + * @author nik + */ +public abstract class JpsPackagingElementLoader { + private final String myTypeId; + + protected JpsPackagingElementLoader(String typeId) { + myTypeId = typeId; + } + + public String getTypeId() { + return myTypeId; + } + + public abstract E load(Element element); +} diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelLoaderExtension.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelLoaderExtension.java index 23b449144c66..794e853097a9 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelLoaderExtension.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelLoaderExtension.java @@ -3,6 +3,7 @@ package org.jetbrains.jps.model.serialization.java; import com.intellij.openapi.util.JDOMUtil; import org.jdom.Element; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.JpsElementFactory; import org.jetbrains.jps.model.JpsProject; import org.jetbrains.jps.model.JpsUrlList; import org.jetbrains.jps.model.java.*; @@ -10,6 +11,10 @@ import org.jetbrains.jps.model.library.JpsOrderRootType; import org.jetbrains.jps.model.module.JpsDependencyElement; import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.model.serialization.JpsModelLoaderExtension; +import org.jetbrains.jps.model.serialization.artifact.JpsPackagingElementLoader; + +import java.util.Arrays; +import java.util.List; /** * @author nik @@ -74,6 +79,11 @@ public class JpsJavaModelLoaderExtension extends JpsModelLoaderExtension { return null; } + @Override + public List> getPackagingElementLoaders() { + return Arrays.asList(new JpsModuleOutputPackagingElementLoader(), new JpsTestModuleOutputPackagingElementLoader()); + } + private static void loadExplodedDirectoryExtension(JpsModule module, Element rootModelComponent) { final Element exploded = rootModelComponent.getChild("exploded"); if (exploded != null) { @@ -112,4 +122,27 @@ public class JpsJavaModelLoaderExtension extends JpsModelLoaderExtension { result.addUrl(root.getAttributeValue("url")); } } + + private static class JpsModuleOutputPackagingElementLoader extends JpsPackagingElementLoader { + private JpsModuleOutputPackagingElementLoader() { + super("module-output"); + } + + @Override + public JpsProductionModuleOutputPackagingElement load(Element element) { + return JpsJavaExtensionService.getInstance().createProductionModuleOutput(JpsElementFactory.getInstance().createModuleReference(element.getAttributeValue("name"))); + } + } + + private static class JpsTestModuleOutputPackagingElementLoader extends JpsPackagingElementLoader { + private JpsTestModuleOutputPackagingElementLoader() { + super("module-test-output"); + } + + @Override + public JpsTestModuleOutputPackagingElement load(Element element) { + return JpsJavaExtensionService.getInstance().createTestModuleOutput( + JpsElementFactory.getInstance().createModuleReference(element.getAttributeValue("name"))); + } + } } diff --git a/jps/model/jps-model.iml b/jps/model/jps-model.iml index 64cff6c7c701..3571c5219fe6 100644 --- a/jps/model/jps-model.iml +++ b/jps/model/jps-model.iml @@ -11,6 +11,7 @@ + diff --git a/jps/model/src/org/jetbrains/jps/Project.groovy b/jps/model/src/org/jetbrains/jps/Project.groovy index 82f1e7081bbe..10857b12892e 100644 --- a/jps/model/src/org/jetbrains/jps/Project.groovy +++ b/jps/model/src/org/jetbrains/jps/Project.groovy @@ -1,5 +1,4 @@ package org.jetbrains.jps -import org.jetbrains.jps.artifacts.Artifact /** * @author max */ @@ -7,7 +6,6 @@ class Project { String projectName int locationHash - final Map artifacts = [:] final Map runConfigurations = [:] final CompilerConfiguration compilerConfiguration = new CompilerConfiguration() final UiDesignerConfiguration uiDesignerConfiguration = new UiDesignerConfiguration() diff --git a/jps/model/src/org/jetbrains/jps/ProjectPaths.java b/jps/model/src/org/jetbrains/jps/ProjectPaths.java index b009a5539cf5..b464985de0aa 100644 --- a/jps/model/src/org/jetbrains/jps/ProjectPaths.java +++ b/jps/model/src/org/jetbrains/jps/ProjectPaths.java @@ -10,7 +10,6 @@ import org.jetbrains.jps.model.java.JavaSourceRootType; import org.jetbrains.jps.model.java.JpsJavaClasspathKind; import org.jetbrains.jps.model.java.JpsJavaExtensionService; import org.jetbrains.jps.model.library.JpsLibrary; -import org.jetbrains.jps.model.library.JpsLibraryRoot; import org.jetbrains.jps.model.library.JpsOrderRootType; import org.jetbrains.jps.model.module.*; @@ -25,17 +24,10 @@ public class ProjectPaths { private static final String DEFAULT_GENERATED_DIR_NAME = "generated"; @NotNull private final JpsProject myProject; - @Nullable - private final File myProjectTargetDir; //private final Map>> myCachedClasspath = new HashMap>>(); public ProjectPaths(JpsProject project) { - this(project, null); - } - - public ProjectPaths(JpsProject project, @Nullable File projectTargetDir) { myProject = project; - myProjectTargetDir = projectTargetDir; } public Collection getClasspathFiles(JpsModule module, JpsJavaClasspathKind kind) { @@ -114,39 +106,9 @@ public class ProjectPaths { } } - public static void addLibraryFiles(Collection classpath, @Nullable JpsLibrary library) { + private static void addLibraryFiles(Set classpath, @Nullable JpsLibrary library) { if (library != null) { - for (JpsLibraryRoot root : library.getRoots(JpsOrderRootType.COMPILED)) { - final File file = JpsPathUtil.urlToFile(root.getUrl()); - switch (root.getInclusionOptions()) { - case ROOT_ITSELF: - classpath.add(file); - break; - case ARCHIVES_UNDER_ROOT: - collectArchives(file, false, classpath); - break; - case ARCHIVES_UNDER_ROOT_RECURSIVELY: - collectArchives(file, true, classpath); - break; - } - } - } - } - - private static void collectArchives(File file, boolean recursively, Collection result) { - final File[] children = file.listFiles(); - if (children != null) { - for (File child : children) { - final String extension = FileUtil.getExtension(child.getName()); - if (child.isDirectory()) { - if (recursively) { - collectArchives(child, recursively, result); - } - } - else if (extension.equals("jar") || extension.equals("zip")) { - result.add(child); - } - } + classpath.addAll(library.getFiles(JpsOrderRootType.COMPILED)); } } @@ -259,11 +221,6 @@ public class ProjectPaths { @Nullable public File getModuleOutputDir(JpsModule module, boolean forTests) { - if (myProjectTargetDir != null) { - final File basePath = new File(myProjectTargetDir, forTests ? "test" : "production"); - return new File(basePath, module.getName()); - } - final String url = JpsJavaExtensionService.getInstance().getOutputUrl(module, forTests); return url != null ? JpsPathUtil.urlToFile(url) : null; } diff --git a/jps/model/src/org/jetbrains/jps/artifacts/Artifact.groovy b/jps/model/src/org/jetbrains/jps/artifacts/Artifact.groovy deleted file mode 100644 index d8ec4a2f8891..000000000000 --- a/jps/model/src/org/jetbrains/jps/artifacts/Artifact.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package org.jetbrains.jps.artifacts - -/** - * @author nik - */ -class Artifact { - String name - LayoutElement rootElement - String outputPath - Map properties; - - def String toString() { - return "artifact '$name'" - } -} diff --git a/jps/model/src/org/jetbrains/jps/artifacts/ArtifactProperties.groovy b/jps/model/src/org/jetbrains/jps/artifacts/ArtifactProperties.groovy deleted file mode 100644 index dbfbcfee9197..000000000000 --- a/jps/model/src/org/jetbrains/jps/artifacts/ArtifactProperties.groovy +++ /dev/null @@ -1,7 +0,0 @@ -package org.jetbrains.jps.artifacts - -/** - * @author nik - */ -interface ArtifactProperties { -} diff --git a/jps/model/src/org/jetbrains/jps/artifacts/ArtifactPropertiesProviderService.groovy b/jps/model/src/org/jetbrains/jps/artifacts/ArtifactPropertiesProviderService.groovy deleted file mode 100644 index 719968d42519..000000000000 --- a/jps/model/src/org/jetbrains/jps/artifacts/ArtifactPropertiesProviderService.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package org.jetbrains.jps.artifacts - -import org.jetbrains.jps.MacroExpander - -/** - * @author nik - */ -abstract class ArtifactPropertiesProviderService

{ - final String id - - ArtifactPropertiesProviderService(String id) { - this.id = id - } - - abstract P loadProperties(Node node, MacroExpander macroExpander) -} diff --git a/jps/model/src/org/jetbrains/jps/artifacts/ComplexLayoutElement.groovy b/jps/model/src/org/jetbrains/jps/artifacts/ComplexLayoutElement.groovy deleted file mode 100644 index 5353a3298b43..000000000000 --- a/jps/model/src/org/jetbrains/jps/artifacts/ComplexLayoutElement.groovy +++ /dev/null @@ -1,79 +0,0 @@ -package org.jetbrains.jps.artifacts - -import org.jetbrains.jps.Project -import org.jetbrains.jps.ProjectPaths -import org.jetbrains.jps.idea.ProjectLoadingErrorReporter -import org.jetbrains.jps.model.JpsModel -import org.jetbrains.jps.model.library.JpsLibrary -import org.jetbrains.jps.model.library.JpsLibraryCollection -/** - * @author nik - */ -abstract class ComplexLayoutElement extends LayoutElement { - abstract List getSubstitution(Project project, JpsModel model) - - boolean process(Project project, JpsModel model, Closure processor) { - if (processor(this)) { - getSubstitution(project, model)*.process(project, model, processor) - } - } -} - -class LibraryFilesElement extends ComplexLayoutElement { - public static final String PROJECT_LEVEL = "project" - String moduleName - String libraryName - String libraryLevel - - List getSubstitution(Project project, JpsModel model) { - JpsLibraryCollection libraries = null - switch (libraryLevel) { - case PROJECT_LEVEL: - libraries = model.project.libraryCollection - break - case "module": - libraries = model.project.modules.find {it.name.equals(moduleName)}?.libraryCollection - break - case "application": - libraries = model.global.libraryCollection - break - } - JpsLibrary library = libraries?.findLibrary(libraryName) - if (library == null) { - return [] - } - - List files = new ArrayList() - ProjectPaths.addLibraryFiles(files, library) - return files.collect {File file -> - if (file.isDirectory()) { - return new DirectoryCopyElement(dirPath: file.absolutePath) - } - else { - return new FileCopyElement(filePath: file.absolutePath) - } - } - } -} - -class ArtifactLayoutElement extends ComplexLayoutElement { - String artifactName - ProjectLoadingErrorReporter errorReporter - - List getSubstitution(Project project, JpsModel model) { - Artifact artifact = project.artifacts[artifactName] - if (artifact == null) { - errorReporter.error("unknown artifact: $artifactName") - return [] - } - def root = artifact.rootElement - if (root instanceof RootElement) { - return ((RootElement)root).children - } - return [root] - } - - Artifact findArtifact(Project project) { - return project.artifacts[artifactName] - } -} diff --git a/jps/model/src/org/jetbrains/jps/artifacts/CompositeLayoutElement.groovy b/jps/model/src/org/jetbrains/jps/artifacts/CompositeLayoutElement.groovy deleted file mode 100644 index f7d0b3b4939b..000000000000 --- a/jps/model/src/org/jetbrains/jps/artifacts/CompositeLayoutElement.groovy +++ /dev/null @@ -1,46 +0,0 @@ -package org.jetbrains.jps.artifacts - -import org.jetbrains.jps.Project -import org.jetbrains.jps.model.JpsModel -/** - * @author nik - */ -abstract class CompositeLayoutElement extends LayoutElement { - String name - protected final List children = [] - - List getChildren() { - return children - } - - LayoutElement leftShift(LayoutElement child) { - children << child - return child - } - - boolean process(Project project, JpsModel model, Closure processor) { - if (processor(this)) { - children*.process(project, model, processor) - } - } -} - -class RootElement extends CompositeLayoutElement { - def RootElement(List children) { - this.children.addAll(children) - } -} - -class DirectoryElement extends CompositeLayoutElement { - def DirectoryElement(String name, List children) { - this.name = name - this.children.addAll(children) - } -} - -class ArchiveElement extends CompositeLayoutElement { - def ArchiveElement(String name, List children) { - this.name = name - this.children.addAll(children) - } -} diff --git a/jps/model/src/org/jetbrains/jps/artifacts/LayoutElement.groovy b/jps/model/src/org/jetbrains/jps/artifacts/LayoutElement.groovy deleted file mode 100644 index 05a30cf1948e..000000000000 --- a/jps/model/src/org/jetbrains/jps/artifacts/LayoutElement.groovy +++ /dev/null @@ -1,49 +0,0 @@ -package org.jetbrains.jps.artifacts -import org.jetbrains.jps.Project -import org.jetbrains.jps.model.JpsModel -/** - * @author nik - */ -abstract class LayoutElement { - boolean process(Project project, JpsModel model, Closure processor) { - return processor(this) - } -} - -class FileCopyElement extends LayoutElement { - String filePath - String outputFileName - - FileCopyElement() { - } - - FileCopyElement(String filePath, String outputFileName) { - this.filePath = filePath - this.outputFileName = outputFileName - } -} - -class DirectoryCopyElement extends LayoutElement { - DirectoryCopyElement() { - } - - DirectoryCopyElement(String dirPath) { - this.dirPath = dirPath - } - - String dirPath -} - -class ExtractedDirectoryElement extends LayoutElement { - String jarPath - String pathInJar -} - -class ModuleOutputElement extends LayoutElement { - String moduleName - -} - -class ModuleTestOutputElement extends LayoutElement { - String moduleName -} diff --git a/jps/model/src/org/jetbrains/jps/artifacts/LayoutElementFactory.groovy b/jps/model/src/org/jetbrains/jps/artifacts/LayoutElementFactory.groovy deleted file mode 100644 index 96cc3c283177..000000000000 --- a/jps/model/src/org/jetbrains/jps/artifacts/LayoutElementFactory.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package org.jetbrains.jps.artifacts - -/** - * @author nik - */ -class LayoutElementFactory { - - static LayoutElement createParentDirectories(String path, LayoutElement element) { - def result = element - path.split("/").reverseEach { - if (it != "") { - result = new DirectoryElement(it, [result]) - } - } - return result - } - -} diff --git a/jps/model/src/org/jetbrains/jps/artifacts/LayoutElementTypeService.java b/jps/model/src/org/jetbrains/jps/artifacts/LayoutElementTypeService.java deleted file mode 100644 index a9c15ffe72e1..000000000000 --- a/jps/model/src/org/jetbrains/jps/artifacts/LayoutElementTypeService.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.jetbrains.jps.artifacts; - -import groovy.util.Node; -import org.jetbrains.jps.MacroExpander; -import org.jetbrains.jps.Project; -import org.jetbrains.jps.idea.ProjectLoadingErrorReporter; - -/** - * @author nik - */ -public abstract class LayoutElementTypeService { - private final String typeId; - - protected LayoutElementTypeService(String typeId) { - this.typeId = typeId; - } - - public String getTypeId() { - return typeId; - } - - public abstract LayoutElement createElement(Project project, Node tag, MacroExpander macroExpander, ProjectLoadingErrorReporter errorReporter); -} diff --git a/jps/model/src/org/jetbrains/jps/idea/ArtifactLoader.groovy b/jps/model/src/org/jetbrains/jps/idea/ArtifactLoader.groovy deleted file mode 100644 index a99a37bbc4dd..000000000000 --- a/jps/model/src/org/jetbrains/jps/idea/ArtifactLoader.groovy +++ /dev/null @@ -1,125 +0,0 @@ -package org.jetbrains.jps.idea - -import org.jetbrains.jps.MacroExpander -import org.jetbrains.jps.Project -import org.jetbrains.jps.artifacts.* - - /** - * @author nik - */ -class ArtifactLoader { - private final Project project - private final MacroExpander macroExpander - private static OwnServiceLoader elementTypeLoader = OwnServiceLoader.load(LayoutElementTypeService.class) - private static OwnServiceLoader propertiesProvidersLoader = OwnServiceLoader.load(ArtifactPropertiesProviderService.class) - private static Map elementTypes = null - private static Map propertiesProviders = null - private final ProjectLoadingErrorReporter errorReporter - - def ArtifactLoader(Project project, MacroExpander macroExpander, ProjectLoadingErrorReporter errorReporter) { - this.macroExpander = macroExpander - this.project = project - this.errorReporter = errorReporter - } - - LayoutElement loadLayoutElement(Node tag, String artifactName) { - String id = tag."@id"; - switch (id) { - case "root": - return new RootElement(loadChildren(tag, artifactName)); - case "directory": - return new DirectoryElement(tag."@name", loadChildren(tag, artifactName)); - case "archive": - return new ArchiveElement(tag."@name", loadChildren(tag, artifactName)); - case "artifact": - return new ArtifactLayoutElement(artifactName: tag."@artifact-name", errorReporter: errorReporter) - case "file-copy": - def path = macroExpander.expandMacros(tag."@path") - if (!new File(path).exists()) { - errorReporter.warning("Error in '$artifactName' artifact: file '$path' doesn't exist") - } - return new FileCopyElement(filePath: path, - outputFileName: tag."@output-file-name"); - case "dir-copy": - def path = macroExpander.expandMacros(tag."@path") - if (!new File(path).exists()) { - errorReporter.warning("Error in '$artifactName' artifact: directory '$path' doesn't exist") - } - return new DirectoryCopyElement(dirPath: path); - case "extracted-dir": - def jarPath = macroExpander.expandMacros(tag."@path") - String pathInJar = tag."@path-in-jar" - if (pathInJar == null) pathInJar = "/" - if (!new File(jarPath).exists()) { - errorReporter.warning("Error in '$artifactName' artifact: file '$jarPath' doesn't exist") - } - return new ExtractedDirectoryElement(jarPath: jarPath, pathInJar: pathInJar) - case "module-output": - def name = tag."@name" - return new ModuleOutputElement(moduleName: name); - case "module-test-output": - def name = tag."@name" - return new ModuleTestOutputElement(moduleName: name); - case "library": - return new LibraryFilesElement(libraryLevel: tag."@level", libraryName: tag."@name", moduleName: tag."@module-name"); - } - - LayoutElementTypeService type = findType(id) - if (type != null) { - return type.createElement(project, tag, macroExpander, errorReporter) - } - - errorReporter.error("unknown element in '$artifactName' artifact: $id"); - return null - } - - private LayoutElementTypeService findType(String typeId) { - if (elementTypes == null) { - elementTypes = [:] - elementTypeLoader.each {LayoutElementTypeService type -> - elementTypes[type.typeId] = type - } - } - return elementTypes[typeId] - } - - private ArtifactPropertiesProviderService findPropertiesProvider(String id) { - if (propertiesProviders == null) { - propertiesProviders = [:] - propertiesProvidersLoader.each {ArtifactPropertiesProviderService provider -> - propertiesProviders[provider.id] = provider - } - } - return propertiesProviders[id] - } - - Map loadOptions(Node artifactTag, String artifactName) { - def Map res = [:]; - artifactTag.properties.each {Node propertiesNode -> - def String id = propertiesNode."@id"; - ArtifactPropertiesProviderService provider = findPropertiesProvider(id) - if (provider != null) { - try { - res[id] = provider.loadProperties(propertiesNode.options[0], macroExpander) - } catch (Exception e) { - errorReporter.warning("Failed to load properties of the artifact: $artifactName, error: " + e.getMessage()); - } - } - else { - errorReporter.warning("Unknown properties '$id' in '$artifactName' artifact") - } - } - return res; - } - - List loadChildren(Node node, String artifactName) { - List children = [] - node.element.each { - def child = loadLayoutElement(it, artifactName) - if (child != null) { - children << child - } - } - return children - } -} diff --git a/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy b/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy index 473eb6304c03..3aa7f6e3cee6 100644 --- a/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy +++ b/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy @@ -2,7 +2,6 @@ package org.jetbrains.jps.idea import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.text.StringUtil import org.jetbrains.jps.* -import org.jetbrains.jps.artifacts.Artifact /** * @author max */ @@ -84,7 +83,6 @@ public class IdeaProjectLoader { loadProjectFileEncodings(root) loadWorkspaceConfiguration(new File(iprFile.parentFile, iprFile.name[0..-4]+"iws")) loadUiDesignerConfiguration(root) - loadArtifacts(getComponent(root, "ArtifactManager")) loadRunConfigurations(getComponent(root, "ProjectRunConfigurationManager")) } @@ -109,16 +107,6 @@ public class IdeaProjectLoader { loadUiDesignerConfiguration(xmlParser.parse(uiDesignerXml)) } - def artifactsFolder = new File(dir, "artifacts") - if (artifactsFolder.isDirectory()) { - artifactsFolder.eachFile {File file -> - if (isXmlFile(file)) { - def artifactsComponent = xmlParser.parse(file) - loadArtifacts(artifactsComponent) - } - } - } - def runConfFolder = new File(dir, "runConfigurations") if (runConfFolder.isDirectory()) { runConfFolder.eachFile {File file -> @@ -296,19 +284,6 @@ public class IdeaProjectLoader { } } - def loadArtifacts(Node artifactsComponent) { - if (artifactsComponent == null) return; - ArtifactLoader artifactLoader = new ArtifactLoader(project, projectMacroExpander, errorReporter) - artifactsComponent.artifact.each {Node artifactTag -> - def artifactName = artifactTag."@name" - def outputPath = projectMacroExpander.expandMacros(artifactTag."output-path"[0]?.text()) - def root = artifactLoader.loadLayoutElement(artifactTag.root[0], artifactName) - def options = artifactLoader.loadOptions(artifactTag, artifactName) - def artifact = new Artifact(name: artifactName, rootElement: root, outputPath: outputPath, properties: options); - project.artifacts[artifact.name] = artifact; - } - } - def loadRunConfigurations(Node runConfManager) { if (runConfManager == null) return; From 7a9eddae63b7029c837a20815a0505100d7d1f7d Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Mon, 23 Jul 2012 18:46:39 +0400 Subject: [PATCH 07/35] IDEA-19061 Integrate the Rearranger-plugin into core-IDEA 1. Arrangement core engine is provided; 2. Arrangement tests infrastructure is provided; 3. Added java-specific support for arrangement by type, name and modifier; 4. Corresponding tests are added; --- .../arrangement/JavaArrangementVisitor.java | 195 +++++++++++++++ .../JavaElementArrangementEntry.java | 93 +++++++ .../codeStyle/arrangement/JavaRearranger.java | 44 ++++ .../arrangement/AbstractRearrangerTest.groovy | 84 +++++++ .../JavaRearrangerByTypeTest.groovy | 178 ++++++++++++++ .../codeStyle/CommonCodeStyleSettings.java | 21 +- .../arrangement/ArrangementEntry.java | 12 + ...mentRuleUtil.java => ArrangementUtil.java} | 81 +++++- .../arrangement/DefaultArrangementEntry.java | 76 ++++++ .../psi/codeStyle/arrangement/Rearranger.java | 12 +- .../match/ByNameArrangementEntryMatcher.java | 4 +- .../match/ModifierAwareArrangementEntry.java | 4 +- .../DefaultArrangementRuleSerializerTest.java | 8 +- .../arrangement/engine/ArrangementEngine.java | 232 ++++++++++++++++++ .../src/META-INF/LangExtensionPoints.xml | 1 + .../src/META-INF/LangExtensions.xml | 2 + .../openapi/util/text/StringUtil.java | 11 + resources/src/META-INF/IdeaPlugin.xml | 3 +- 18 files changed, 1038 insertions(+), 23 deletions(-) create mode 100644 java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java create mode 100644 java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaElementArrangementEntry.java create mode 100644 java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.groovy create mode 100644 java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerByTypeTest.groovy rename platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/{ArrangementRuleUtil.java => ArrangementUtil.java} (64%) create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/DefaultArrangementEntry.java create mode 100644 platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java new file mode 100644 index 000000000000..2ba78bf98153 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java @@ -0,0 +1,195 @@ +/* + * 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.psi.codeStyle.arrangement; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType; +import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier; +import com.intellij.util.containers.Stack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class JavaArrangementVisitor extends JavaElementVisitor { + + private static final Map MODIFIERS = new HashMap(); + static { + MODIFIERS.put(PsiModifier.PUBLIC, ArrangementModifier.PUBLIC); + MODIFIERS.put(PsiModifier.PROTECTED, ArrangementModifier.PROTECTED); + MODIFIERS.put(PsiModifier.PRIVATE, ArrangementModifier.PRIVATE); + MODIFIERS.put(PsiModifier.PACKAGE_LOCAL, ArrangementModifier.PACKAGE_PRIVATE); + MODIFIERS.put(PsiModifier.STATIC, ArrangementModifier.STATIC); + MODIFIERS.put(PsiModifier.FINAL, ArrangementModifier.FINAL); + } + + private final Stack myStack = new Stack(); + + @NotNull private final List myRootEntries; + @NotNull private Document myDocument; + @NotNull private Collection myRanges; + + public JavaArrangementVisitor(@NotNull List entries, + @NotNull Document document, + @NotNull Collection ranges) + { + myRootEntries = entries; + myDocument = document; + myRanges = ranges; + } + + @Override + public void visitClass(PsiClass aClass) { + JavaElementArrangementEntry entry = createNewEntry(aClass.getTextRange(), ArrangementEntryType.CLASS, aClass.getName(), true); + processEntry(entry, aClass, aClass); + } + + @Override + public void visitAnonymousClass(PsiAnonymousClass aClass) { + JavaElementArrangementEntry entry = createNewEntry(aClass.getTextRange(), ArrangementEntryType.CLASS, aClass.getName(), false); + processEntry(entry, null, aClass); + } + + @Override + public void visitJavaFile(PsiJavaFile file) { + for (PsiClass psiClass : file.getClasses()) { + visitClass(psiClass); + } + } + + @Override + public void visitField(PsiField field) { + JavaElementArrangementEntry entry = createNewEntry(field.getTextRange(), ArrangementEntryType.FIELD, field.getName(), true); + processEntry(entry, field, field.getInitializer()); + } + + @Override + public void visitMethod(PsiMethod method) { + JavaElementArrangementEntry entry = createNewEntry(method.getTextRange(), ArrangementEntryType.METHOD, method.getName(), true); + processEntry(entry, method, method.getBody()); + } + + @Override + public void visitExpressionStatement(PsiExpressionStatement statement) { + statement.getExpression().acceptChildren(this); + } + + @Override + public void visitNewExpression(PsiNewExpression expression) { + PsiAnonymousClass anonymousClass = expression.getAnonymousClass(); + if (anonymousClass == null) { + return; + } + JavaElementArrangementEntry entry = + createNewEntry(anonymousClass.getTextRange(), ArrangementEntryType.CLASS, anonymousClass.getName(), false); + processEntry(entry, null, anonymousClass); + } + + @Override + public void visitExpressionList(PsiExpressionList list) { + for (PsiExpression expression : list.getExpressions()) { + expression.acceptChildren(this); + } + } + + @Override + public void visitDeclarationStatement(PsiDeclarationStatement statement) { + for (PsiElement element : statement.getDeclaredElements()) { + element.acceptChildren(this); + } + } + + private void processEntry(@Nullable JavaElementArrangementEntry entry, + @Nullable PsiModifierListOwner modifier, + @Nullable PsiElement nextPsiRoot) + { + if (entry == null) { + return; + } + if (modifier != null) { + parseModifiers(modifier.getModifierList(), entry); + } + if (nextPsiRoot == null) { + return; + } + myStack.push(entry); + try { + nextPsiRoot.acceptChildren(this); + } + finally { + myStack.pop(); + } + } + + @Nullable + private JavaElementArrangementEntry createNewEntry(@NotNull TextRange range, + @NotNull ArrangementEntryType type, + @Nullable String name, + boolean canArrange) + { + if (!isWithinBounds(range)) { + return null; + } + DefaultArrangementEntry current = getCurrent(); + JavaElementArrangementEntry entry; + if (canArrange) { + TextRange expandedRange = ArrangementUtil.expandToLine(range, myDocument.getCharsSequence()); + TextRange rangeToUse = expandedRange == null ? range : expandedRange; + entry = new JavaElementArrangementEntry(current, rangeToUse, type, name, expandedRange != null); + } + else { + entry = new JavaElementArrangementEntry(current, range, type, name, false); + } + if (current == null) { + myRootEntries.add(entry); + } + else { + current.addChild(entry); + } + + return entry; + } + + private boolean isWithinBounds(@NotNull TextRange range) { + for (TextRange textRange : myRanges) { + if (textRange.intersects(range)) { + return true; + } + } + return false; + } + + @Nullable + private DefaultArrangementEntry getCurrent() { + return myStack.isEmpty() ? null : myStack.peek(); + } + + private static void parseModifiers(@Nullable PsiModifierList modifierList, @NotNull JavaElementArrangementEntry entry) { + if (modifierList == null) { + return; + } + for (String modifier : PsiModifier.MODIFIERS) { + if (modifierList.hasModifierProperty(modifier)) { + entry.addModifier(MODIFIERS.get(modifier)); + } + } + } +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaElementArrangementEntry.java b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaElementArrangementEntry.java new file mode 100644 index 000000000000..75e243feeb92 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaElementArrangementEntry.java @@ -0,0 +1,93 @@ +/* + * 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.psi.codeStyle.arrangement; + +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType; +import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier; +import com.intellij.psi.codeStyle.arrangement.match.ModifierAwareArrangementEntry; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.EnumSet; +import java.util.Set; + +/** + * @author Denis Zhdanov + * @since 7/20/12 4:50 PM + */ +public class JavaElementArrangementEntry extends DefaultArrangementEntry + implements TypeAwareArrangementEntry, NameAwareArrangementEntry,ModifierAwareArrangementEntry +{ + + private final Set myModifiers = EnumSet.noneOf(ArrangementModifier.class); + + @NotNull private final ArrangementEntryType myType; + @Nullable private final String myName; + + public JavaElementArrangementEntry(@Nullable ArrangementEntry parent, + @NotNull TextRange range, + @NotNull ArrangementEntryType type, + @Nullable String name, + boolean canBeMatched) + { + this(parent, range.getStartOffset(), range.getEndOffset(), type, name, canBeMatched); + } + + public JavaElementArrangementEntry(@Nullable ArrangementEntry parent, + int startOffset, + int endOffset, + @NotNull ArrangementEntryType type, + @Nullable String name, + boolean canBeArranged) + { + super(parent, startOffset, endOffset, canBeArranged); + myType = type; + myName = name; + } + + @NotNull + @Override + public Set getModifiers() { + return myModifiers; + } + + public void addModifier(@NotNull ArrangementModifier modifier) { + myModifiers.add(modifier); + } + + @Nullable + @Override + public String getName() { + return myName; + } + + @NotNull + @Override + public ArrangementEntryType getType() { + return myType; + } + + @Override + public String toString() { + return String.format( + "[%d; %d): %s %s %s", + getStartOffset(), getEndOffset(), StringUtil.join(myModifiers, " ").toLowerCase(), myType.toString().toLowerCase(), + myName == null ? "" : myName + ); + } +} diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java new file mode 100644 index 000000000000..a4124104df51 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java @@ -0,0 +1,44 @@ +/* + * 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.psi.codeStyle.arrangement; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author Denis Zhdanov + * @since 7/20/12 2:31 PM + */ +public class JavaRearranger implements Rearranger { + + @NotNull + @Override + public Collection parse(@NotNull PsiElement root, + @NotNull Document document, + @NotNull Collection ranges) + { + // Following entries are subject to arrangement: class, interface, field, method. + List result = new ArrayList(); + root.accept(new JavaArrangementVisitor(result, document, ranges)); + return result; + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.groovy b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.groovy new file mode 100644 index 000000000000..b7147b116d7e --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.groovy @@ -0,0 +1,84 @@ +/* + * 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.psi.codeStyle.arrangement + +import com.intellij.lang.java.JavaLanguage +import com.intellij.openapi.components.ServiceManager +import com.intellij.openapi.fileTypes.FileType +import com.intellij.openapi.util.TextRange +import com.intellij.psi.codeStyle.CodeStyleSettings +import com.intellij.psi.codeStyle.CodeStyleSettingsManager +import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import org.jetbrains.annotations.NotNull +/** + * @author Denis Zhdanov + * @since 7/20/12 2:54 PM + */ +abstract class AbstractRearrangerTest extends LightCodeInsightFixtureTestCase { + + def FileType fileType + + @Override + protected void setUp() { + super.setUp() + CodeStyleSettingsManager.getInstance(myFixture.project).temporarySettings = new CodeStyleSettings() + } + + @Override + protected void tearDown() { + CodeStyleSettingsManager.getInstance(myFixture.project).dropTemporarySettings() + super.tearDown() + } + + protected void doTest(@NotNull String initial, + @NotNull String expected, + @NotNull List rules, + @NotNull Collection ranges = null) + { + def (String textToUse, List rangesToUse) = parseRanges(initial) + if (rangesToUse && ranges) { + fail("Duplicate ranges info detected: explicitly given: $ranges, derived from markup: $rangesToUse. Text:\n$initial") + } + if (!rangesToUse) { + rangesToUse = ranges ?: [TextRange.from(0, initial.length())] + } + + myFixture.configureByText(fileType, textToUse) + def settings = CodeStyleSettingsManager.getInstance(myFixture.project).currentSettings.getCommonSettings(JavaLanguage.INSTANCE) + settings.arrangementRules = rules + ArrangementEngine engine = ServiceManager.getService(myFixture.project, ArrangementEngine) + engine.arrange(myFixture.file, rangesToUse); + assertEquals(expected, myFixture.editor.document.text); + } + + @NotNull + private static def parseRanges(@NotNull String text) { + def clearText = new StringBuilder(text) + def ranges = [] + int shift = 0 + int shiftIncrease = ''.length() * 2 + 1 + def match = text =~ '(?is).*?' + match.each { + ranges << TextRange.create(match.start() - shift, match.end() - shift - shiftIncrease) + clearText.delete(match.end() - ''.length() - shift, match.end() - shift) + clearText.delete(match.start() - shift, match.start() + ''.length() - shift) + shift += shiftIncrease + } + + [clearText.toString(), ranges] + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerByTypeTest.groovy b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerByTypeTest.groovy new file mode 100644 index 000000000000..4642e9825c45 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerByTypeTest.groovy @@ -0,0 +1,178 @@ +/* + * 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.psi.codeStyle.arrangement + +import com.intellij.ide.highlighter.JavaFileType +import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType +import com.intellij.psi.codeStyle.arrangement.match.ByTypeArrangementEntryMatcher +/** + * @author Denis Zhdanov + * @since 7/20/12 2:45 PM + */ +class JavaRearrangerByTypeTest extends AbstractRearrangerTest { + + JavaRearrangerByTypeTest() { + fileType = JavaFileType.INSTANCE + } + + void testFieldsBeforeMethods() { + doTest( + '''\ +class Test { + public void test() {} + private int i; +} +class Test2 { +public void test() { +} + private int i; + private int j; +}''', + '''\ +class Test { + private int i; + public void test() {} +} +class Test2 { + private int i; + private int j; +public void test() { +} +}''', + [new ArrangementRule(new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD))] + ) + } + + void testAnonymousClassAtFieldInitializer() { + doTest( + '''\ +class Test { + private Object first = new Object() { + int inner1; + public String toString() { return "test"; } + int inner2; + }; + public Object test(Object ... args) { + return null; + } + private Object second = test(test(new Object() { + public String toString() { + return "test"; + } + private Object inner = new Object() { + public String toString() { return "innerTest"; } + }; + })); +}''', + '''\ +class Test { + private Object first = new Object() { + int inner1; + int inner2; + public String toString() { return "test"; } + }; + private Object second = test(test(new Object() { + private Object inner = new Object() { + public String toString() { return "innerTest"; } + }; + public String toString() { + return "test"; + } + })); + public Object test(Object ... args) { + return null; + } +}''', + [new ArrangementRule(new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD))] + ) + } + + void testAnonymousClassAtMethod() { + doTest( + '''\ +class Test { + void declaration() { + Object o = new Object() { + private int test() { return 1; } + String s; + } + } + double d; + void call() { + test(test(1, new Object() { + public void test() {} + int i; + }); + } +}''', + '''\ +class Test { + double d; + void declaration() { + Object o = new Object() { + String s; + private int test() { return 1; } + } + } + void call() { + test(test(1, new Object() { + int i; + public void test() {} + }); + } +}''', + [new ArrangementRule(new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD))] + ) + } + + void testRanges() { + doTest( + '''\ +class Test { + void outer1() {} + String outer2() {} + int i; + void test() { + method(new Object() { + void inner1() {} + Object field = new Object() { + void inner2() {} + String s; + Integer i; + } + }); + } +}''', + '''\ +class Test { + void outer1() {} + int i; + String outer2() {} + void test() { + method(new Object() { + void inner1() {} + Object field = new Object() { + String s; + void inner2() {} + Integer i; + } + }); + } +}''', + [new ArrangementRule(new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD))] + ) + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java index 15bf90ccec1f..08da83c4b290 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java @@ -20,7 +20,7 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.util.*; import com.intellij.psi.codeStyle.arrangement.ArrangementRule; -import com.intellij.psi.codeStyle.arrangement.ArrangementRuleUtil; +import com.intellij.psi.codeStyle.arrangement.ArrangementUtil; import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; import com.intellij.util.xmlb.XmlSerializer; import org.intellij.lang.annotations.MagicConstant; @@ -120,6 +120,16 @@ public class CommonCodeStyleSettings { return myIndentOptions; } + @NotNull + public List getArrangementRules() { + return myArrangementRules; + } + + public void setArrangementRules(@NotNull List rules) { + myArrangementRules.clear(); + myArrangementRules.addAll(rules); + } + public CommonCodeStyleSettings clone(CodeStyleSettings rootSettings) { assert rootSettings != null; CommonCodeStyleSettings commonSettings = new CommonCodeStyleSettings(myLanguage, getFileType()); @@ -168,10 +178,7 @@ public class CommonCodeStyleSettings { private static void copyFieldValue(final Object from, Object to, final Field field) throws IllegalAccessException { Class fieldType = field.getType(); - if (fieldType.isPrimitive()) { - field.set(to, field.get(from)); - } - else if (fieldType.equals(String.class)) { + if (fieldType.isPrimitive() || fieldType.equals(String.class)) { field.set(to, field.get(from)); } else { @@ -202,7 +209,7 @@ public class CommonCodeStyleSettings { } Element arrangementRulesContainer = element.getChild(ARRANGEMENT_ELEMENT_NAME); if (arrangementRulesContainer != null) { - myArrangementRules.addAll(ArrangementRuleUtil.readExternal(arrangementRulesContainer, myLanguage)); + myArrangementRules.addAll(ArrangementUtil.readExternal(arrangementRulesContainer, myLanguage)); } } @@ -224,7 +231,7 @@ public class CommonCodeStyleSettings { if (!myArrangementRules.isEmpty()) { Element container = new Element(ARRANGEMENT_ELEMENT_NAME); - ArrangementRuleUtil.writeExternal(container, myArrangementRules, myLanguage); + ArrangementUtil.writeExternal(container, myArrangementRules, myLanguage); if (!container.getChildren().isEmpty()) { element.addContent(container); } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementEntry.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementEntry.java index f29ed7d103a2..d3ad9f9eefee 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementEntry.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementEntry.java @@ -15,6 +15,7 @@ */ package com.intellij.psi.codeStyle.arrangement; +import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -66,4 +67,15 @@ public interface ArrangementEntry { * to move rearranged entries */ int getEndOffset(); + + /** + * Sometimes we want particular entry to serve just as another entries holder. For example, we might want to arrange + * anonymous class entries but don't want the class itself, say, to be arranged with normal inner classes. + *

+ * That is achieved for entries which return 'false' from this method call. + * + * @return true if current entry can be {@link ArrangementEntryMatcher#isMatched(ArrangementEntry) matched}; + * false otherwise + */ + boolean canBeMatched(); } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRuleUtil.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java similarity index 64% rename from platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRuleUtil.java rename to platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java index 9d9c21da3533..520407ba89ba 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRuleUtil.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java @@ -16,6 +16,8 @@ package com.intellij.psi.codeStyle.arrangement; import com.intellij.lang.Language; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher; import com.intellij.psi.codeStyle.arrangement.match.CompositeArrangementEntryMatcher; import org.jdom.Element; @@ -30,9 +32,9 @@ import java.util.List; * @author Denis Zhdanov * @since 7/17/12 11:24 AM */ -public class ArrangementRuleUtil { +public class ArrangementUtil { - private ArrangementRuleUtil() { + private ArrangementUtil() { } //region Serialization @@ -141,4 +143,79 @@ public class ArrangementRuleUtil { return composite; } //endregion + + //region ArrangementEntry + + /** + * Tries to build a text range on the given arguments basis. It should conform to the criteria below: + *

+   * 
    + *
  • it's start offset is located at the start of the same line where given range starts;
  • + *
  • it's end offset is located at the end of the same line where given range ends;
  • + *
  • all symbols between the resulting range start offset and given range's start offset are white spaces or tabulations;
  • + *
  • all symbols between the given range's end offset and resulting range's end offset are white spaces or tabulations;
  • + *
+ *
+ * This method is expected to be used in a situation when we want to arrange complete rows. + * Example: + *
+   *   class Test {
+   *        void test() {
+   *        }
+   *      int i;
+   *   }
+   * 
+ * Suppose, we want to locate fields before methods. We can move the exact field and method range then but indent will be broken, + * i.e. we'll get the result below: + *
+   *   class Test {
+   *        int i;
+   *      void test() {
+   *        }
+   *   }
+   * 
+ * We can expand field and method range to the whole lines and that would allow to achieve the desired result: + *
+   *   class Test {
+   *      int i;
+   *        void test() {
+   *        }
+   *   }
+   * 
+ * + * @param initialRange anchor range + * @param text target text against which the ranges are built + * @return expanded range if possible; null otherwise + */ + @Nullable + public static TextRange expandToLine(@NotNull TextRange initialRange, @NotNull CharSequence text) { + int startOffsetToUse = initialRange.getStartOffset(); + for (int i = startOffsetToUse - 1; i >= 0; i--) { + char c = text.charAt(i); + if (!StringUtil.isWhiteSpace(c)) { + return null; + } + else if (c == '\n') { + break; + } + else { + startOffsetToUse = i; + } + } + + int endOffsetToUse = initialRange.getEndOffset(); + for (int i = endOffsetToUse; i < text.length(); i++) { + char c = text.charAt(i); + if (!StringUtil.isWhiteSpace(c)) { + return null; + } + else if (c == '\n') { + endOffsetToUse = i; + break; + } + } + + return TextRange.create(startOffsetToUse, endOffsetToUse); + } + //endregion } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/DefaultArrangementEntry.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/DefaultArrangementEntry.java new file mode 100644 index 000000000000..b580ee928f37 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/DefaultArrangementEntry.java @@ -0,0 +1,76 @@ +/* + * 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.psi.codeStyle.arrangement; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author Denis Zhdanov + * @since 7/20/12 4:53 PM + */ +public class DefaultArrangementEntry implements ArrangementEntry { + + private final List myChildren = new ArrayList(); + + @Nullable ArrangementEntry myParent; + private final int myStartOffset; + private final int myEndOffset; + private final boolean myCanBeMatched; + + public DefaultArrangementEntry(@Nullable ArrangementEntry parent, int startOffset, int endOffset, boolean canBeMatched) { + myCanBeMatched = canBeMatched; + assert startOffset < endOffset; + myParent = parent; + myStartOffset = startOffset; + myEndOffset = endOffset; + } + + @Nullable + @Override + public ArrangementEntry getParent() { + return myParent; + } + + @NotNull + @Override + public Collection getChildren() { + return myChildren; + } + + public void addChild(@NotNull ArrangementEntry entry) { + myChildren.add(entry); + } + + @Override + public int getStartOffset() { + return myStartOffset; + } + + @Override + public int getEndOffset() { + return myEndOffset; + } + + @Override + public boolean canBeMatched() { + return myCanBeMatched; + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/Rearranger.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/Rearranger.java index b8eb681b3704..617491fcf2bf 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/Rearranger.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/Rearranger.java @@ -16,6 +16,7 @@ package com.intellij.psi.codeStyle.arrangement; import com.intellij.lang.LanguageExtension; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; @@ -33,15 +34,16 @@ import java.util.Collection; */ public interface Rearranger { - LanguageExtension> EXTENSION = new LanguageExtension>("com.intellij.rearranger.facade"); + LanguageExtension> EXTENSION = new LanguageExtension>("com.intellij.lang.rearranger"); /** * Allows to build rearranger-interested data for the given element. * - * @param root root element which children should be parsed for the rearrangement - * @param range target offsets range to use for filtering given root's children - * @return given root's children that are subject for further rearrangement + * @param root root element which children should be parsed for the rearrangement + * @param document document which corresponds to the target PSI tree + * @param ranges target offsets ranges to use for filtering given root's children + * @return given root's children which are subject for further rearrangement */ @NotNull - Collection parse(@NotNull PsiElement root, @NotNull TextRange range); + Collection parse(@NotNull PsiElement root, @NotNull Document document, @NotNull Collection ranges); } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByNameArrangementEntryMatcher.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByNameArrangementEntryMatcher.java index 251c3c91f8dc..458c8763bb21 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByNameArrangementEntryMatcher.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByNameArrangementEntryMatcher.java @@ -35,9 +35,7 @@ public class ByNameArrangementEntryMatcher implements ArrangementEntryMatcher { public boolean isMatched(@NotNull ArrangementEntry entry) { if (entry instanceof NameAwareArrangementEntry) { String name = ((NameAwareArrangementEntry)entry).getName(); - if (name != null) { - return name.matches(myPattern); - } + return name != null && name.matches(myPattern); } return false; } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ModifierAwareArrangementEntry.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ModifierAwareArrangementEntry.java index 10acb1bbd263..af25c6f904ac 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ModifierAwareArrangementEntry.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ModifierAwareArrangementEntry.java @@ -18,6 +18,8 @@ package com.intellij.psi.codeStyle.arrangement.match; import com.intellij.psi.codeStyle.arrangement.ArrangementEntry; import org.jetbrains.annotations.NotNull; +import java.util.Set; + /** * @author Denis Zhdanov * @since 7/17/12 8:57 PM @@ -25,5 +27,5 @@ import org.jetbrains.annotations.NotNull; public interface ModifierAwareArrangementEntry extends ArrangementEntry { @NotNull - ArrangementModifier getModifier(); + Set getModifiers(); } diff --git a/platform/lang-api/testSources/com/intellij/psi/codeStyle/arrangement/match/DefaultArrangementRuleSerializerTest.java b/platform/lang-api/testSources/com/intellij/psi/codeStyle/arrangement/match/DefaultArrangementRuleSerializerTest.java index 37948f38fa31..547b35b49b4f 100644 --- a/platform/lang-api/testSources/com/intellij/psi/codeStyle/arrangement/match/DefaultArrangementRuleSerializerTest.java +++ b/platform/lang-api/testSources/com/intellij/psi/codeStyle/arrangement/match/DefaultArrangementRuleSerializerTest.java @@ -17,7 +17,7 @@ package com.intellij.psi.codeStyle.arrangement.match; import com.intellij.psi.codeStyle.arrangement.ArrangementRule; import com.intellij.psi.codeStyle.arrangement.ArrangementRuleSerializer; -import com.intellij.psi.codeStyle.arrangement.ArrangementRuleUtil; +import com.intellij.psi.codeStyle.arrangement.ArrangementUtil; import com.intellij.psi.codeStyle.arrangement.DefaultArrangementRuleSerializer; import org.jdom.Element; import org.jetbrains.annotations.NotNull; @@ -48,13 +48,13 @@ public class DefaultArrangementRuleSerializerTest { @Test public void compositeMatchers() { - doTest(ArrangementRuleUtil.or( + doTest(ArrangementUtil.or( new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD), new ByTypeArrangementEntryMatcher(ArrangementEntryType.METHOD)) ); - doTest(ArrangementRuleUtil.and( - ArrangementRuleUtil.or( + doTest(ArrangementUtil.and( + ArrangementUtil.or( new ByTypeArrangementEntryMatcher(ArrangementEntryType.METHOD), new ByNameArrangementEntryMatcher("get*") ) diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java new file mode 100644 index 000000000000..9072ca1c8b8a --- /dev/null +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java @@ -0,0 +1,232 @@ +/* + * 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.psi.codeStyle.arrangement.engine; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.ex.DocumentEx; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.codeStyle.arrangement.ArrangementEntry; +import com.intellij.psi.codeStyle.arrangement.ArrangementRule; +import com.intellij.psi.codeStyle.arrangement.Rearranger; +import com.intellij.util.containers.Stack; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +/** + * @author Denis Zhdanov + * @since 7/20/12 1:56 PM + */ +public class ArrangementEngine { + + /** + * Arranges given PSI root contents that belong to the given ranges. + * + * @param file target PSI root + * @param ranges target ranges to use within the given root + */ + @SuppressWarnings("MethodMayBeStatic") + public void arrange(@NotNull PsiFile file, @NotNull Collection ranges) { + final Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file); + if (document == null) { + return; + } + + CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(file.getProject()).getCurrentSettings(); + final List arrangementRules = settings.getCommonSettings(file.getLanguage()).getArrangementRules(); + if (arrangementRules.isEmpty()) { + return; + } + + Rearranger rearranger = Rearranger.EXTENSION.forLanguage(file.getLanguage()); + if (rearranger == null) { + return; + } + + final Collection entriesToProcess = rearranger.parse(file, document, ranges); + final DocumentEx documentEx; + if (document instanceof DocumentEx && !((DocumentEx)document).isInBulkUpdate()) { + documentEx = (DocumentEx)document; + } + else { + documentEx = null; + } + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + if (documentEx != null) { + documentEx.setInBulkUpdate(true); + } + try { + doArrange(document, arrangementRules, entriesToProcess); + } + finally { + if (documentEx != null) { + documentEx.setInBulkUpdate(false); + } + } + } + }); + } + + private static void doArrange(@NotNull final Document document, + @NotNull List arrangementRules, + @NotNull Collection entriesToProcess) + { + // The general idea is to process entries bottom-up where every processed group belongs to the same parent. We may not bother + // with entries text ranges then. We use a list and a stack for achieving that than. + // + // Example: + // Entry1 Entry2 + // / \ / \ + // Entry11 Entry12 Entry21 Entry22 + // + // -------------------------- + // Stage 1: + // list: Entry1 Entry2 + // stack: [0, 0, 2] + // -------------------------- + // Stage 2: + // list: Entry1 Entry2 Entry11 Entry12 + // stack: [0, 1, 2] + // [2, 2, 4] + // -------------------------- + // Stage 3: + // list: Entry1 Entry2 Entry11 Entry12 + // stack: [0, 1, 2] + // [2, 3, 4] + // -------------------------- + // Stage 4: + // list: Entry1 Entry2 Entry11 Entry12 + // stack: [0, 1, 2] + // [2, 4, 4] + // -------------------------- + // arrange 'Entry11 Entry12' + // -------------------------- + // Stage 5: + // list: Entry1 Entry2 + // stack: [0, 1, 2] + // -------------------------- + // Stage 6: + // list: Entry1 Entry2 Entry21 Entry22 + // stack: [0, 2, 2] + // [2, 2, 4] + // -------------------------- + // Stage 7: + // list: Entry1 Entry2 Entry21 Entry22 + // stack: [0, 2, 2] + // [2, 3, 4] + // -------------------------- + // Stage 8: + // list: Entry1 Entry2 Entry21 Entry22 + // stack: [0, 2, 2] + // [2, 4, 4] + // -------------------------- + // arrange 'Entry21 Entry22' + // -------------------------- + // Stage 9: + // list: Entry1 Entry2 + // stack: [0, 2, 2] + // -------------------------- + // arrange 'Entry1 Entry2' + + List entries = new ArrayList(); + Stack stack = new Stack(); + entries.addAll(entriesToProcess); + stack.push(new StackEntry(0, entriesToProcess.size())); + while (!stack.isEmpty()) { + StackEntry stackEntry = stack.peek(); + if (stackEntry.current >= stackEntry.end) { + List subEntries = entries.subList(stackEntry.start, stackEntry.end); + if (subEntries.size() > 1) { + doArrange(arrangementRules, subEntries, document); + } + subEntries.clear(); + stack.pop(); + } + else { + ArrangementEntry entry = entries.get(stackEntry.current++); + Collection children = entry.getChildren(); + if (!children.isEmpty()) { + entries.addAll(children); + stack.push(new StackEntry(stackEntry.end, children.size())); + } + } + } + } + + private static void doArrange(@NotNull List rules, + @NotNull List entries, + @NotNull Document document) + { + List arranged = new ArrayList(); + Set unprocessed = new LinkedHashSet(entries); + + for (ArrangementRule rule : rules) { + for (ArrangementEntry entry : entries) { + if (entry.canBeMatched() && unprocessed.contains(entry) && rule.getMatcher().isMatched(entry)) { + arranged.add(entry); + unprocessed.remove(entry); + } + } + } + arranged.addAll(unprocessed); + + if (arranged.equals(entries)) { + return; + } + + // We apply changes from the last position to the first position in order not to bother with offsets shifts. + ArrangementEntry parent = entries.get(0).getParent(); + final String initial; + final int shift; + if (parent == null) { + initial = document.getCharsSequence().toString(); + shift = 0; + } + else { + initial = document.getCharsSequence().subSequence(parent.getStartOffset(), parent.getEndOffset()).toString(); + shift = parent.getStartOffset(); + } + for (int i = arranged.size() - 1; i >= 0; i--) { + ArrangementEntry arrangedEntry = arranged.get(i); + ArrangementEntry initialEntry = entries.get(i); + if (!arrangedEntry.equals(initialEntry)) { + String text = initial.substring(arrangedEntry.getStartOffset() - shift, arrangedEntry.getEndOffset() - shift); + document.replaceString(initialEntry.getStartOffset(), initialEntry.getEndOffset(), text); + } + } + } + + private static class StackEntry { + + public int start; + public int current; + public int end; + + StackEntry(int start, int count) { + this.start = start; + current = start; + end = start + count; + } + } +} diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index 187bb8a1311b..5f657f13666a 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -123,6 +123,7 @@ beanClass="com.intellij.lang.LanguageExtensionPoint"/> + diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 1f635d2026e8..302bc00f4117 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -177,6 +177,8 @@ + + diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 62e9ef562fea..ec9efc4e0729 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -1163,6 +1163,17 @@ public class StringUtil extends StringUtilRt { return join((Iterable)items, f, separator); } + public static String join(@NotNull Iterable items, @NotNull @NonNls String separator) { + StringBuilder result = new StringBuilder(); + for (Object item : items) { + result.append(item).append(separator); + } + if (result.length() > 0) { + result.setLength(result.length() - 1); + } + return result.toString(); + } + @NotNull public static String join(@NotNull Iterable items, @NotNull Function f, @NotNull @NonNls String separator) { final StringBuilder result = new StringBuilder(); diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 5cc31d889e58..df858b547c50 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -764,7 +764,8 @@ - + + From 0364eb48a61c0373802c14dff15f23f71c52c88d Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 24 Jul 2012 09:39:25 +0200 Subject: [PATCH 08/35] fix new byte[]null in lookups --- .../com/intellij/codeInsight/lookup/PsiTypeLookupItem.java | 2 +- .../codeInsight/completion/smartType/NewByteArray.java | 5 +++++ .../codeInsight/completion/SmartTypeCompletionTest.java | 7 +++++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/NewByteArray.java diff --git a/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java b/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java index b1672bd395f3..1ba18d7f49ce 100644 --- a/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java +++ b/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java @@ -226,7 +226,7 @@ public class PsiTypeLookupItem extends LookupItem { } if (myBracketsCount > 0) { - presentation.setTailText(StringUtil.repeat("[]", myBracketsCount) + presentation.getTailText(), true); + presentation.setTailText(StringUtil.repeat("[]", myBracketsCount) + StringUtil.notNullize(presentation.getTailText()), true); } } diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NewByteArray.java b/java/java-tests/testData/codeInsight/completion/smartType/NewByteArray.java new file mode 100644 index 000000000000..f0cdb7199549 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/NewByteArray.java @@ -0,0 +1,5 @@ +class A { + byte[] m() { + return new x; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index 22e8b463b992..9d8703dca517 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -612,6 +612,13 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { assertEquals("[] (java.lang)", LookupElementPresentation.renderElement(myItems[1]).getTailText()); } + public void testNewByteArray() { + configureByTestName(); + assertStringItems("byte"); + assertEquals("[]", LookupElementPresentation.renderElement(myItems[0]).getTailText()); + + } + public void testInsideStringLiteral() throws Throwable { doAntiTest(); } public void testDefaultAnnoParam() throws Throwable { doTest(); } From 42eebc6127b28d78d91b173cfa7729e86ee5a899 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 24 Jul 2012 10:31:15 +0200 Subject: [PATCH 09/35] IDEA-84963 Disprefer annotations in autocomplete at places where they cannot be used --- .../completion/PreferByKindWeigher.java | 53 ++- .../source/tree/java/PsiAnnotationImpl.java | 26 +- .../PreferApplicableAnnotations.java | 12 + .../NormalCompletionOrderingTest.groovy | 4 + .../completion/weighers/GrKindWeigher.java | 369 +++++++++--------- .../annotation/GrAnnotationImpl.java | 2 +- .../completion/GroovyCompletionTest.groovy | 18 + 7 files changed, 287 insertions(+), 197 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normalSorting/PreferApplicableAnnotations.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java index 7e9c4d7a920e..1465616183b2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java @@ -18,16 +18,17 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementWeigher; +import com.intellij.openapi.util.Condition; import com.intellij.patterns.ElementPattern; import com.intellij.psi.*; import com.intellij.psi.filters.getters.MembersGetter; import com.intellij.psi.impl.source.tree.JavaElementType; +import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.Set; @@ -55,26 +56,60 @@ public class PreferByKindWeigher extends LookupElementWeigher { private final CompletionType myCompletionType; private final PsiElement myPosition; private final Set myNonInitializedFields; - @Nullable private final String myRequiredSuper; + @NotNull private final Condition myRequiredSuper; - public PreferByKindWeigher(CompletionType completionType, PsiElement position) { + public PreferByKindWeigher(CompletionType completionType, final PsiElement position) { super("local"); myCompletionType = completionType; myPosition = position; myNonInitializedFields = JavaCompletionProcessor.getNonInitializedFields(position); + myRequiredSuper = createSuitabilityCondition(position); + } + private static Condition createSuitabilityCondition(final PsiElement position) { if (IN_CATCH_TYPE.accepts(position) || IN_MULTI_CATCH_TYPE.accepts(position) || JavaSmartCompletionContributor.AFTER_THROW_NEW.accepts(position) || INSIDE_METHOD_THROWS_CLAUSE.accepts(position)) { - myRequiredSuper = CommonClassNames.JAVA_LANG_THROWABLE; + return new Condition() { + @Override + public boolean value(PsiClass psiClass) { + return InheritanceUtil.isInheritor(psiClass, CommonClassNames.JAVA_LANG_THROWABLE); + } + }; } - else if (IN_RESOURCE_TYPE.accepts(position)) { - myRequiredSuper = CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE; + + if (IN_RESOURCE_TYPE.accepts(position)) { + return new Condition() { + @Override + public boolean value(PsiClass psiClass) { + return InheritanceUtil.isInheritor(psiClass, CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE); + } + }; } - else { - myRequiredSuper = null; + + if (psiElement().withParents(PsiJavaCodeReferenceElement.class, PsiAnnotation.class).accepts(position)) { + final PsiAnnotation annotation = PsiTreeUtil.getParentOfType(position, PsiAnnotation.class); + assert annotation != null; + PsiAnnotationOwner owner = annotation.getOwner(); + if (owner instanceof PsiModifierList || owner instanceof PsiTypeElement || + owner instanceof PsiMethodReceiver || owner instanceof PsiTypeParameter) { + PsiElement member = ((PsiElement)owner).getParent(); + final String[] elementTypeFields = PsiAnnotationImpl + .getApplicableElementTypeFields(owner instanceof PsiModifierList ? member : (PsiElement)owner); + return new Condition() { + @Override + public boolean value(PsiClass psiClass) { + if (!psiClass.isAnnotationType()) { + return false; + } + return PsiAnnotationImpl.isAnnotationApplicable(false, psiClass, elementTypeFields, position.getResolveScope()); + } + }; + } } + //noinspection unchecked + return Condition.FALSE; } enum MyResult { @@ -156,7 +191,7 @@ public class PreferByKindWeigher extends LookupElementWeigher { } if (object instanceof PsiClass) { - if (myRequiredSuper != null && InheritanceUtil.isInheritor((PsiClass)object, myRequiredSuper)) { + if (myRequiredSuper.value((PsiClass)object)) { return MyResult.suitableClass; } return MyResult.classNameOrGlobalStatic; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationImpl.java index b6fe75031c4e..047e0182facf 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationImpl.java @@ -162,14 +162,17 @@ public class PsiAnnotationImpl extends JavaStubPsiElement imp return !strict; } PsiClass annotationType = (PsiClass)resolved; - return isAnnotationApplicable(strict, annotationType, elementTypeFields, annotation.getManager(), annotation.getResolveScope()); + return isAnnotationApplicable(strict, annotationType, elementTypeFields, annotation.getResolveScope()); } public static boolean isAnnotationApplicable(boolean strict, - PsiClass annotationType, - String[] elementTypeFields, - PsiManager manager, + @NotNull PsiClass annotationType, + @Nullable String[] elementTypeFields, GlobalSearchScope resolveScope) { + if (elementTypeFields == null) { + return !strict; + } + PsiAnnotation target = annotationType.getModifierList().findAnnotation(CommonClassNames.TARGET_ANNOTATION_FQ_NAME); if (target == null) { //todo hack: ambiguity in spec @@ -183,7 +186,8 @@ public class PsiAnnotationImpl extends JavaStubPsiElement imp PsiAnnotationMemberValue value = attributes[0].getValue(); LOG.assertTrue(elementTypeFields.length > 0); - PsiClass elementTypeClass = JavaPsiFacade.getInstance(manager.getProject()).findClass("java.lang.annotation.ElementType", resolveScope); + PsiClass elementTypeClass = + JavaPsiFacade.getInstance(annotationType.getProject()).findClass("java.lang.annotation.ElementType", resolveScope); if (elementTypeClass == null) { //todo hack return !strict; @@ -192,17 +196,23 @@ public class PsiAnnotationImpl extends JavaStubPsiElement imp for (String fieldName : elementTypeFields) { PsiField field = elementTypeClass.findFieldByName(fieldName, false); - if (field == null) continue; + if (field == null) { + continue; + } if (value instanceof PsiArrayInitializerMemberValue) { PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)value).getInitializers(); for (PsiAnnotationMemberValue initializer : initializers) { if (initializer instanceof PsiReference) { - if (((PsiReference)initializer).isReferenceTo(field)) return true; + if (((PsiReference)initializer).isReferenceTo(field)) { + return true; + } } } } else if (value instanceof PsiReference) { - if (((PsiReference)value).isReferenceTo(field)) return true; + if (((PsiReference)value).isReferenceTo(field)) { + return true; + } } } return false; diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/PreferApplicableAnnotations.java b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferApplicableAnnotations.java new file mode 100644 index 000000000000..75ba46a656f5 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferApplicableAnnotations.java @@ -0,0 +1,12 @@ +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +@Z +@interface Foo { +} + +@Target({ElementType.ANNOTATION_TYPE}) +@interface ZMetaAnno {} + +@Target({ElementType.LOCAL_VARIABLE}) +@interface ZLocalAnno {} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy index a5797213a6c9..aa532f06acb5 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy @@ -342,6 +342,10 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase { checkPreferredItems 0, 'serial', 'superExpressionInIllegalContext' } + public void testPreferApplicableAnnotations() throws Throwable { + checkPreferredItems 0, 'ZMetaAnno', 'ZLocalAnno' + } + public void testJComponentAddNewWithStats() throws Throwable { final LookupImpl lookup = invokeCompletion("/../smartTypeSorting/JComponentAddNew.java"); assertPreferredItems(0, "FooBean3", "JComponent", "Component"); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java index 60fb62fa6cbb..36e6063a6ea0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java @@ -1,179 +1,190 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.plugins.groovy.lang.completion.weighers; - -import com.intellij.codeInsight.completion.CompletionLocation; -import com.intellij.codeInsight.completion.CompletionWeigher; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.PsiTypeLookupItem; -import com.intellij.psi.*; -import com.intellij.psi.impl.light.LightElement; -import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.containers.CollectionFactory; -import com.intellij.util.containers.hash.HashSet; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.extensions.NamedArgumentDescriptor; -import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionContributor; -import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; -import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod; -import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrPropertyForCompletion; -import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; -import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; - -import java.util.Set; - -/** - * @author Maxim.Medvedev - */ -public class GrKindWeigher extends CompletionWeigher { - private static final Set TRASH_CLASSES = new HashSet(10); - private static final Set PRIORITY_KEYWORDS = CollectionFactory.hashSet( - PsiKeyword.RETURN, PsiKeyword.INSTANCEOF, "in", - PsiKeyword.PRIVATE, PsiKeyword.PROTECTED, PsiKeyword.PUBLIC, PsiKeyword.STATIC, "def", - PsiKeyword.TRUE, PsiKeyword.FALSE, PsiKeyword.NULL); - - static { - TRASH_CLASSES.add(CommonClassNames.JAVA_LANG_CLASS); - TRASH_CLASSES.add(CommonClassNames.JAVA_LANG_OBJECT); - TRASH_CLASSES.add(GroovyCommonClassNames.GROOVY_OBJECT_SUPPORT); - } - - @Override - public Comparable weigh(@NotNull LookupElement element, @NotNull CompletionLocation location) { - final PsiElement position = location.getCompletionParameters().getPosition(); - if (!(position.getContainingFile() instanceof GroovyFileBase)) return null; - - Object o = element.getObject(); - if (o instanceof ResolveResult) { - o = ((ResolveResult)o).getElement(); - } - - final PsiElement parent = position.getParent(); - final PsiElement qualifier = parent instanceof GrReferenceElement ? ((GrReferenceElement)parent).getQualifier() : null; - if (qualifier == null) { - if (o instanceof NamedArgumentDescriptor) { - switch (((NamedArgumentDescriptor)o).getPriority()) { - case ALWAYS_ON_TOP: - return NotQualifiedKind.onTop; - case AS_LOCAL_VARIABLE: - return NotQualifiedKind.local; - default: - return NotQualifiedKind.unknown; - } - } - if (o instanceof PsiVariable && !(o instanceof PsiField)) { - return NotQualifiedKind.local; - } - - PsiTypeLookupItem item = element.as(PsiTypeLookupItem.CLASS_CONDITION_KEY); - if (item != null && item.getBracketsCount() > 0) { - return NotQualifiedKind.arrayType; - } - - if (isPriorityKeyword(o)) return NotQualifiedKind.local; - if (isLightElement(o)) return NotQualifiedKind.unknown; - if (o instanceof PsiClass) { - if (((PsiClass)o).isAnnotationType() && GroovyCompletionContributor.AFTER_AT.accepts(position)) { - return NotQualifiedKind.restrictedClass; - } - if (GroovyCompletionContributor.IN_CATCH_TYPE.accepts(position) && - InheritanceUtil.isInheritor((PsiClass)o, CommonClassNames.JAVA_LANG_THROWABLE)) { - return NotQualifiedKind.restrictedClass; - } - } - if (o instanceof PsiMember) { - final PsiClass containingClass = ((PsiMember)o).getContainingClass(); - if (isAccessor((PsiMember)o)) return NotQualifiedKind.accessor; - if (o instanceof PsiClass && ((PsiClass)o).getContainingClass() == null || o instanceof PsiPackage) return NotQualifiedKind.unknown; - if (o instanceof PsiClass) return NotQualifiedKind.innerClass; - if (PsiTreeUtil.isContextAncestor(containingClass, position, false)) return NotQualifiedKind.currentClassMember; - return NotQualifiedKind.member; - } - return NotQualifiedKind.unknown; - } - else { - if (o instanceof PsiEnumConstant) return QualifiedKind.enumConstant; - - if (isLightElement(o)) return QualifiedKind.unknown; - if (o instanceof PsiMember) { - if (isTrashMethod((PsiMember)o)) return QualifiedKind.unknown; - if (isAccessor((PsiMember)o)) return QualifiedKind.accessor; - if (isQualifierClassMember((PsiMember)o, qualifier)) { - return QualifiedKind.currentClassMember; - } - if (o instanceof PsiClass && ((PsiClass)o).getContainingClass() == null || o instanceof PsiPackage) return QualifiedKind.unknown; - if (o instanceof PsiClass) return QualifiedKind.innerClass; - return QualifiedKind.member; - } - return QualifiedKind.unknown; - } - } - - private static boolean isPriorityKeyword(Object o) { - //noinspection SuspiciousMethodCalls - return PRIORITY_KEYWORDS.contains(o); - } - - private static boolean isLightElement(Object o) { - return o instanceof LightElement && !(o instanceof GrPropertyForCompletion) && !(o instanceof GrAccessorMethod); - } - - private static boolean isTrashMethod(PsiMember o) { - final PsiClass containingClass = o.getContainingClass(); - return containingClass != null && TRASH_CLASSES.contains(containingClass.getQualifiedName()); - } - - private static boolean isAccessor(PsiMember member) { - return member instanceof PsiMethod && (GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)member) || "setProperty".equals(((PsiMethod)member).getName())); - } - - - private static boolean isQualifierClassMember(PsiMember member, PsiElement qualifier) { - if (!(qualifier instanceof GrExpression)) return false; - - final PsiType type = ((GrExpression)qualifier).getType(); - if (!(type instanceof PsiClassType)) return false; - - final PsiClass psiClass = ((PsiClassType)type).resolve(); - if (psiClass == null) return false; - - return qualifier.getManager().areElementsEquivalent(member.getContainingClass(), psiClass); - } - - private enum NotQualifiedKind { - arrayType, - innerClass, - unknown, - accessor, - member, - currentClassMember, - restrictedClass, - local, - onTop - } - - private enum QualifiedKind { - innerClass, - unknown, - accessor, - member, - currentClassMember, - enumConstant, - } -} +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.lang.completion.weighers; + +import com.intellij.codeInsight.completion.CompletionLocation; +import com.intellij.codeInsight.completion.CompletionWeigher; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.PsiTypeLookupItem; +import com.intellij.psi.*; +import com.intellij.psi.impl.light.LightElement; +import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl; +import com.intellij.psi.util.InheritanceUtil; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.containers.CollectionFactory; +import com.intellij.util.containers.hash.HashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.extensions.NamedArgumentDescriptor; +import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionContributor; +import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod; +import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationImpl; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrPropertyForCompletion; +import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; +import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; + +import java.util.Set; + +/** + * @author Maxim.Medvedev + */ +public class GrKindWeigher extends CompletionWeigher { + private static final Set TRASH_CLASSES = new HashSet(10); + private static final Set PRIORITY_KEYWORDS = CollectionFactory.hashSet( + PsiKeyword.RETURN, PsiKeyword.INSTANCEOF, "in", + PsiKeyword.PRIVATE, PsiKeyword.PROTECTED, PsiKeyword.PUBLIC, PsiKeyword.STATIC, "def", + PsiKeyword.TRUE, PsiKeyword.FALSE, PsiKeyword.NULL); + + static { + TRASH_CLASSES.add(CommonClassNames.JAVA_LANG_CLASS); + TRASH_CLASSES.add(CommonClassNames.JAVA_LANG_OBJECT); + TRASH_CLASSES.add(GroovyCommonClassNames.GROOVY_OBJECT_SUPPORT); + } + + @Override + public Comparable weigh(@NotNull LookupElement element, @NotNull CompletionLocation location) { + final PsiElement position = location.getCompletionParameters().getPosition(); + if (!(position.getContainingFile() instanceof GroovyFileBase)) return null; + + Object o = element.getObject(); + if (o instanceof ResolveResult) { + o = ((ResolveResult)o).getElement(); + } + + final PsiElement parent = position.getParent(); + final PsiElement qualifier = parent instanceof GrReferenceElement ? ((GrReferenceElement)parent).getQualifier() : null; + if (qualifier == null) { + if (o instanceof NamedArgumentDescriptor) { + switch (((NamedArgumentDescriptor)o).getPriority()) { + case ALWAYS_ON_TOP: + return NotQualifiedKind.onTop; + case AS_LOCAL_VARIABLE: + return NotQualifiedKind.local; + default: + return NotQualifiedKind.unknown; + } + } + if (o instanceof PsiVariable && !(o instanceof PsiField)) { + return NotQualifiedKind.local; + } + + PsiTypeLookupItem item = element.as(PsiTypeLookupItem.CLASS_CONDITION_KEY); + if (item != null && item.getBracketsCount() > 0) { + return NotQualifiedKind.arrayType; + } + + if (isPriorityKeyword(o)) return NotQualifiedKind.local; + if (isLightElement(o)) return NotQualifiedKind.unknown; + if (o instanceof PsiClass) { + if (((PsiClass)o).isAnnotationType() && GroovyCompletionContributor.AFTER_AT.accepts(position)) { + final GrAnnotation annotation = PsiTreeUtil.getParentOfType(position, GrAnnotation.class); + if (annotation != null) { + PsiElement annoParent = annotation.getParent(); + PsiElement owner = annoParent.getParent(); + String[] elementTypeFields = GrAnnotationImpl.getApplicableElementTypeFields(annoParent instanceof PsiModifierList ? owner : annoParent); + if (PsiAnnotationImpl.isAnnotationApplicable(false, (PsiClass)o, elementTypeFields, position.getResolveScope())) { + return NotQualifiedKind.restrictedClass; + } + } + } + if (GroovyCompletionContributor.IN_CATCH_TYPE.accepts(position) && + InheritanceUtil.isInheritor((PsiClass)o, CommonClassNames.JAVA_LANG_THROWABLE)) { + return NotQualifiedKind.restrictedClass; + } + } + if (o instanceof PsiMember) { + final PsiClass containingClass = ((PsiMember)o).getContainingClass(); + if (isAccessor((PsiMember)o)) return NotQualifiedKind.accessor; + if (o instanceof PsiClass && ((PsiClass)o).getContainingClass() == null || o instanceof PsiPackage) return NotQualifiedKind.unknown; + if (o instanceof PsiClass) return NotQualifiedKind.innerClass; + if (PsiTreeUtil.isContextAncestor(containingClass, position, false)) return NotQualifiedKind.currentClassMember; + return NotQualifiedKind.member; + } + return NotQualifiedKind.unknown; + } + else { + if (o instanceof PsiEnumConstant) return QualifiedKind.enumConstant; + + if (isLightElement(o)) return QualifiedKind.unknown; + if (o instanceof PsiMember) { + if (isTrashMethod((PsiMember)o)) return QualifiedKind.unknown; + if (isAccessor((PsiMember)o)) return QualifiedKind.accessor; + if (isQualifierClassMember((PsiMember)o, qualifier)) { + return QualifiedKind.currentClassMember; + } + if (o instanceof PsiClass && ((PsiClass)o).getContainingClass() == null || o instanceof PsiPackage) return QualifiedKind.unknown; + if (o instanceof PsiClass) return QualifiedKind.innerClass; + return QualifiedKind.member; + } + return QualifiedKind.unknown; + } + } + + private static boolean isPriorityKeyword(Object o) { + //noinspection SuspiciousMethodCalls + return PRIORITY_KEYWORDS.contains(o); + } + + private static boolean isLightElement(Object o) { + return o instanceof LightElement && !(o instanceof GrPropertyForCompletion) && !(o instanceof GrAccessorMethod); + } + + private static boolean isTrashMethod(PsiMember o) { + final PsiClass containingClass = o.getContainingClass(); + return containingClass != null && TRASH_CLASSES.contains(containingClass.getQualifiedName()); + } + + private static boolean isAccessor(PsiMember member) { + return member instanceof PsiMethod && (GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)member) || "setProperty".equals(((PsiMethod)member).getName())); + } + + + private static boolean isQualifierClassMember(PsiMember member, PsiElement qualifier) { + if (!(qualifier instanceof GrExpression)) return false; + + final PsiType type = ((GrExpression)qualifier).getType(); + if (!(type instanceof PsiClassType)) return false; + + final PsiClass psiClass = ((PsiClassType)type).resolve(); + if (psiClass == null) return false; + + return qualifier.getManager().areElementsEquivalent(member.getContainingClass(), psiClass); + } + + private enum NotQualifiedKind { + arrayType, + innerClass, + unknown, + accessor, + member, + currentClassMember, + restrictedClass, + local, + onTop + } + + private enum QualifiedKind { + innerClass, + unknown, + accessor, + member, + currentClassMember, + enumConstant, + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java index fb954985066d..ddb032dfb9ef 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java @@ -179,7 +179,7 @@ public class GrAnnotationImpl extends GrStubElementBase implem GrCodeReferenceElement nameRef = annotation.getClassReference(); PsiElement resolved = nameRef.resolve(); if (resolved instanceof PsiClass && ((PsiClass)resolved).isAnnotationType()) { - return PsiAnnotationImpl.isAnnotationApplicable(strict, (PsiClass)resolved, elementTypeFields, annotation.getManager(),annotation.getResolveScope()); + return PsiAnnotationImpl.isAnnotationApplicable(strict, (PsiClass)resolved, elementTypeFields, annotation.getResolveScope()); } return !strict; } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index 57b3a07e1a30..4b2c458e6d94 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -1398,4 +1398,22 @@ def bar(){}''') assertOrderedEquals(myFixture.lookupElementStrings, ['fooo', 'fooo1']) } + public void testPreferApplicableAnnotations() { + configure(''' +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +@Z +@interface Foo { +} + +@Target(ElementType.ANNOTATION_TYPE) +@interface ZMetaAnno {} + +@Target(ElementType.LOCAL_VARIABLE) +@interface ZLocalAnno {}''') + myFixture.completeBasic() + myFixture.assertPreferredCompletionItems 0, 'ZMetaAnno', 'ZLocalAnno' + } + } \ No newline at end of file From 9799b8ce43f3609be46078c04ed6e446b8545bfc Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 24 Jul 2012 12:43:08 +0400 Subject: [PATCH 10/35] IDEA-66333 Quick documentation lookup on mouse hover Corrected links appliance --- .../navigation/DocPreviewUtil.java | 70 +++++++++++++++++-- .../navigation/DocPreviewUtilTest.groovy | 19 +++++ 2 files changed, 84 insertions(+), 5 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/DocPreviewUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/DocPreviewUtil.java index 77994a63d9ae..70c485b6b1cf 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/DocPreviewUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/DocPreviewUtil.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.documentation.DocumentationManager; import com.intellij.lang.documentation.DocumentationProvider; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; +import gnu.trove.TIntHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,6 +37,23 @@ import java.util.regex.Pattern; */ public class DocPreviewUtil { + private static final TIntHashSet ALLOWED_LINK_SEPARATORS = new TIntHashSet(); + static { + ALLOWED_LINK_SEPARATORS.add(','); + ALLOWED_LINK_SEPARATORS.add(' '); + ALLOWED_LINK_SEPARATORS.add('.'); + ALLOWED_LINK_SEPARATORS.add(';'); + ALLOWED_LINK_SEPARATORS.add('&'); + ALLOWED_LINK_SEPARATORS.add('\t'); + ALLOWED_LINK_SEPARATORS.add('\n'); + ALLOWED_LINK_SEPARATORS.add('['); + ALLOWED_LINK_SEPARATORS.add(']'); + ALLOWED_LINK_SEPARATORS.add('('); + ALLOWED_LINK_SEPARATORS.add(')'); + ALLOWED_LINK_SEPARATORS.add('<'); + ALLOWED_LINK_SEPARATORS.add('>'); + } + /** * We shorten links text from fully qualified name to short names (e.g. from 'java.lang.String' to 'String'). * There is a possible situation then that we have two replacements where one key is a simple name and another one is a fully qualified @@ -90,13 +108,16 @@ public class DocPreviewUtil { Map links = new HashMap(); process(fullText, new LinksCollector(links)); - // Add short names. + // Add derived names. Map toAdd = new HashMap(); for (Map.Entry entry : links.entrySet()) { - String key = entry.getKey(); - int i = key.lastIndexOf('.'); - if (i > 0 && i < key.length() - 1) { - toAdd.put(key.substring(i + 1), entry.getValue()); + String shortName = parseShortName(entry.getKey()); + if (shortName != null) { + toAdd.put(shortName, entry.getValue()); + } + String longName = parseLongName(entry.getKey(), entry.getValue()); + if (longName != null) { + toAdd.put(longName, entry.getValue()); } } links.putAll(toAdd); @@ -121,6 +142,40 @@ public class DocPreviewUtil { return buffer.toString(); } + /** + * Tries to build a short name form the given name assuming that it is a full name. + *

+ * Example: return {@code 'String'} for a given {@code 'java.lang.String'}. + * + * @param name name to process + * @return short name derived from the given full name if possible; null otherwise + */ + @Nullable + private static String parseShortName(@NotNull String name) { + int i = name.lastIndexOf('.'); + return i > 0 && i < name.length() - 1 ? name.substring(i + 1) : null; + } + + /** + * Tries to build a long name from the given short name and a link. + *

+ * Example: return {@code 'java.lang.String'} for a given pair (name {@code 'String'}; address: {@code 'psi_element://java.lang.String'}. + * + * @param shortName short name to process + * @param address address to process + * @return long name derived from the given arguments (if any); null otherwise + */ + @Nullable + private static String parseLongName(@NotNull String shortName, @NotNull String address) { + String pureAddress = address; + int i = pureAddress.lastIndexOf("//"); + if (i > 0 && i < pureAddress.length() - 2) { + pureAddress = pureAddress.substring(i + 2); + } + + return (pureAddress.equals(shortName) || !pureAddress.endsWith(shortName)) ? null : pureAddress; + } + private static void replace(@NotNull StringBuilder text, @NotNull String replaceFrom, @NotNull String replaceTo, @@ -131,6 +186,11 @@ public class DocPreviewUtil { if (intersects(readOnlyChanges, i, end)) { continue; } + if (end - i > 1 && end < text.length() && !ALLOWED_LINK_SEPARATORS.contains(text.charAt(end))) { + // Consider a situation when we have, say, replacement from text 'PsiType' and encounter a 'PsiTypeParameter' in the text. + // We don't want to perform the replacement then. + continue; + } text.replace(i, end, replaceTo); int diff = replaceTo.length() - replaceFrom.length(); for (int j = 0; j < readOnlyChanges.size(); j++) { diff --git a/platform/lang-impl/testSources/com/intellij/codeInsight/navigation/DocPreviewUtilTest.groovy b/platform/lang-impl/testSources/com/intellij/codeInsight/navigation/DocPreviewUtilTest.groovy index a7799d0b61a0..31b235dcd1ca 100644 --- a/platform/lang-impl/testSources/com/intellij/codeInsight/navigation/DocPreviewUtilTest.groovy +++ b/platform/lang-impl/testSources/com/intellij/codeInsight/navigation/DocPreviewUtilTest.groovy @@ -145,4 +145,23 @@ Qname''' assertEquals(expected, DocPreviewUtil.buildPreview(header, null, fullText)) } + + @Test + void substrings() { + def header = '''\ +PsiResolveHelperImpl +public static com.intellij.openapi.util.Pair<com.intellij.psi.PsiType, com.intellij.psi.ConstraintType> getSubstitutionForTypeParameterConstraint (com.intellij.psi.PsiTypeParameter typeParam, com.intellij.psi.PsiType param, com.intellij.psi.PsiType arg, boolean isContraVariantPosition, com.intellij.pom.java.LanguageLevel languageLevel)''' + + def fullText = '''\ + com.intellij.psi.impl.source.resolve.PsiResolveHelperImpl

@Nullable public static Pair<PsiType, ConstraintType> getSubstitutionForTypeParameterConstraint(PsiTypeParameter typeParam,
+                                                                                  PsiType param,
+                                                                                  PsiType arg,
+                                                                                  boolean isContraVariantPosition,
+                                                                                  LanguageLevel languageLevel)
''' + + def expected = '''\ +PsiResolveHelperImpl
public static Pair<PsiType, ConstraintType> getSubstitutionForTypeParameterConstraint (PsiTypeParameter typeParam, PsiType param, PsiType arg, boolean isContraVariantPosition, LanguageLevel languageLevel)''' + + assertEquals(expected, DocPreviewUtil.buildPreview(header, null, fullText)) + } } From ebea5751f434b2d3fdf1e0cf8a4667c18b8ae837 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 24 Jul 2012 13:16:49 +0400 Subject: [PATCH 11/35] IDEA-19061 Integrate the Rearranger-plugin into core-IDEA Fix tests at the server --- .../psi/codeStyle/arrangement/AbstractRearrangerTest.groovy | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.groovy b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.groovy index b7147b116d7e..8d2a19cee7cf 100644 --- a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.groovy +++ b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.groovy @@ -24,6 +24,7 @@ import com.intellij.psi.codeStyle.CodeStyleSettingsManager import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import org.jetbrains.annotations.NotNull +import org.jetbrains.annotations.Nullable /** * @author Denis Zhdanov * @since 7/20/12 2:54 PM @@ -47,7 +48,7 @@ abstract class AbstractRearrangerTest extends LightCodeInsightFixtureTestCase { protected void doTest(@NotNull String initial, @NotNull String expected, @NotNull List rules, - @NotNull Collection ranges = null) + Collection ranges = null) { def (String textToUse, List rangesToUse) = parseRanges(initial) if (rangesToUse && ranges) { From 249daacf1cd09e8d6eb37d0ce13f07d798eff734 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 24 Jul 2012 13:32:09 +0400 Subject: [PATCH 12/35] Fix maven test --- .../idea/maven/compiler/ResourceCopyingTest.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceCopyingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceCopyingTest.java index 4e282fabea6c..133a3af9e2d8 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceCopyingTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceCopyingTest.java @@ -26,6 +26,16 @@ import org.jetbrains.idea.maven.importing.MavenDefaultModifiableModelsProvider; import org.jetbrains.idea.maven.importing.MavenRootModelAdapter; public class ResourceCopyingTest extends MavenImportingTestCase { + + @Override + protected void setUpInWriteAction() throws Exception { + super.setUpInWriteAction(); + + CompilerConfiguration.getInstance(myProject).addResourceFilePattern("!*.xxx"); + CompilerConfiguration.getInstance(myProject).addResourceFilePattern("!*.yyy"); + CompilerConfiguration.getInstance(myProject).addResourceFilePattern("!*.zzz"); + } + public void testBasic() throws Exception { createProjectSubFile("src/main/resources/dir/file.properties"); From b305a80a899e21c58c3064dd110821b6439f1eca Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 23 Jul 2012 17:37:15 +0400 Subject: [PATCH 13/35] fixL add listener to avd combo --- .../org/jetbrains/android/run/ExtendedDeviceChooserDialog.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java b/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java index 61a17ded1d1a..5cd03042bc56 100644 --- a/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java +++ b/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java @@ -95,6 +95,7 @@ public class ExtendedDeviceChooserDialog extends DialogWrapper { }; myLaunchEmulatorRadioButton.addActionListener(listener); myChooserRunningDeviceRadioButton.addActionListener(listener); + myAvdCombo.addActionListener(listener); init(); From bc8a93e51b1fb07b227caae1d726bde62512fe6b Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 23 Jul 2012 17:43:54 +0400 Subject: [PATCH 14/35] default package choosing strategy --- .../AndroidAppPropertiesEditor.form | 2 +- .../AndroidAppPropertiesEditor.java | 37 +++++++++++++++++-- .../newProject/AndroidModuleWizardStep.java | 6 ++- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.form b/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.form index f43a933de4c7..05279b1e407c 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.form +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.form @@ -51,7 +51,7 @@ - + diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.java b/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.java index 698b7319a208..d5ca0ec5db4a 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.java +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.java @@ -45,11 +45,11 @@ public class AndroidAppPropertiesEditor { private JLabel myErrorLabel; private JPanel myContentPanel; - private final String myModuleName; - public AndroidAppPropertiesEditor(String moduleName) { - myModuleName = moduleName; - myApplicationNameField.setText(moduleName); + if (moduleName != null) { + myApplicationNameField.setText(moduleName); + myPackageNameField.setText(getDefaultPackageNameByModuleName(moduleName)); + } myHelloAndroidCheckBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { updateActivityPanel(); @@ -71,6 +71,31 @@ public class AndroidAppPropertiesEditor { }); } + @NotNull + public static String getDefaultPackageNameByModuleName(@NotNull String moduleName) { + return "com.example." + toIdentifier(moduleName); + } + + @NotNull + private static String toIdentifier(@NotNull String s) { + final StringBuilder result = new StringBuilder(); + + for (int i = 0, n = s.length(); i < n; i++) { + final char c = s.charAt(i); + + if (Character.isJavaIdentifierPart(c)) { + if (i == 0 && !Character.isJavaIdentifierStart(c)) { + result.append('_'); + } + result.append(c); + } + else { + result.append('_'); + } + } + return result.toString(); + } + public void updateActivityPanel() { myErrorLabel.setForeground(Color.RED); UIUtil.setEnabled(myActivtiyPanel, myHelloAndroidCheckBox.isSelected(), true); @@ -155,6 +180,10 @@ public class AndroidAppPropertiesEditor { return myApplicationNameField; } + public JTextField getPackageNameField() { + return myPackageNameField; + } + public JPanel getActivtiyPanel() { return myActivtiyPanel; } diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.java b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.java index 31ab03089d17..48a638f98f5e 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.java +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.java @@ -241,8 +241,12 @@ public class AndroidModuleWizardStep extends ModuleWizardStep { } public JComponent getComponent() { - myAppPropertiesEditor.getApplicationNameField().setText(myModuleBuilder.getName()); + final String moduleName = myModuleBuilder.getName(); + if (moduleName != null) { + myAppPropertiesEditor.getApplicationNameField().setText(moduleName); + myAppPropertiesEditor.getPackageNameField().setText(AndroidAppPropertiesEditor.getDefaultPackageNameByModuleName(moduleName)); + } Sdk selectedSdk = mySdkComboBoxWithBrowseButton.getSelectedSdk(); final PropertiesComponent properties = PropertiesComponent.getInstance(); From a08d59089ef3a99528a838c8173e47ed1752531a Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 23 Jul 2012 18:17:52 +0400 Subject: [PATCH 15/35] IDEA-85332 warn if applications with same package name will be installed --- .../android/run/AndroidRunningState.java | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/run/AndroidRunningState.java b/plugins/android/src/org/jetbrains/android/run/AndroidRunningState.java index 8062411f4133..8294d4fc520c 100644 --- a/plugins/android/src/org/jetbrains/android/run/AndroidRunningState.java +++ b/plugins/android/src/org/jetbrains/android/run/AndroidRunningState.java @@ -53,6 +53,7 @@ import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.ui.content.Content; import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.HashMap; import com.intellij.xdebugger.DefaultDebugProcessHandler; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.facet.AndroidRootUtil; @@ -69,7 +70,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.Map; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -622,6 +623,7 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb message("Target device: " + getDevicePresentableName(device), STDOUT); try { if (myDeploy) { + if (!checkPackageNames()) return false; if (!uploadAndInstall(device, myPackageName, myFacet)) return false; if (!uploadAndInstallDependentModules(device)) return false; myApplicationDeployed = true; @@ -661,6 +663,45 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb return false; } } + + private boolean checkPackageNames() { + final Map> packageName2ModuleNames = new HashMap>(); + packageName2ModuleNames.put(myPackageName, new ArrayList(Arrays.asList(myFacet.getModule().getName()))); + + for (Map.Entry entry : myAdditionalFacet2PackageName.entrySet()) { + final String moduleName = entry.getKey().getModule().getName(); + final String packageName = entry.getValue(); + List list = packageName2ModuleNames.get(packageName); + + if (list == null) { + list = new ArrayList(); + packageName2ModuleNames.put(packageName, list); + } + list.add(moduleName); + } + boolean result = true; + + for (Map.Entry> entry : packageName2ModuleNames.entrySet()) { + final String packageName = entry.getKey(); + final List moduleNames = entry.getValue(); + + if (moduleNames.size() > 1) { + final StringBuilder messageBuilder = new StringBuilder("Applications have the same package name "); + messageBuilder.append(packageName).append(":\n "); + + for (Iterator it = moduleNames.iterator(); it.hasNext(); ) { + String moduleName = it.next(); + messageBuilder.append(moduleName); + if (it.hasNext()) { + messageBuilder.append(", "); + } + } + message(messageBuilder.toString(), STDERR); + result = false; + } + } + return result; + } protected static void clearLogcatAndConsole(@NotNull final Project project, @NotNull final IDevice device) { final boolean[] result = {true}; From d2cd023b0f10fc3e7bd0e82b0a0a17e269bb5df1 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 23 Jul 2012 18:48:52 +0400 Subject: [PATCH 16/35] IDEA-85332 check if package name is already used in android new module wizard --- .../AndroidAppPropertiesEditor.java | 58 ++++++++++++++----- .../newProject/AndroidModuleBuilder.java | 2 +- .../newProject/AndroidModuleWizardStep.java | 18 ++---- 3 files changed, 51 insertions(+), 27 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.java b/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.java index d5ca0ec5db4a..84bbbc2fb2d1 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.java +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.java @@ -18,11 +18,15 @@ package org.jetbrains.android.newProject; import com.intellij.lexer.JavaLexer; import com.intellij.lexer.Lexer; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.module.Module; import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.roots.ui.configuration.ModulesProvider; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.JavaTokenType; import com.intellij.ui.DocumentAdapter; import com.intellij.util.ui.UIUtil; +import org.jetbrains.android.dom.manifest.Manifest; +import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.util.AndroidBundle; import org.jetbrains.android.util.AndroidCommonUtils; import org.jetbrains.annotations.NotNull; @@ -45,7 +49,12 @@ public class AndroidAppPropertiesEditor { private JLabel myErrorLabel; private JPanel myContentPanel; - public AndroidAppPropertiesEditor(String moduleName) { + private final ModulesProvider myModulesProvider; + private boolean myApp; + + public AndroidAppPropertiesEditor(String moduleName, ModulesProvider modulesProvider) { + myModulesProvider = modulesProvider; + if (moduleName != null) { myApplicationNameField.setText(moduleName); myPackageNameField.setText(getDefaultPackageNameByModuleName(moduleName)); @@ -58,7 +67,7 @@ public class AndroidAppPropertiesEditor { myPackageNameField.getDocument().addDocumentListener(new DocumentAdapter() { @Override protected void textChanged(DocumentEvent e) { - String message = validatePackageName(); + String message = validatePackageName(!myApp); myErrorLabel.setText(message); } }); @@ -71,6 +80,20 @@ public class AndroidAppPropertiesEditor { }); } + public void update(boolean app) { + myApplicationNameField.setEnabled(app); + myHelloAndroidCheckBox.setEnabled(app); + if (app) { + updateActivityPanel(); + } + else { + UIUtil.setEnabled(myActivtiyPanel, app, true); + } + myApp = app; + final String message = validatePackageName(!app); + myErrorLabel.setText(message); + } + @NotNull public static String getDefaultPackageNameByModuleName(@NotNull String moduleName) { return "com.example." + toIdentifier(moduleName); @@ -101,7 +124,7 @@ public class AndroidAppPropertiesEditor { UIUtil.setEnabled(myActivtiyPanel, myHelloAndroidCheckBox.isSelected(), true); } - private String validatePackageName() { + private String validatePackageName(boolean library) { String candidate = myPackageNameField.getText().trim(); if (candidate.length() == 0) { return AndroidBundle.message("specify.package.name.error"); @@ -112,6 +135,21 @@ public class AndroidAppPropertiesEditor { if (!AndroidCommonUtils.contains2Identifiers(candidate)) { return AndroidBundle.message("package.name.must.contain.2.ids.error"); } + + if (!library) { + for (Module module : myModulesProvider.getModules()) { + final AndroidFacet facet = AndroidFacet.getInstance(module); + if (facet != null && !facet.getConfiguration().LIBRARY_PROJECT) { + final Manifest manifest = facet.getManifest(); + if (manifest != null) { + final String packageName = manifest.getPackage().getValue(); + if (candidate.equals(packageName)) { + return "Package name '" + packageName + "' is already used by module '" + module.getName() + "'"; + } + } + } + } + } return ""; } @@ -147,12 +185,12 @@ public class AndroidAppPropertiesEditor { return myContentPanel; } - public void validate(boolean testProject) throws ConfigurationException { - String message = validatePackageName(); + public void validate(boolean library) throws ConfigurationException { + String message = validatePackageName(library); if (message.length() > 0) { throw new ConfigurationException(message); } - if (!testProject) { + if (!library) { message = validateActivityName(); if (message.length() > 0) { throw new ConfigurationException(message); @@ -172,10 +210,6 @@ public class AndroidAppPropertiesEditor { return myApplicationNameField.getText().trim(); } - public JCheckBox getHelloAndroidCheckBox() { - return myHelloAndroidCheckBox; - } - public JTextField getApplicationNameField() { return myApplicationNameField; } @@ -183,8 +217,4 @@ public class AndroidAppPropertiesEditor { public JTextField getPackageNameField() { return myPackageNameField; } - - public JPanel getActivtiyPanel() { - return myActivtiyPanel; - } } diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java index 454a5c1f5f07..e4fcbdaa5526 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java @@ -672,7 +672,7 @@ public class AndroidModuleBuilder extends JavaModuleBuilder { }); } - steps.add(new AndroidModuleWizardStep(this, wizardContext)); + steps.add(new AndroidModuleWizardStep(this, wizardContext, modulesProvider)); return steps.toArray(new ModuleWizardStep[steps.size()]); } diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.java b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.java index 48a638f98f5e..9092b23c1807 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.java +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.java @@ -28,6 +28,7 @@ import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.ProjectJdkTable; import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.ui.configuration.ModulesProvider; import com.intellij.openapi.ui.LabeledComponent; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Disposer; @@ -90,11 +91,11 @@ public class AndroidModuleWizardStep extends ModuleWizardStep { @NonNls private static final String TARGET_SELECTION_MODE_FOR_NEW_MODULE_PROPERTY = "ANDROID_TARGET_SELECTION_MODE_FOR_NEW_MODULE"; @NonNls private static final String TARGET_AVD_FOR_NEW_MODULE_PROPERTY = "ANDROID_TARGET_AVD_FOR_NEW_MODULE"; - public AndroidModuleWizardStep(@NotNull AndroidModuleBuilder moduleBuilder, WizardContext context) { + public AndroidModuleWizardStep(@NotNull AndroidModuleBuilder moduleBuilder, WizardContext context, ModulesProvider modulesProvider) { super(); myApplicationProjectButton.setSelected(true); - myAppPropertiesEditor = new AndroidAppPropertiesEditor(moduleBuilder.getName()); + myAppPropertiesEditor = new AndroidAppPropertiesEditor(moduleBuilder.getName(), modulesProvider); Project project = context.getProject(); myTestPropertiesEditor = project != null ? new AndroidTestPropertiesEditor(project) : null; myPropertiesPanel.setLayout(new OverlayLayout(myPropertiesPanel)); @@ -201,6 +202,7 @@ public class AndroidModuleWizardStep extends ModuleWizardStep { myDoNotCreateConfigurationRadioButton.setSelected(true); } } + updatePropertiesEditor(); } @Override @@ -223,15 +225,7 @@ public class AndroidModuleWizardStep extends ModuleWizardStep { if (myTestPropertiesEditor != null) { myTestPropertiesEditor.getContentPanel().setVisible(false); } - boolean app = myApplicationProjectButton.isSelected(); - myAppPropertiesEditor.getApplicationNameField().setEnabled(app); - myAppPropertiesEditor.getHelloAndroidCheckBox().setEnabled(app); - if (app) { - myAppPropertiesEditor.updateActivityPanel(); - } - else { - UIUtil.setEnabled(myAppPropertiesEditor.getActivtiyPanel(), app, true); - } + myAppPropertiesEditor.update(myApplicationProjectButton.isSelected()); } else { myAppPropertiesEditor.getContentPanel().setVisible(false); @@ -285,7 +279,7 @@ public class AndroidModuleWizardStep extends ModuleWizardStep { } if (myApplicationProjectButton.isSelected() || myLibProjectButton.isSelected()) { - myAppPropertiesEditor.validate(myTestProjectButton.isSelected()); + myAppPropertiesEditor.validate(myLibProjectButton.isSelected()); } else { assert myTestPropertiesEditor != null; From c79e96d9c3811cf8407ba5f98addab0254b7930a Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 23 Jul 2012 19:20:51 +0400 Subject: [PATCH 17/35] IDEA-86963 always generate android module inside temp directory --- .../newProject/AndroidModuleBuilder.java | 96 ++++++++++--------- 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java index e4fcbdaa5526..a45207b8a309 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java @@ -199,23 +199,6 @@ public class AndroidModuleBuilder extends JavaModuleBuilder { private boolean createProjectByAndroidTool(final VirtualFile contentRoot, final VirtualFile sourceRoot, final AndroidFacet facet) { - - - File tempContentRoot = null; - - // todo: support custom non-empty source root - - if (sourceRoot != null && - sourceRoot.getChildren().length == 0 && - (!Comparing.equal(sourceRoot.getParent(), contentRoot) || !SdkConstants.FD_SOURCES.equals(sourceRoot.getName()))) { - try { - tempContentRoot = FileUtil.createTempDirectory("android_temp_content_root", "tmp"); - } - catch (IOException e) { - LOG.error(e); - } - } - final Module module = facet.getModule(); AndroidPlatform platform = AndroidPlatform.parse(mySdk); @@ -254,7 +237,16 @@ public class AndroidModuleBuilder extends JavaModuleBuilder { commandLine.addParameter(getAntProjectName(module.getName())); commandLine.addParameters("--path"); - final String targetDirectoryPath = tempContentRoot != null ? tempContentRoot.getPath() : contentRoot.getPath(); + + File tempContentRoot; + try { + tempContentRoot = FileUtil.createTempDirectory("android_temp_content_root", "tmp"); + } + catch (IOException e) { + LOG.error(e); + return false; + } + final String targetDirectoryPath = tempContentRoot.getPath(); commandLine.addParameter(FileUtil.toSystemDependentName(targetDirectoryPath)); if (myProjectType == ProjectType.APPLICATION || myProjectType == ProjectType.LIBRARY) { @@ -282,32 +274,12 @@ public class AndroidModuleBuilder extends JavaModuleBuilder { @Override public void run() { final Project project = module.getProject(); - AndroidUtils.runExternalTool(commandLine, project); - - if (finalTempContentRoot != null) { - final File[] children = finalTempContentRoot.listFiles(); - - if (children != null) { - for (File child : children) { - if (SdkConstants.FD_SOURCES.equals(child.getName())) { - continue; - } - final File to = new File(contentRoot.getPath(), child.getName()); - - if (!FileUtil.moveDirWithContent(child, to)) { - LOG.error("Cannot move content from " + child.getPath() + " to " + to.getPath()); - } - } - } - - final File tempSourceRoot = new File(finalTempContentRoot, SdkConstants.FD_SOURCES); - if (tempSourceRoot.exists()) { - final File to = new File(sourceRoot.getPath()); - - if (!FileUtil.moveDirWithContent(tempSourceRoot, to)) { - LOG.error("Cannot move content from " + tempSourceRoot.getPath() + " to " + to.getPath()); - } - } + try { + AndroidUtils.runExternalTool(commandLine, project); + copyGeneratedAndroidProject(finalTempContentRoot, contentRoot, sourceRoot); + } + finally { + FileUtil.delete(finalTempContentRoot); } StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() { @@ -387,6 +359,42 @@ public class AndroidModuleBuilder extends JavaModuleBuilder { return true; } + private static void copyGeneratedAndroidProject(File tempDir, VirtualFile contentRoot, VirtualFile sourceRoot) { + final File[] children = tempDir.listFiles(); + if (children != null) { + for (File child : children) { + if (SdkConstants.FD_SOURCES.equals(child.getName())) { + continue; + } + final File to = new File(contentRoot.getPath(), child.getName()); + + try { + if (child.isDirectory()) { + FileUtil.copyDir(child, to); + } + else { + FileUtil.copy(child, to); + } + } + catch (IOException e) { + LOG.error(e); + } + } + } + + final File tempSourceRoot = new File(tempDir, SdkConstants.FD_SOURCES); + if (tempSourceRoot.exists()) { + final File to = new File(sourceRoot.getPath()); + + try { + FileUtil.copyDir(tempSourceRoot, to); + } + catch (IOException e) { + LOG.error(e); + } + } + } + private static void configureManifest(@NotNull AndroidFacet facet, @NotNull IAndroidTarget target) { final Manifest manifest = facet.getManifest(); if (manifest == null) { From a6b571e62278c11b71580c395fdaef55a74fb4df Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 23 Jul 2012 19:22:23 +0400 Subject: [PATCH 18/35] clean up message --- .../org/jetbrains/android/newProject/AndroidModuleBuilder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java index a45207b8a309..d5b9b89a47db 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java @@ -464,7 +464,8 @@ public class AndroidModuleBuilder extends JavaModuleBuilder { AndroidPlatform platform = AndroidPlatform.parse(mySdk); if (platform == null) { - Messages.showErrorDialog(project, "Cannot parse Android SDK: 'default.properties' won't be generated", CommonBundle.getErrorTitle()); + Messages.showErrorDialog(project, "Cannot parse Android SDK: '" + SdkConstants.FN_PROJECT_PROPERTIES + "' won't be generated", + CommonBundle.getErrorTitle()); return; } From e641a6f01f3822d2b2e0758dfdafe3e3ed5d571c Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 24 Jul 2012 13:30:34 +0400 Subject: [PATCH 19/35] IDEA-89094 Validate names of android resources --- .../messages/AndroidBundle.properties | 5 +++- .../actions/CreateResourceFileDialog.java | 7 +++++ .../CreateTypedResourceFileAction.java | 19 +++++++++++- .../dom/resources/ResourceElement.java | 2 ++ .../dom/resources/ResourceNameConverter.java | 30 +++++++++++++++++++ .../android/util/AndroidResourceUtil.java | 14 +++++++++ .../testData/dom/resources/nameValidation.xml | 9 ++++++ .../dom/AndroidValueResourcesTest.java | 4 +++ 8 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 plugins/android/src/org/jetbrains/android/dom/resources/ResourceNameConverter.java create mode 100644 plugins/android/testData/dom/resources/nameValidation.xml diff --git a/plugins/android/resources/messages/AndroidBundle.properties b/plugins/android/resources/messages/AndroidBundle.properties index 98fd6cb89e9f..a991cb90d471 100644 --- a/plugins/android/resources/messages/AndroidBundle.properties +++ b/plugins/android/resources/messages/AndroidBundle.properties @@ -417,4 +417,7 @@ cannot.find.zip.align=The zipalign tool was not found in the SDK.\n\nPlease upda file.name.not.specified.error=File name is not specified root.element.not.specified.error=Root element is not specified directory.not.specified.error=Directory is not specified -android.manifest.merger.not.supported.error=Manifest merging is not supported. Please, reconfigure your manifest files \ No newline at end of file +android.manifest.merger.not.supported.error=Manifest merging is not supported. Please, reconfigure your manifest files +invalid.file.resource.name.error=Resource file name must contain only lowercase a-z, 0-9, or _ +invalid.file.resource.name.error1=Invalid resource file name +invalid.resource.name.error=Invalid resource name ''{0}'' \ No newline at end of file diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileDialog.java b/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileDialog.java index ecd4adbde004..a4bd770f4830 100644 --- a/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileDialog.java +++ b/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileDialog.java @@ -34,6 +34,7 @@ import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.uipreview.DeviceConfiguratorPanel; import org.jetbrains.android.uipreview.InvalidOptionValueException; import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.android.util.AndroidResourceUtil; import org.jetbrains.android.util.AndroidUtils; import org.jetbrains.android.util.ModuleListCellRendererWrapper; import org.jetbrains.annotations.NotNull; @@ -252,6 +253,12 @@ public class CreateResourceFileDialog extends DialogWrapper { Messages.showErrorDialog(myPanel, AndroidBundle.message("directory.not.specified.error"), CommonBundle.getErrorTitle()); return; } + + final String errorMessage = AndroidResourceUtil.getInvalidResourceFileNameMessage(fileName); + if (errorMessage != null) { + Messages.showErrorDialog(myPanel, errorMessage, CommonBundle.getErrorTitle()); + return; + } myValidator = createValidator(subdirName); if (myValidator == null || myValidator.checkInput(fileName) && myValidator.canClose(fileName)) { super.doOKAction(); diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateTypedResourceFileAction.java b/plugins/android/src/org/jetbrains/android/actions/CreateTypedResourceFileAction.java index 10074fea9763..d067378f1d2b 100644 --- a/plugins/android/src/org/jetbrains/android/actions/CreateTypedResourceFileAction.java +++ b/plugins/android/src/org/jetbrains/android/actions/CreateTypedResourceFileAction.java @@ -27,6 +27,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.InputValidatorEx; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Computable; import com.intellij.psi.PsiDirectory; @@ -78,7 +79,7 @@ public class CreateTypedResourceFileAction extends CreateElementActionBase { @NotNull @Override protected PsiElement[] invokeDialog(Project project, PsiDirectory directory) { - MyInputValidator validator = new MyInputValidator(project, directory); + MyInputValidator validator = new MyValidator(project, directory); Messages.showInputDialog(project, AndroidBundle.message("new.file.dialog.text"), AndroidBundle.message("new.typed.resource.dialog.title", myResourcePresentableName), Messages.getQuestionIcon(), "", validator); @@ -203,4 +204,20 @@ public class CreateTypedResourceFileAction extends CreateElementActionBase { } throw new IllegalArgumentException("Incorrect resource folder type"); } + + private class MyValidator extends MyInputValidator implements InputValidatorEx { + public MyValidator(Project project, PsiDirectory directory) { + super(project, directory); + } + + @Override + public boolean checkInput(String inputString) { + return getErrorText(inputString) == null; + } + + @Override + public String getErrorText(String inputString) { + return AndroidResourceUtil.getInvalidResourceFileNameMessage(inputString); + } + } } diff --git a/plugins/android/src/org/jetbrains/android/dom/resources/ResourceElement.java b/plugins/android/src/org/jetbrains/android/dom/resources/ResourceElement.java index d870c9971240..7d18b9f8b035 100644 --- a/plugins/android/src/org/jetbrains/android/dom/resources/ResourceElement.java +++ b/plugins/android/src/org/jetbrains/android/dom/resources/ResourceElement.java @@ -15,6 +15,7 @@ */ package org.jetbrains.android.dom.resources; +import com.intellij.util.xml.Convert; import com.intellij.util.xml.GenericAttributeValue; import com.intellij.util.xml.GenericDomValue; import com.intellij.util.xml.Required; @@ -25,5 +26,6 @@ import org.jetbrains.android.dom.AndroidDomElement; */ public interface ResourceElement extends GenericDomValue, AndroidDomElement { @Required + @Convert(ResourceNameConverter.class) GenericAttributeValue getName(); } diff --git a/plugins/android/src/org/jetbrains/android/dom/resources/ResourceNameConverter.java b/plugins/android/src/org/jetbrains/android/dom/resources/ResourceNameConverter.java new file mode 100644 index 000000000000..27970394b212 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/dom/resources/ResourceNameConverter.java @@ -0,0 +1,30 @@ +package org.jetbrains.android.dom.resources; + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.xml.ConvertContext; +import com.intellij.util.xml.Converter; +import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.android.util.AndroidResourceUtil; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; + +/** + * @author Eugene.Kudelevsky + */ +public class ResourceNameConverter extends Converter { + @Override + public String fromString(@Nullable @NonNls String s, ConvertContext context) { + return s != null && StringUtil.isJavaIdentifier(AndroidResourceUtil.getFieldNameByResourceName(s)) + ? s : null; + } + + @Override + public String toString(@Nullable String s, ConvertContext context) { + return s; + } + + @Override + public String getErrorMessage(@Nullable String s, ConvertContext context) { + return AndroidBundle.message("invalid.resource.name.error", s); + } +} diff --git a/plugins/android/src/org/jetbrains/android/util/AndroidResourceUtil.java b/plugins/android/src/org/jetbrains/android/util/AndroidResourceUtil.java index f54e4cf1afd5..15ce866737bc 100644 --- a/plugins/android/src/org/jetbrains/android/util/AndroidResourceUtil.java +++ b/plugins/android/src/org/jetbrains/android/util/AndroidResourceUtil.java @@ -806,4 +806,18 @@ public class AndroidResourceUtil { public static String getFieldNameByResourceName(@NotNull String fieldName) { return fieldName.replace('.', '_').replace('-', '_').replace(':', '_'); } + + @Nullable + public static String getInvalidResourceFileNameMessage(@NotNull String fileName) { + for (int i = 0, n = fileName.length(); i < n; i++) { + char c = fileName.charAt(i); + if (!((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c == '.')) { + return AndroidBundle.message("invalid.file.resource.name.error"); + } + } + if (!StringUtil.isJavaIdentifier(getFieldNameByResourceName(fileName))) { + return AndroidBundle.message("invalid.file.resource.name.error1"); + } + return null; + } } diff --git a/plugins/android/testData/dom/resources/nameValidation.xml b/plugins/android/testData/dom/resources/nameValidation.xml new file mode 100644 index 000000000000..acf5c477d4a6 --- /dev/null +++ b/plugins/android/testData/dom/resources/nameValidation.xml @@ -0,0 +1,9 @@ + + a + a + a + 1 + 1 + 1 + 1 + \ No newline at end of file diff --git a/plugins/android/testSrc/org/jetbrains/android/dom/AndroidValueResourcesTest.java b/plugins/android/testSrc/org/jetbrains/android/dom/AndroidValueResourcesTest.java index f504be57df66..0cba392db1f8 100644 --- a/plugins/android/testSrc/org/jetbrains/android/dom/AndroidValueResourcesTest.java +++ b/plugins/android/testSrc/org/jetbrains/android/dom/AndroidValueResourcesTest.java @@ -214,6 +214,10 @@ public class AndroidValueResourcesTest extends AndroidDomTest { doTestHighlighting(); } + public void testNameValidation() throws Throwable { + doTestHighlighting(); + } + public void testResourceReferenceAsValueCompletion1() throws Throwable { doTestCompletion(); } From 8ca681a88b55f88ffbae03b8182ba73069a04d42 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 23 Jul 2012 17:38:50 +0200 Subject: [PATCH 20/35] Move IdeaWin32 to utils --- bin/win/IdeaWin32.dll | Bin 44544 -> 35840 bytes bin/win/IdeaWin64.dll | Bin 40448 -> 41472 bytes native/IdeaWin32/IdeaWin32.cpp | 188 +- native/IdeaWin32/IdeaWin32.h | 33 +- native/IdeaWin32/IdeaWin32.props | 17 + native/IdeaWin32/IdeaWin32.sln | 20 +- native/IdeaWin32/IdeaWin32.vcproj | 229 -- native/IdeaWin32/IdeaWin32.vcxproj | 162 ++ native/IdeaWin32/IdeaWin32.vcxproj.filters | 27 + native/IdeaWin32/IdeaWin32.vcxproj.user | 3 + native/IdeaWin32/jlong.h | 31 - native/IdeaWin32/jlong_md.h | 93 - native/IdeaWin32/jni.h | 1944 ----------------- native/IdeaWin32/jni_md.h | 19 - native/IdeaWin32/jni_util.h | 347 --- native/IdeaWin32/readme.txt | 0 native/IdeaWin32/stdafx.cpp | 8 - native/IdeaWin32/stdafx.h | 30 - .../openapi/vfs/impl/win32/IdeaWin32.java | 25 - .../openapi/vfs/impl/win32/Win32Kernel.java | 15 +- .../vfs/impl/win32/Win32LocalFileSystem.java | 38 +- .../openapi/util/io}/win32/FileInfo.java | 22 +- .../openapi/util/io/win32/IdeaWin32.java | 95 + 23 files changed, 506 insertions(+), 2840 deletions(-) create mode 100644 native/IdeaWin32/IdeaWin32.props delete mode 100644 native/IdeaWin32/IdeaWin32.vcproj create mode 100644 native/IdeaWin32/IdeaWin32.vcxproj create mode 100644 native/IdeaWin32/IdeaWin32.vcxproj.filters create mode 100644 native/IdeaWin32/IdeaWin32.vcxproj.user delete mode 100644 native/IdeaWin32/jlong.h delete mode 100644 native/IdeaWin32/jlong_md.h delete mode 100644 native/IdeaWin32/jni.h delete mode 100644 native/IdeaWin32/jni_md.h delete mode 100644 native/IdeaWin32/jni_util.h create mode 100644 native/IdeaWin32/readme.txt delete mode 100644 native/IdeaWin32/stdafx.cpp delete mode 100644 native/IdeaWin32/stdafx.h delete mode 100644 platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/IdeaWin32.java rename platform/{platform-impl/src/com/intellij/openapi/vfs/impl => util/src/com/intellij/openapi/util/io}/win32/FileInfo.java (61%) create mode 100644 platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java diff --git a/bin/win/IdeaWin32.dll b/bin/win/IdeaWin32.dll index c6675b1b1f3bcf86cc9dfc44b60b45cd1cc3a0d7..7556f14f241129c568079969b9b526272dc99ad3 100644 GIT binary patch literal 35840 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 iG>*f5>0_ox#o -jfieldID nameID; -jfieldID attributesID; -jfieldID timestampID; -jfieldID lengthID; -JNIEXPORT void JNICALL Java_com_intellij_openapi_vfs_impl_win32_FileInfo_initIDs(JNIEnv *env, jclass cls) { - nameID = env->GetFieldID(cls, "name", "Ljava/lang/String;"); - attributesID = env->GetFieldID(cls, "attributes", "I"); - timestampID = env->GetFieldID(cls, "timestamp", "J"); - lengthID = env->GetFieldID(cls, "length", "J"); +static jfieldID nameID = NULL; +static jfieldID attributesID = NULL; +static jfieldID timestampID = NULL; +static jfieldID lengthID = NULL; + +static jclass getFileInfoClass(JNIEnv *env) { + return env->FindClass("com/intellij/openapi/util/io/win32/FileInfo"); } static HANDLE FindFileInner(JNIEnv *env, jstring path, LPWIN32_FIND_DATA lpData) { @@ -31,7 +43,7 @@ static bool CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src, jin return true; } -static LONGLONG pairToInt64(DWORD lowPart, DWORD highPart) { +static inline LONGLONG pairToInt64(DWORD lowPart, DWORD highPart) { ULARGE_INTEGER large; large.LowPart = lowPart; large.HighPart = highPart; @@ -39,9 +51,10 @@ static LONGLONG pairToInt64(DWORD lowPart, DWORD highPart) { } #define IS_SET(flags, flag) ((flags & flag) == flag) +#define FILE_SHARE_ATTRIBUTES (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) -static jobject CreateFileInfo(JNIEnv *env, jstring path, bool append, LPWIN32_FIND_DATA lpData, jclass cls) { - jobject o = env->AllocObject(cls); +static jobject CreateFileInfo(JNIEnv *env, jstring path, bool append, LPWIN32_FIND_DATA lpData, jclass fileInfoClass) { + jobject o = env->AllocObject(fileInfoClass); if (o == NULL) { return NULL; } @@ -53,34 +66,39 @@ static jobject CreateFileInfo(JNIEnv *env, jstring path, bool append, LPWIN32_FI env->SetObjectField(o, nameID, fileName); bool read = false; - if (IS_SET(lpData->dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT) && IS_SET(lpData->dwReserved0, IO_REPARSE_TAG_SYMLINK)) { - int nameLen = env->GetStringLength(path) + wcslen(lpData->cFileName) + 2; - wchar_t *lpName = (wchar_t *)malloc(nameLen * sizeof(wchar_t)); + if (IS_SET(lpData->dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT)) { + if (IS_SET(lpData->dwReserved0, IO_REPARSE_TAG_SYMLINK)) { + size_t nameLen = env->GetStringLength(path) + wcslen(lpData->cFileName) + 2; + wchar_t *lpName = (wchar_t *)malloc(nameLen * sizeof(wchar_t)); - if (lpName != NULL) { - const jchar *dirName = env->GetStringChars(path, 0); - wcscpy_s(lpName, nameLen, (LPCWSTR)dirName); - env->ReleaseStringChars(path, dirName); - if (append) { - wcscat_s(lpName, nameLen, L"\\"); - wcscat_s(lpName, nameLen, lpData->cFileName); - } - - // read symlink target attributes - HANDLE th = CreateFile(lpName, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (th != INVALID_HANDLE_VALUE) { - BY_HANDLE_FILE_INFORMATION targetData; - if (GetFileInformationByHandle(th, &targetData)) { - env->SetIntField(o, attributesID, targetData.dwFileAttributes); - env->SetLongField(o, timestampID, pairToInt64(targetData.ftLastWriteTime.dwLowDateTime, targetData.ftLastWriteTime.dwHighDateTime)); - env->SetLongField(o, lengthID, pairToInt64(targetData.nFileSizeLow, targetData.nFileSizeHigh)); - read = true; + if (lpName != NULL) { + const jchar *dirName = env->GetStringChars(path, 0); + wcscpy_s(lpName, nameLen, (LPCWSTR)dirName); + env->ReleaseStringChars(path, dirName); + if (append) { + wcscat_s(lpName, nameLen, L"\\"); + wcscat_s(lpName, nameLen, lpData->cFileName); } - CloseHandle(th); - } - free(lpName); + // read symlink target attributes + HANDLE th = CreateFile(lpName, 0, FILE_SHARE_ATTRIBUTES, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (th != INVALID_HANDLE_VALUE) { + BY_HANDLE_FILE_INFORMATION targetData; + if (GetFileInformationByHandle(th, &targetData)) { + targetData.dwFileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT; + env->SetIntField(o, attributesID, targetData.dwFileAttributes); + env->SetLongField(o, timestampID, pairToInt64(targetData.ftLastWriteTime.dwLowDateTime, targetData.ftLastWriteTime.dwHighDateTime)); + env->SetLongField(o, lengthID, pairToInt64(targetData.nFileSizeLow, targetData.nFileSizeHigh)); + read = true; + } + CloseHandle(th); + } + + free(lpName); + } + } + else { + lpData->dwFileAttributes &= (~ FILE_ATTRIBUTE_REPARSE_POINT); // keep reparse flag only for symlinks } } @@ -93,28 +111,97 @@ static jobject CreateFileInfo(JNIEnv *env, jstring path, bool append, LPWIN32_FI return o; } -JNIEXPORT jobject JNICALL Java_com_intellij_openapi_vfs_impl_win32_IdeaWin32_getInfo(JNIEnv *env, jobject method, jstring path) { + +JNIEXPORT void JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_initIDs(JNIEnv *env, jclass cls) { + jclass fileInfoClass = getFileInfoClass(env); + if (fileInfoClass == NULL) { + return; + } + + nameID = env->GetFieldID(fileInfoClass, "name", "Ljava/lang/String;"); + attributesID = env->GetFieldID(fileInfoClass, "attributes", "I"); + timestampID = env->GetFieldID(fileInfoClass, "timestamp", "J"); + lengthID = env->GetFieldID(fileInfoClass, "length", "J"); +} + + +JNIEXPORT jobject JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_getInfo(JNIEnv *env, jobject method, jstring path) { + WIN32_FIND_DATA data; + HANDLE h = FindFileInner(env, path, &data); + if (h == INVALID_HANDLE_VALUE) { + return NULL; + } + + FindClose(h); + + jclass fileInfoClass = getFileInfoClass(env); + if (fileInfoClass == NULL) { + return NULL; + } + + return CreateFileInfo(env, path, false, &data, fileInfoClass); +} + + +JNIEXPORT jstring JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_resolveSymLink(JNIEnv *env, jobject method, jstring path) { WIN32_FIND_DATA data; HANDLE h = FindFileInner(env, path, &data); if (h == INVALID_HANDLE_VALUE) { return NULL; } FindClose(h); - jclass infoClass = env->FindClass("com/intellij/openapi/vfs/impl/win32/FileInfo"); - return CreateFileInfo(env, path, false, &data, infoClass); + + if (!IS_SET(data.dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT) || !IS_SET(data.dwReserved0, IO_REPARSE_TAG_SYMLINK)) { + return NULL; + } + + const jchar* str = env->GetStringChars(path, 0); + HANDLE th = CreateFile((LPCWSTR)str, 0, FILE_SHARE_ATTRIBUTES, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + env->ReleaseStringChars(path, str); + if (th == INVALID_HANDLE_VALUE) { + return NULL; + } + + jstring result = NULL; + + TCHAR name[MAX_PATH]; + DWORD len = GetFinalPathNameByHandle(th, name, MAX_PATH, 0); + if (len > 0) { + if (len < MAX_PATH) { + result = env->NewString((jchar *)name, len); + } + else { + TCHAR *name = (TCHAR *)malloc(sizeof(TCHAR) * (len + 1)); + if (name != NULL) { + len = GetFinalPathNameByHandle(th, name, len, 0); + if (len > 0) { + result = env->NewString((jchar *)name, len); + } + free(name); + } + } + } + + CloseHandle(th); + return result; } -JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_vfs_impl_win32_IdeaWin32_listChildren(JNIEnv *env, jobject method, jstring path) { + +JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_listChildren(JNIEnv *env, jobject method, jstring path) { WIN32_FIND_DATA data; HANDLE h = FindFileInner(env, path, &data); if (h == INVALID_HANDLE_VALUE) { return NULL; } + jclass fileInfoClass = getFileInfoClass(env); + if (fileInfoClass == NULL) { + return NULL; + } + jobjectArray rv, old; int len = 0, maxlen = 16; - jclass infoClass = env->FindClass("com/intellij/openapi/vfs/impl/win32/FileInfo"); - rv = env->NewObjectArray(maxlen, infoClass, NULL); + rv = env->NewObjectArray(maxlen, fileInfoClass, NULL); if (rv == NULL) { goto error; } @@ -122,13 +209,13 @@ JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_vfs_impl_win32_IdeaWin3 do { if (len == maxlen) { old = rv; - rv = env->NewObjectArray(maxlen <<= 1, infoClass, NULL); + rv = env->NewObjectArray(maxlen <<= 1, fileInfoClass, NULL); if (rv == NULL || !CopyObjectArray(env, rv, old, len)) { goto error; } env->DeleteLocalRef(old); } - jobject o = CreateFileInfo(env, path, true, &data, infoClass); + jobject o = CreateFileInfo(env, path, true, &data, fileInfoClass); env->SetObjectArrayElement(rv, len++, o); env->DeleteLocalRef(o); } @@ -137,7 +224,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_vfs_impl_win32_IdeaWin3 FindClose(h); old = rv; - rv = env->NewObjectArray(len, infoClass, NULL); + rv = env->NewObjectArray(len, fileInfoClass, NULL); if (rv == NULL || !CopyObjectArray(env, rv, old, len)) { goto error; } @@ -148,6 +235,7 @@ error: return NULL; } -BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; } diff --git a/native/IdeaWin32/IdeaWin32.h b/native/IdeaWin32/IdeaWin32.h index 2fe5bd16e17d..67173207e1f1 100644 --- a/native/IdeaWin32/IdeaWin32.h +++ b/native/IdeaWin32/IdeaWin32.h @@ -1,15 +1,40 @@ -#include "jni.h" +/* + * 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. + */ +#include + +#ifndef _Included_com_intellij_openapi_util_io_win32_IdeaWin32 +#define _Included_com_intellij_openapi_util_io_win32_IdeaWin32 #ifdef __cplusplus extern "C" { #endif -JNIEXPORT void JNICALL Java_com_intellij_openapi_vfs_impl_win32_FileInfo_initIDs(JNIEnv *env, jclass cls); +JNIEXPORT void JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_initIDs + (JNIEnv *, jclass); -JNIEXPORT jobject JNICALL Java_com_intellij_openapi_vfs_impl_win32_IdeaWin32_getInfo(JNIEnv *env, jobject method, jstring path); +JNIEXPORT jobject JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_getInfo + (JNIEnv *, jobject, jstring); -JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_vfs_impl_win32_IdeaWin32_listChildren(JNIEnv *env, jobject method, jstring path); +JNIEXPORT jstring JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_resolveSymLink + (JNIEnv *, jobject, jstring); + +JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_listChildren + (JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif +#endif diff --git a/native/IdeaWin32/IdeaWin32.props b/native/IdeaWin32/IdeaWin32.props new file mode 100644 index 000000000000..467d726981e9 --- /dev/null +++ b/native/IdeaWin32/IdeaWin32.props @@ -0,0 +1,17 @@ + + + + + C:\Tools\JDK6 + + + $(Configuration)$(Platform)\ + $(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;$(JAVA_HOME)\include;$(JAVA_HOME)\include\win32 + + + + + $(JAVA_HOME) + + + \ No newline at end of file diff --git a/native/IdeaWin32/IdeaWin32.sln b/native/IdeaWin32/IdeaWin32.sln index fd410bf12728..05286e510063 100644 --- a/native/IdeaWin32/IdeaWin32.sln +++ b/native/IdeaWin32/IdeaWin32.sln @@ -1,18 +1,24 @@  -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IdeaWin32", "IdeaWin32.vcproj", "{D1A0CC4B-C100-46E4-918A-958626AE1ACF}" +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IdeaWin32", "IdeaWin32.vcxproj", "{F68FFBFC-3437-4215-839A-563936B9A3CC}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D1A0CC4B-C100-46E4-918A-958626AE1ACF}.Debug|Win32.ActiveCfg = Debug|Win32 - {D1A0CC4B-C100-46E4-918A-958626AE1ACF}.Debug|Win32.Build.0 = Debug|Win32 - {D1A0CC4B-C100-46E4-918A-958626AE1ACF}.Release|Win32.ActiveCfg = Release|Win32 - {D1A0CC4B-C100-46E4-918A-958626AE1ACF}.Release|Win32.Build.0 = Release|Win32 + {F68FFBFC-3437-4215-839A-563936B9A3CC}.Debug|Win32.ActiveCfg = Debug|Win32 + {F68FFBFC-3437-4215-839A-563936B9A3CC}.Debug|Win32.Build.0 = Debug|Win32 + {F68FFBFC-3437-4215-839A-563936B9A3CC}.Debug|x64.ActiveCfg = Debug|x64 + {F68FFBFC-3437-4215-839A-563936B9A3CC}.Debug|x64.Build.0 = Debug|x64 + {F68FFBFC-3437-4215-839A-563936B9A3CC}.Release|Win32.ActiveCfg = Release|Win32 + {F68FFBFC-3437-4215-839A-563936B9A3CC}.Release|Win32.Build.0 = Release|Win32 + {F68FFBFC-3437-4215-839A-563936B9A3CC}.Release|x64.ActiveCfg = Release|x64 + {F68FFBFC-3437-4215-839A-563936B9A3CC}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/native/IdeaWin32/IdeaWin32.vcproj b/native/IdeaWin32/IdeaWin32.vcproj deleted file mode 100644 index 4f26b1821867..000000000000 --- a/native/IdeaWin32/IdeaWin32.vcproj +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/native/IdeaWin32/IdeaWin32.vcxproj b/native/IdeaWin32/IdeaWin32.vcxproj new file mode 100644 index 000000000000..bdf7114484b6 --- /dev/null +++ b/native/IdeaWin32/IdeaWin32.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {F68FFBFC-3437-4215-839A-563936B9A3CC} + Win32Proj + IdeaWin32 + + + + DynamicLibrary + true + Unicode + Windows7.1SDK + + + DynamicLibrary + true + Unicode + Windows7.1SDK + + + DynamicLibrary + false + true + Unicode + Windows7.1SDK + + + DynamicLibrary + false + true + Unicode + Windows7.1SDK + + + + + + + + + + + + + + + + + + + + + + + false + $(Configuration)$(Platform)\ + IdeaWin32 + + + false + $(Configuration)$(Platform)\ + IdeaWin64 + + + false + $(Configuration)$(Platform)\ + IdeaWin32 + + + false + $(Configuration)$(Platform)\ + IdeaWin64 + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;IDEAWIN32_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + Windows + true + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;IDEAWIN32_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + Windows + true + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;IDEAWIN32_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + + + Windows + true + true + true + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;IDEAWIN32_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + + + Windows + true + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/native/IdeaWin32/IdeaWin32.vcxproj.filters b/native/IdeaWin32/IdeaWin32.vcxproj.filters new file mode 100644 index 000000000000..cf3b94ffcf16 --- /dev/null +++ b/native/IdeaWin32/IdeaWin32.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/native/IdeaWin32/IdeaWin32.vcxproj.user b/native/IdeaWin32/IdeaWin32.vcxproj.user new file mode 100644 index 000000000000..ace9a86acb77 --- /dev/null +++ b/native/IdeaWin32/IdeaWin32.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/native/IdeaWin32/jlong.h b/native/IdeaWin32/jlong.h deleted file mode 100644 index d3fe33fd58c7..000000000000 --- a/native/IdeaWin32/jlong.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 1997 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -#ifndef _JLONG_H_ -#define _JLONG_H_ - -#include "jlong_md.h" - -#endif diff --git a/native/IdeaWin32/jlong_md.h b/native/IdeaWin32/jlong_md.h deleted file mode 100644 index 8b62f26c37e1..000000000000 --- a/native/IdeaWin32/jlong_md.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 1997-2002 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -#ifndef _WIN32_JLONG_MD_H_ -#define _WIN32_JLONG_MD_H_ - -/* Make sure ptrdiff_t is defined */ -#include - -#define jlong_high(a) ((jint)((a)>>32)) -#define jlong_low(a) ((jint)(a)) -#define jlong_add(a, b) ((a) + (b)) -#define jlong_and(a, b) ((a) & (b)) -#define jlong_div(a, b) ((a) / (b)) -#define jlong_mul(a, b) ((a) * (b)) -#define jlong_neg(a) (-(a)) -#define jlong_not(a) (~(a)) -#define jlong_or(a, b) ((a) | (b)) -#define jlong_shl(a, n) ((a) << (n)) -#define jlong_shr(a, n) ((a) >> (n)) -#define jlong_sub(a, b) ((a) - (b)) -#define jlong_xor(a, b) ((a) ^ (b)) -#define jlong_rem(a,b) ((a) % (b)) - -/* comparison operators */ -#define jlong_ltz(ll) ((ll) < 0) -#define jlong_gez(ll) ((ll) >= 0) -#define jlong_gtz(ll) ((ll) > 0) -#define jlong_eqz(a) ((a) == 0) -#define jlong_eq(a, b) ((a) == (b)) -#define jlong_ne(a,b) ((a) != (b)) -#define jlong_ge(a,b) ((a) >= (b)) -#define jlong_le(a,b) ((a) <= (b)) -#define jlong_lt(a,b) ((a) < (b)) -#define jlong_gt(a,b) ((a) > (b)) - -#define jlong_zero ((jlong) 0) -#define jlong_one ((jlong) 1) -#define jlong_minus_one ((jlong) -1) - -/* For static variables initialized to zero */ -#define jlong_zero_init ((jlong) 0) - -#ifdef _WIN64 -#define jlong_to_ptr(a) ((void*)(a)) -#define ptr_to_jlong(a) ((jlong)(a)) -#else -/* Double casting to avoid warning messages looking for casting of */ -/* smaller sizes into pointers */ -#define jlong_to_ptr(a) ((void*)(int)(a)) -#define ptr_to_jlong(a) ((jlong)(int)(a)) -#endif - -#define jint_to_jlong(a) ((jlong)(a)) -#define jlong_to_jint(a) ((jint)(a)) - -/* Useful on machines where jlong and jdouble have different endianness. */ -#define jlong_to_jdouble_bits(a) -#define jdouble_to_jlong_bits(a) - -#define jlong_to_int(a) ((int)(a)) -#define int_to_jlong(a) ((jlong)(a)) -#define jlong_to_uint(a) ((unsigned int)(a)) -#define uint_to_jlong(a) ((jlong)(a)) -#define jlong_to_ptrdiff(a) ((ptrdiff_t)(a)) -#define ptrdiff_to_jlong(a) ((jlong)(a)) -#define jlong_to_size(a) ((size_t)(a)) -#define size_to_jlong(a) ((jlong)(a)) -#define long_to_jlong(a) ((jlong)(a)) - -#endif diff --git a/native/IdeaWin32/jni.h b/native/IdeaWin32/jni.h deleted file mode 100644 index f53476c09671..000000000000 --- a/native/IdeaWin32/jni.h +++ /dev/null @@ -1,1944 +0,0 @@ -/* - * @(#)jni.h 1.62 06/02/02 - * - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -/* - * We used part of Netscape's Java Runtime Interface (JRI) as the starting - * point of our design and implementation. - */ - -/****************************************************************************** - * Java Runtime Interface - * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved. - *****************************************************************************/ - -#ifndef _JAVASOFT_JNI_H_ -#define _JAVASOFT_JNI_H_ - -#include -#include - -/* jni_md.h contains the machine-dependent typedefs for jbyte, jint - and jlong */ - -#include "jni_md.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * JNI Types - */ - -#ifndef JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H - -typedef unsigned char jboolean; -typedef unsigned short jchar; -typedef short jshort; -typedef float jfloat; -typedef double jdouble; - -typedef jint jsize; - -#ifdef __cplusplus - -class _jobject {}; -class _jclass : public _jobject {}; -class _jthrowable : public _jobject {}; -class _jstring : public _jobject {}; -class _jarray : public _jobject {}; -class _jbooleanArray : public _jarray {}; -class _jbyteArray : public _jarray {}; -class _jcharArray : public _jarray {}; -class _jshortArray : public _jarray {}; -class _jintArray : public _jarray {}; -class _jlongArray : public _jarray {}; -class _jfloatArray : public _jarray {}; -class _jdoubleArray : public _jarray {}; -class _jobjectArray : public _jarray {}; - -typedef _jobject *jobject; -typedef _jclass *jclass; -typedef _jthrowable *jthrowable; -typedef _jstring *jstring; -typedef _jarray *jarray; -typedef _jbooleanArray *jbooleanArray; -typedef _jbyteArray *jbyteArray; -typedef _jcharArray *jcharArray; -typedef _jshortArray *jshortArray; -typedef _jintArray *jintArray; -typedef _jlongArray *jlongArray; -typedef _jfloatArray *jfloatArray; -typedef _jdoubleArray *jdoubleArray; -typedef _jobjectArray *jobjectArray; - -#else - -struct _jobject; - -typedef struct _jobject *jobject; -typedef jobject jclass; -typedef jobject jthrowable; -typedef jobject jstring; -typedef jobject jarray; -typedef jarray jbooleanArray; -typedef jarray jbyteArray; -typedef jarray jcharArray; -typedef jarray jshortArray; -typedef jarray jintArray; -typedef jarray jlongArray; -typedef jarray jfloatArray; -typedef jarray jdoubleArray; -typedef jarray jobjectArray; - -#endif - -typedef jobject jweak; - -typedef union jvalue { - jboolean z; - jbyte b; - jchar c; - jshort s; - jint i; - jlong j; - jfloat f; - jdouble d; - jobject l; -} jvalue; - -struct _jfieldID; -typedef struct _jfieldID *jfieldID; - -struct _jmethodID; -typedef struct _jmethodID *jmethodID; - -/* Return values from jobjectRefType */ -typedef enum _jobjectType { - JNIInvalidRefType = 0, - JNILocalRefType = 1, - JNIGlobalRefType = 2, - JNIWeakGlobalRefType = 3 -} jobjectRefType; - - -#endif /* JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H */ - -/* - * jboolean constants - */ - -#define JNI_FALSE 0 -#define JNI_TRUE 1 - -/* - * possible return values for JNI functions. - */ - -#define JNI_OK 0 /* success */ -#define JNI_ERR (-1) /* unknown error */ -#define JNI_EDETACHED (-2) /* thread detached from the VM */ -#define JNI_EVERSION (-3) /* JNI version error */ -#define JNI_ENOMEM (-4) /* not enough memory */ -#define JNI_EEXIST (-5) /* VM already created */ -#define JNI_EINVAL (-6) /* invalid arguments */ - -/* - * used in ReleaseScalarArrayElements - */ - -#define JNI_COMMIT 1 -#define JNI_ABORT 2 - -/* - * used in RegisterNatives to describe native method name, signature, - * and function pointer. - */ - -typedef struct { - char *name; - char *signature; - void *fnPtr; -} JNINativeMethod; - -/* - * JNI Native Method Interface. - */ - -struct JNINativeInterface_; - -struct JNIEnv_; - -#ifdef __cplusplus -typedef JNIEnv_ JNIEnv; -#else -typedef const struct JNINativeInterface_ *JNIEnv; -#endif - -/* - * JNI Invocation Interface. - */ - -struct JNIInvokeInterface_; - -struct JavaVM_; - -#ifdef __cplusplus -typedef JavaVM_ JavaVM; -#else -typedef const struct JNIInvokeInterface_ *JavaVM; -#endif - -struct JNINativeInterface_ { - void *reserved0; - void *reserved1; - void *reserved2; - - void *reserved3; - jint (JNICALL *GetVersion)(JNIEnv *env); - - jclass (JNICALL *DefineClass) - (JNIEnv *env, const char *name, jobject loader, const jbyte *buf, - jsize len); - jclass (JNICALL *FindClass) - (JNIEnv *env, const char *name); - - jmethodID (JNICALL *FromReflectedMethod) - (JNIEnv *env, jobject method); - jfieldID (JNICALL *FromReflectedField) - (JNIEnv *env, jobject field); - - jobject (JNICALL *ToReflectedMethod) - (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic); - - jclass (JNICALL *GetSuperclass) - (JNIEnv *env, jclass sub); - jboolean (JNICALL *IsAssignableFrom) - (JNIEnv *env, jclass sub, jclass sup); - - jobject (JNICALL *ToReflectedField) - (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic); - - jint (JNICALL *Throw) - (JNIEnv *env, jthrowable obj); - jint (JNICALL *ThrowNew) - (JNIEnv *env, jclass clazz, const char *msg); - jthrowable (JNICALL *ExceptionOccurred) - (JNIEnv *env); - void (JNICALL *ExceptionDescribe) - (JNIEnv *env); - void (JNICALL *ExceptionClear) - (JNIEnv *env); - void (JNICALL *FatalError) - (JNIEnv *env, const char *msg); - - jint (JNICALL *PushLocalFrame) - (JNIEnv *env, jint capacity); - jobject (JNICALL *PopLocalFrame) - (JNIEnv *env, jobject result); - - jobject (JNICALL *NewGlobalRef) - (JNIEnv *env, jobject lobj); - void (JNICALL *DeleteGlobalRef) - (JNIEnv *env, jobject gref); - void (JNICALL *DeleteLocalRef) - (JNIEnv *env, jobject obj); - jboolean (JNICALL *IsSameObject) - (JNIEnv *env, jobject obj1, jobject obj2); - jobject (JNICALL *NewLocalRef) - (JNIEnv *env, jobject ref); - jint (JNICALL *EnsureLocalCapacity) - (JNIEnv *env, jint capacity); - - jobject (JNICALL *AllocObject) - (JNIEnv *env, jclass clazz); - jobject (JNICALL *NewObject) - (JNIEnv *env, jclass clazz, jmethodID methodID, ...); - jobject (JNICALL *NewObjectV) - (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); - jobject (JNICALL *NewObjectA) - (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); - - jclass (JNICALL *GetObjectClass) - (JNIEnv *env, jobject obj); - jboolean (JNICALL *IsInstanceOf) - (JNIEnv *env, jobject obj, jclass clazz); - - jmethodID (JNICALL *GetMethodID) - (JNIEnv *env, jclass clazz, const char *name, const char *sig); - - jobject (JNICALL *CallObjectMethod) - (JNIEnv *env, jobject obj, jmethodID methodID, ...); - jobject (JNICALL *CallObjectMethodV) - (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); - jobject (JNICALL *CallObjectMethodA) - (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args); - - jboolean (JNICALL *CallBooleanMethod) - (JNIEnv *env, jobject obj, jmethodID methodID, ...); - jboolean (JNICALL *CallBooleanMethodV) - (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); - jboolean (JNICALL *CallBooleanMethodA) - (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args); - - jbyte (JNICALL *CallByteMethod) - (JNIEnv *env, jobject obj, jmethodID methodID, ...); - jbyte (JNICALL *CallByteMethodV) - (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); - jbyte (JNICALL *CallByteMethodA) - (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); - - jchar (JNICALL *CallCharMethod) - (JNIEnv *env, jobject obj, jmethodID methodID, ...); - jchar (JNICALL *CallCharMethodV) - (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); - jchar (JNICALL *CallCharMethodA) - (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); - - jshort (JNICALL *CallShortMethod) - (JNIEnv *env, jobject obj, jmethodID methodID, ...); - jshort (JNICALL *CallShortMethodV) - (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); - jshort (JNICALL *CallShortMethodA) - (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); - - jint (JNICALL *CallIntMethod) - (JNIEnv *env, jobject obj, jmethodID methodID, ...); - jint (JNICALL *CallIntMethodV) - (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); - jint (JNICALL *CallIntMethodA) - (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); - - jlong (JNICALL *CallLongMethod) - (JNIEnv *env, jobject obj, jmethodID methodID, ...); - jlong (JNICALL *CallLongMethodV) - (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); - jlong (JNICALL *CallLongMethodA) - (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); - - jfloat (JNICALL *CallFloatMethod) - (JNIEnv *env, jobject obj, jmethodID methodID, ...); - jfloat (JNICALL *CallFloatMethodV) - (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); - jfloat (JNICALL *CallFloatMethodA) - (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); - - jdouble (JNICALL *CallDoubleMethod) - (JNIEnv *env, jobject obj, jmethodID methodID, ...); - jdouble (JNICALL *CallDoubleMethodV) - (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); - jdouble (JNICALL *CallDoubleMethodA) - (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); - - void (JNICALL *CallVoidMethod) - (JNIEnv *env, jobject obj, jmethodID methodID, ...); - void (JNICALL *CallVoidMethodV) - (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); - void (JNICALL *CallVoidMethodA) - (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args); - - jobject (JNICALL *CallNonvirtualObjectMethod) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); - jobject (JNICALL *CallNonvirtualObjectMethodV) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - va_list args); - jobject (JNICALL *CallNonvirtualObjectMethodA) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - const jvalue * args); - - jboolean (JNICALL *CallNonvirtualBooleanMethod) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); - jboolean (JNICALL *CallNonvirtualBooleanMethodV) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - va_list args); - jboolean (JNICALL *CallNonvirtualBooleanMethodA) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - const jvalue * args); - - jbyte (JNICALL *CallNonvirtualByteMethod) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); - jbyte (JNICALL *CallNonvirtualByteMethodV) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - va_list args); - jbyte (JNICALL *CallNonvirtualByteMethodA) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - const jvalue *args); - - jchar (JNICALL *CallNonvirtualCharMethod) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); - jchar (JNICALL *CallNonvirtualCharMethodV) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - va_list args); - jchar (JNICALL *CallNonvirtualCharMethodA) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - const jvalue *args); - - jshort (JNICALL *CallNonvirtualShortMethod) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); - jshort (JNICALL *CallNonvirtualShortMethodV) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - va_list args); - jshort (JNICALL *CallNonvirtualShortMethodA) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - const jvalue *args); - - jint (JNICALL *CallNonvirtualIntMethod) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); - jint (JNICALL *CallNonvirtualIntMethodV) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - va_list args); - jint (JNICALL *CallNonvirtualIntMethodA) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - const jvalue *args); - - jlong (JNICALL *CallNonvirtualLongMethod) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); - jlong (JNICALL *CallNonvirtualLongMethodV) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - va_list args); - jlong (JNICALL *CallNonvirtualLongMethodA) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - const jvalue *args); - - jfloat (JNICALL *CallNonvirtualFloatMethod) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); - jfloat (JNICALL *CallNonvirtualFloatMethodV) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - va_list args); - jfloat (JNICALL *CallNonvirtualFloatMethodA) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - const jvalue *args); - - jdouble (JNICALL *CallNonvirtualDoubleMethod) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); - jdouble (JNICALL *CallNonvirtualDoubleMethodV) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - va_list args); - jdouble (JNICALL *CallNonvirtualDoubleMethodA) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - const jvalue *args); - - void (JNICALL *CallNonvirtualVoidMethod) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); - void (JNICALL *CallNonvirtualVoidMethodV) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - va_list args); - void (JNICALL *CallNonvirtualVoidMethodA) - (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, - const jvalue * args); - - jfieldID (JNICALL *GetFieldID) - (JNIEnv *env, jclass clazz, const char *name, const char *sig); - - jobject (JNICALL *GetObjectField) - (JNIEnv *env, jobject obj, jfieldID fieldID); - jboolean (JNICALL *GetBooleanField) - (JNIEnv *env, jobject obj, jfieldID fieldID); - jbyte (JNICALL *GetByteField) - (JNIEnv *env, jobject obj, jfieldID fieldID); - jchar (JNICALL *GetCharField) - (JNIEnv *env, jobject obj, jfieldID fieldID); - jshort (JNICALL *GetShortField) - (JNIEnv *env, jobject obj, jfieldID fieldID); - jint (JNICALL *GetIntField) - (JNIEnv *env, jobject obj, jfieldID fieldID); - jlong (JNICALL *GetLongField) - (JNIEnv *env, jobject obj, jfieldID fieldID); - jfloat (JNICALL *GetFloatField) - (JNIEnv *env, jobject obj, jfieldID fieldID); - jdouble (JNICALL *GetDoubleField) - (JNIEnv *env, jobject obj, jfieldID fieldID); - - void (JNICALL *SetObjectField) - (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val); - void (JNICALL *SetBooleanField) - (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val); - void (JNICALL *SetByteField) - (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val); - void (JNICALL *SetCharField) - (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val); - void (JNICALL *SetShortField) - (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val); - void (JNICALL *SetIntField) - (JNIEnv *env, jobject obj, jfieldID fieldID, jint val); - void (JNICALL *SetLongField) - (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val); - void (JNICALL *SetFloatField) - (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val); - void (JNICALL *SetDoubleField) - (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val); - - jmethodID (JNICALL *GetStaticMethodID) - (JNIEnv *env, jclass clazz, const char *name, const char *sig); - - jobject (JNICALL *CallStaticObjectMethod) - (JNIEnv *env, jclass clazz, jmethodID methodID, ...); - jobject (JNICALL *CallStaticObjectMethodV) - (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); - jobject (JNICALL *CallStaticObjectMethodA) - (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); - - jboolean (JNICALL *CallStaticBooleanMethod) - (JNIEnv *env, jclass clazz, jmethodID methodID, ...); - jboolean (JNICALL *CallStaticBooleanMethodV) - (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); - jboolean (JNICALL *CallStaticBooleanMethodA) - (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); - - jbyte (JNICALL *CallStaticByteMethod) - (JNIEnv *env, jclass clazz, jmethodID methodID, ...); - jbyte (JNICALL *CallStaticByteMethodV) - (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); - jbyte (JNICALL *CallStaticByteMethodA) - (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); - - jchar (JNICALL *CallStaticCharMethod) - (JNIEnv *env, jclass clazz, jmethodID methodID, ...); - jchar (JNICALL *CallStaticCharMethodV) - (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); - jchar (JNICALL *CallStaticCharMethodA) - (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); - - jshort (JNICALL *CallStaticShortMethod) - (JNIEnv *env, jclass clazz, jmethodID methodID, ...); - jshort (JNICALL *CallStaticShortMethodV) - (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); - jshort (JNICALL *CallStaticShortMethodA) - (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); - - jint (JNICALL *CallStaticIntMethod) - (JNIEnv *env, jclass clazz, jmethodID methodID, ...); - jint (JNICALL *CallStaticIntMethodV) - (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); - jint (JNICALL *CallStaticIntMethodA) - (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); - - jlong (JNICALL *CallStaticLongMethod) - (JNIEnv *env, jclass clazz, jmethodID methodID, ...); - jlong (JNICALL *CallStaticLongMethodV) - (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); - jlong (JNICALL *CallStaticLongMethodA) - (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); - - jfloat (JNICALL *CallStaticFloatMethod) - (JNIEnv *env, jclass clazz, jmethodID methodID, ...); - jfloat (JNICALL *CallStaticFloatMethodV) - (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); - jfloat (JNICALL *CallStaticFloatMethodA) - (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); - - jdouble (JNICALL *CallStaticDoubleMethod) - (JNIEnv *env, jclass clazz, jmethodID methodID, ...); - jdouble (JNICALL *CallStaticDoubleMethodV) - (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); - jdouble (JNICALL *CallStaticDoubleMethodA) - (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); - - void (JNICALL *CallStaticVoidMethod) - (JNIEnv *env, jclass cls, jmethodID methodID, ...); - void (JNICALL *CallStaticVoidMethodV) - (JNIEnv *env, jclass cls, jmethodID methodID, va_list args); - void (JNICALL *CallStaticVoidMethodA) - (JNIEnv *env, jclass cls, jmethodID methodID, const jvalue * args); - - jfieldID (JNICALL *GetStaticFieldID) - (JNIEnv *env, jclass clazz, const char *name, const char *sig); - jobject (JNICALL *GetStaticObjectField) - (JNIEnv *env, jclass clazz, jfieldID fieldID); - jboolean (JNICALL *GetStaticBooleanField) - (JNIEnv *env, jclass clazz, jfieldID fieldID); - jbyte (JNICALL *GetStaticByteField) - (JNIEnv *env, jclass clazz, jfieldID fieldID); - jchar (JNICALL *GetStaticCharField) - (JNIEnv *env, jclass clazz, jfieldID fieldID); - jshort (JNICALL *GetStaticShortField) - (JNIEnv *env, jclass clazz, jfieldID fieldID); - jint (JNICALL *GetStaticIntField) - (JNIEnv *env, jclass clazz, jfieldID fieldID); - jlong (JNICALL *GetStaticLongField) - (JNIEnv *env, jclass clazz, jfieldID fieldID); - jfloat (JNICALL *GetStaticFloatField) - (JNIEnv *env, jclass clazz, jfieldID fieldID); - jdouble (JNICALL *GetStaticDoubleField) - (JNIEnv *env, jclass clazz, jfieldID fieldID); - - void (JNICALL *SetStaticObjectField) - (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value); - void (JNICALL *SetStaticBooleanField) - (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value); - void (JNICALL *SetStaticByteField) - (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value); - void (JNICALL *SetStaticCharField) - (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value); - void (JNICALL *SetStaticShortField) - (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value); - void (JNICALL *SetStaticIntField) - (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value); - void (JNICALL *SetStaticLongField) - (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value); - void (JNICALL *SetStaticFloatField) - (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value); - void (JNICALL *SetStaticDoubleField) - (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value); - - jstring (JNICALL *NewString) - (JNIEnv *env, const jchar *unicode, jsize len); - jsize (JNICALL *GetStringLength) - (JNIEnv *env, jstring str); - const jchar *(JNICALL *GetStringChars) - (JNIEnv *env, jstring str, jboolean *isCopy); - void (JNICALL *ReleaseStringChars) - (JNIEnv *env, jstring str, const jchar *chars); - - jstring (JNICALL *NewStringUTF) - (JNIEnv *env, const char *utf); - jsize (JNICALL *GetStringUTFLength) - (JNIEnv *env, jstring str); - const char* (JNICALL *GetStringUTFChars) - (JNIEnv *env, jstring str, jboolean *isCopy); - void (JNICALL *ReleaseStringUTFChars) - (JNIEnv *env, jstring str, const char* chars); - - - jsize (JNICALL *GetArrayLength) - (JNIEnv *env, jarray array); - - jobjectArray (JNICALL *NewObjectArray) - (JNIEnv *env, jsize len, jclass clazz, jobject init); - jobject (JNICALL *GetObjectArrayElement) - (JNIEnv *env, jobjectArray array, jsize index); - void (JNICALL *SetObjectArrayElement) - (JNIEnv *env, jobjectArray array, jsize index, jobject val); - - jbooleanArray (JNICALL *NewBooleanArray) - (JNIEnv *env, jsize len); - jbyteArray (JNICALL *NewByteArray) - (JNIEnv *env, jsize len); - jcharArray (JNICALL *NewCharArray) - (JNIEnv *env, jsize len); - jshortArray (JNICALL *NewShortArray) - (JNIEnv *env, jsize len); - jintArray (JNICALL *NewIntArray) - (JNIEnv *env, jsize len); - jlongArray (JNICALL *NewLongArray) - (JNIEnv *env, jsize len); - jfloatArray (JNICALL *NewFloatArray) - (JNIEnv *env, jsize len); - jdoubleArray (JNICALL *NewDoubleArray) - (JNIEnv *env, jsize len); - - jboolean * (JNICALL *GetBooleanArrayElements) - (JNIEnv *env, jbooleanArray array, jboolean *isCopy); - jbyte * (JNICALL *GetByteArrayElements) - (JNIEnv *env, jbyteArray array, jboolean *isCopy); - jchar * (JNICALL *GetCharArrayElements) - (JNIEnv *env, jcharArray array, jboolean *isCopy); - jshort * (JNICALL *GetShortArrayElements) - (JNIEnv *env, jshortArray array, jboolean *isCopy); - jint * (JNICALL *GetIntArrayElements) - (JNIEnv *env, jintArray array, jboolean *isCopy); - jlong * (JNICALL *GetLongArrayElements) - (JNIEnv *env, jlongArray array, jboolean *isCopy); - jfloat * (JNICALL *GetFloatArrayElements) - (JNIEnv *env, jfloatArray array, jboolean *isCopy); - jdouble * (JNICALL *GetDoubleArrayElements) - (JNIEnv *env, jdoubleArray array, jboolean *isCopy); - - void (JNICALL *ReleaseBooleanArrayElements) - (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode); - void (JNICALL *ReleaseByteArrayElements) - (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode); - void (JNICALL *ReleaseCharArrayElements) - (JNIEnv *env, jcharArray array, jchar *elems, jint mode); - void (JNICALL *ReleaseShortArrayElements) - (JNIEnv *env, jshortArray array, jshort *elems, jint mode); - void (JNICALL *ReleaseIntArrayElements) - (JNIEnv *env, jintArray array, jint *elems, jint mode); - void (JNICALL *ReleaseLongArrayElements) - (JNIEnv *env, jlongArray array, jlong *elems, jint mode); - void (JNICALL *ReleaseFloatArrayElements) - (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode); - void (JNICALL *ReleaseDoubleArrayElements) - (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode); - - void (JNICALL *GetBooleanArrayRegion) - (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf); - void (JNICALL *GetByteArrayRegion) - (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf); - void (JNICALL *GetCharArrayRegion) - (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf); - void (JNICALL *GetShortArrayRegion) - (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf); - void (JNICALL *GetIntArrayRegion) - (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf); - void (JNICALL *GetLongArrayRegion) - (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf); - void (JNICALL *GetFloatArrayRegion) - (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf); - void (JNICALL *GetDoubleArrayRegion) - (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf); - - void (JNICALL *SetBooleanArrayRegion) - (JNIEnv *env, jbooleanArray array, jsize start, jsize l, const jboolean *buf); - void (JNICALL *SetByteArrayRegion) - (JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf); - void (JNICALL *SetCharArrayRegion) - (JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf); - void (JNICALL *SetShortArrayRegion) - (JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf); - void (JNICALL *SetIntArrayRegion) - (JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf); - void (JNICALL *SetLongArrayRegion) - (JNIEnv *env, jlongArray array, jsize start, jsize len, const jlong *buf); - void (JNICALL *SetFloatArrayRegion) - (JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf); - void (JNICALL *SetDoubleArrayRegion) - (JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf); - - jint (JNICALL *RegisterNatives) - (JNIEnv *env, jclass clazz, const JNINativeMethod *methods, - jint nMethods); - jint (JNICALL *UnregisterNatives) - (JNIEnv *env, jclass clazz); - - jint (JNICALL *MonitorEnter) - (JNIEnv *env, jobject obj); - jint (JNICALL *MonitorExit) - (JNIEnv *env, jobject obj); - - jint (JNICALL *GetJavaVM) - (JNIEnv *env, JavaVM **vm); - - void (JNICALL *GetStringRegion) - (JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf); - void (JNICALL *GetStringUTFRegion) - (JNIEnv *env, jstring str, jsize start, jsize len, char *buf); - - void * (JNICALL *GetPrimitiveArrayCritical) - (JNIEnv *env, jarray array, jboolean *isCopy); - void (JNICALL *ReleasePrimitiveArrayCritical) - (JNIEnv *env, jarray array, void *carray, jint mode); - - const jchar * (JNICALL *GetStringCritical) - (JNIEnv *env, jstring string, jboolean *isCopy); - void (JNICALL *ReleaseStringCritical) - (JNIEnv *env, jstring string, const jchar *cstring); - - jweak (JNICALL *NewWeakGlobalRef) - (JNIEnv *env, jobject obj); - void (JNICALL *DeleteWeakGlobalRef) - (JNIEnv *env, jweak ref); - - jboolean (JNICALL *ExceptionCheck) - (JNIEnv *env); - - jobject (JNICALL *NewDirectByteBuffer) - (JNIEnv* env, void* address, jlong capacity); - void* (JNICALL *GetDirectBufferAddress) - (JNIEnv* env, jobject buf); - jlong (JNICALL *GetDirectBufferCapacity) - (JNIEnv* env, jobject buf); - - /* New JNI 1.6 Features */ - - jobjectRefType (JNICALL *GetObjectRefType) - (JNIEnv* env, jobject obj); -}; - -/* - * We use inlined functions for C++ so that programmers can write: - * - * env->FindClass("java/lang/String") - * - * in C++ rather than: - * - * (*env)->FindClass(env, "java/lang/String") - * - * in C. - */ - -struct JNIEnv_ { - const struct JNINativeInterface_ *functions; -#ifdef __cplusplus - - jint GetVersion() { - return functions->GetVersion(this); - } - jclass DefineClass(const char *name, jobject loader, const jbyte *buf, - jsize len) { - return functions->DefineClass(this, name, loader, buf, len); - } - jclass FindClass(const char *name) { - return functions->FindClass(this, name); - } - jmethodID FromReflectedMethod(jobject method) { - return functions->FromReflectedMethod(this,method); - } - jfieldID FromReflectedField(jobject field) { - return functions->FromReflectedField(this,field); - } - - jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) { - return functions->ToReflectedMethod(this, cls, methodID, isStatic); - } - - jclass GetSuperclass(jclass sub) { - return functions->GetSuperclass(this, sub); - } - jboolean IsAssignableFrom(jclass sub, jclass sup) { - return functions->IsAssignableFrom(this, sub, sup); - } - - jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) { - return functions->ToReflectedField(this,cls,fieldID,isStatic); - } - - jint Throw(jthrowable obj) { - return functions->Throw(this, obj); - } - jint ThrowNew(jclass clazz, const char *msg) { - return functions->ThrowNew(this, clazz, msg); - } - jthrowable ExceptionOccurred() { - return functions->ExceptionOccurred(this); - } - void ExceptionDescribe() { - functions->ExceptionDescribe(this); - } - void ExceptionClear() { - functions->ExceptionClear(this); - } - void FatalError(const char *msg) { - functions->FatalError(this, msg); - } - - jint PushLocalFrame(jint capacity) { - return functions->PushLocalFrame(this,capacity); - } - jobject PopLocalFrame(jobject result) { - return functions->PopLocalFrame(this,result); - } - - jobject NewGlobalRef(jobject lobj) { - return functions->NewGlobalRef(this,lobj); - } - void DeleteGlobalRef(jobject gref) { - functions->DeleteGlobalRef(this,gref); - } - void DeleteLocalRef(jobject obj) { - functions->DeleteLocalRef(this, obj); - } - - jboolean IsSameObject(jobject obj1, jobject obj2) { - return functions->IsSameObject(this,obj1,obj2); - } - - jobject NewLocalRef(jobject ref) { - return functions->NewLocalRef(this,ref); - } - jint EnsureLocalCapacity(jint capacity) { - return functions->EnsureLocalCapacity(this,capacity); - } - - jobject AllocObject(jclass clazz) { - return functions->AllocObject(this,clazz); - } - jobject NewObject(jclass clazz, jmethodID methodID, ...) { - va_list args; - jobject result; - va_start(args, methodID); - result = functions->NewObjectV(this,clazz,methodID,args); - va_end(args); - return result; - } - jobject NewObjectV(jclass clazz, jmethodID methodID, - va_list args) { - return functions->NewObjectV(this,clazz,methodID,args); - } - jobject NewObjectA(jclass clazz, jmethodID methodID, - const jvalue *args) { - return functions->NewObjectA(this,clazz,methodID,args); - } - - jclass GetObjectClass(jobject obj) { - return functions->GetObjectClass(this,obj); - } - jboolean IsInstanceOf(jobject obj, jclass clazz) { - return functions->IsInstanceOf(this,obj,clazz); - } - - jmethodID GetMethodID(jclass clazz, const char *name, - const char *sig) { - return functions->GetMethodID(this,clazz,name,sig); - } - - jobject CallObjectMethod(jobject obj, jmethodID methodID, ...) { - va_list args; - jobject result; - va_start(args,methodID); - result = functions->CallObjectMethodV(this,obj,methodID,args); - va_end(args); - return result; - } - jobject CallObjectMethodV(jobject obj, jmethodID methodID, - va_list args) { - return functions->CallObjectMethodV(this,obj,methodID,args); - } - jobject CallObjectMethodA(jobject obj, jmethodID methodID, - const jvalue * args) { - return functions->CallObjectMethodA(this,obj,methodID,args); - } - - jboolean CallBooleanMethod(jobject obj, - jmethodID methodID, ...) { - va_list args; - jboolean result; - va_start(args,methodID); - result = functions->CallBooleanMethodV(this,obj,methodID,args); - va_end(args); - return result; - } - jboolean CallBooleanMethodV(jobject obj, jmethodID methodID, - va_list args) { - return functions->CallBooleanMethodV(this,obj,methodID,args); - } - jboolean CallBooleanMethodA(jobject obj, jmethodID methodID, - const jvalue * args) { - return functions->CallBooleanMethodA(this,obj,methodID, args); - } - - jbyte CallByteMethod(jobject obj, jmethodID methodID, ...) { - va_list args; - jbyte result; - va_start(args,methodID); - result = functions->CallByteMethodV(this,obj,methodID,args); - va_end(args); - return result; - } - jbyte CallByteMethodV(jobject obj, jmethodID methodID, - va_list args) { - return functions->CallByteMethodV(this,obj,methodID,args); - } - jbyte CallByteMethodA(jobject obj, jmethodID methodID, - const jvalue * args) { - return functions->CallByteMethodA(this,obj,methodID,args); - } - - jchar CallCharMethod(jobject obj, jmethodID methodID, ...) { - va_list args; - jchar result; - va_start(args,methodID); - result = functions->CallCharMethodV(this,obj,methodID,args); - va_end(args); - return result; - } - jchar CallCharMethodV(jobject obj, jmethodID methodID, - va_list args) { - return functions->CallCharMethodV(this,obj,methodID,args); - } - jchar CallCharMethodA(jobject obj, jmethodID methodID, - const jvalue * args) { - return functions->CallCharMethodA(this,obj,methodID,args); - } - - jshort CallShortMethod(jobject obj, jmethodID methodID, ...) { - va_list args; - jshort result; - va_start(args,methodID); - result = functions->CallShortMethodV(this,obj,methodID,args); - va_end(args); - return result; - } - jshort CallShortMethodV(jobject obj, jmethodID methodID, - va_list args) { - return functions->CallShortMethodV(this,obj,methodID,args); - } - jshort CallShortMethodA(jobject obj, jmethodID methodID, - const jvalue * args) { - return functions->CallShortMethodA(this,obj,methodID,args); - } - - jint CallIntMethod(jobject obj, jmethodID methodID, ...) { - va_list args; - jint result; - va_start(args,methodID); - result = functions->CallIntMethodV(this,obj,methodID,args); - va_end(args); - return result; - } - jint CallIntMethodV(jobject obj, jmethodID methodID, - va_list args) { - return functions->CallIntMethodV(this,obj,methodID,args); - } - jint CallIntMethodA(jobject obj, jmethodID methodID, - const jvalue * args) { - return functions->CallIntMethodA(this,obj,methodID,args); - } - - jlong CallLongMethod(jobject obj, jmethodID methodID, ...) { - va_list args; - jlong result; - va_start(args,methodID); - result = functions->CallLongMethodV(this,obj,methodID,args); - va_end(args); - return result; - } - jlong CallLongMethodV(jobject obj, jmethodID methodID, - va_list args) { - return functions->CallLongMethodV(this,obj,methodID,args); - } - jlong CallLongMethodA(jobject obj, jmethodID methodID, - const jvalue * args) { - return functions->CallLongMethodA(this,obj,methodID,args); - } - - jfloat CallFloatMethod(jobject obj, jmethodID methodID, ...) { - va_list args; - jfloat result; - va_start(args,methodID); - result = functions->CallFloatMethodV(this,obj,methodID,args); - va_end(args); - return result; - } - jfloat CallFloatMethodV(jobject obj, jmethodID methodID, - va_list args) { - return functions->CallFloatMethodV(this,obj,methodID,args); - } - jfloat CallFloatMethodA(jobject obj, jmethodID methodID, - const jvalue * args) { - return functions->CallFloatMethodA(this,obj,methodID,args); - } - - jdouble CallDoubleMethod(jobject obj, jmethodID methodID, ...) { - va_list args; - jdouble result; - va_start(args,methodID); - result = functions->CallDoubleMethodV(this,obj,methodID,args); - va_end(args); - return result; - } - jdouble CallDoubleMethodV(jobject obj, jmethodID methodID, - va_list args) { - return functions->CallDoubleMethodV(this,obj,methodID,args); - } - jdouble CallDoubleMethodA(jobject obj, jmethodID methodID, - const jvalue * args) { - return functions->CallDoubleMethodA(this,obj,methodID,args); - } - - void CallVoidMethod(jobject obj, jmethodID methodID, ...) { - va_list args; - va_start(args,methodID); - functions->CallVoidMethodV(this,obj,methodID,args); - va_end(args); - } - void CallVoidMethodV(jobject obj, jmethodID methodID, - va_list args) { - functions->CallVoidMethodV(this,obj,methodID,args); - } - void CallVoidMethodA(jobject obj, jmethodID methodID, - const jvalue * args) { - functions->CallVoidMethodA(this,obj,methodID,args); - } - - jobject CallNonvirtualObjectMethod(jobject obj, jclass clazz, - jmethodID methodID, ...) { - va_list args; - jobject result; - va_start(args,methodID); - result = functions->CallNonvirtualObjectMethodV(this,obj,clazz, - methodID,args); - va_end(args); - return result; - } - jobject CallNonvirtualObjectMethodV(jobject obj, jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallNonvirtualObjectMethodV(this,obj,clazz, - methodID,args); - } - jobject CallNonvirtualObjectMethodA(jobject obj, jclass clazz, - jmethodID methodID, const jvalue * args) { - return functions->CallNonvirtualObjectMethodA(this,obj,clazz, - methodID,args); - } - - jboolean CallNonvirtualBooleanMethod(jobject obj, jclass clazz, - jmethodID methodID, ...) { - va_list args; - jboolean result; - va_start(args,methodID); - result = functions->CallNonvirtualBooleanMethodV(this,obj,clazz, - methodID,args); - va_end(args); - return result; - } - jboolean CallNonvirtualBooleanMethodV(jobject obj, jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallNonvirtualBooleanMethodV(this,obj,clazz, - methodID,args); - } - jboolean CallNonvirtualBooleanMethodA(jobject obj, jclass clazz, - jmethodID methodID, const jvalue * args) { - return functions->CallNonvirtualBooleanMethodA(this,obj,clazz, - methodID, args); - } - - jbyte CallNonvirtualByteMethod(jobject obj, jclass clazz, - jmethodID methodID, ...) { - va_list args; - jbyte result; - va_start(args,methodID); - result = functions->CallNonvirtualByteMethodV(this,obj,clazz, - methodID,args); - va_end(args); - return result; - } - jbyte CallNonvirtualByteMethodV(jobject obj, jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallNonvirtualByteMethodV(this,obj,clazz, - methodID,args); - } - jbyte CallNonvirtualByteMethodA(jobject obj, jclass clazz, - jmethodID methodID, const jvalue * args) { - return functions->CallNonvirtualByteMethodA(this,obj,clazz, - methodID,args); - } - - jchar CallNonvirtualCharMethod(jobject obj, jclass clazz, - jmethodID methodID, ...) { - va_list args; - jchar result; - va_start(args,methodID); - result = functions->CallNonvirtualCharMethodV(this,obj,clazz, - methodID,args); - va_end(args); - return result; - } - jchar CallNonvirtualCharMethodV(jobject obj, jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallNonvirtualCharMethodV(this,obj,clazz, - methodID,args); - } - jchar CallNonvirtualCharMethodA(jobject obj, jclass clazz, - jmethodID methodID, const jvalue * args) { - return functions->CallNonvirtualCharMethodA(this,obj,clazz, - methodID,args); - } - - jshort CallNonvirtualShortMethod(jobject obj, jclass clazz, - jmethodID methodID, ...) { - va_list args; - jshort result; - va_start(args,methodID); - result = functions->CallNonvirtualShortMethodV(this,obj,clazz, - methodID,args); - va_end(args); - return result; - } - jshort CallNonvirtualShortMethodV(jobject obj, jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallNonvirtualShortMethodV(this,obj,clazz, - methodID,args); - } - jshort CallNonvirtualShortMethodA(jobject obj, jclass clazz, - jmethodID methodID, const jvalue * args) { - return functions->CallNonvirtualShortMethodA(this,obj,clazz, - methodID,args); - } - - jint CallNonvirtualIntMethod(jobject obj, jclass clazz, - jmethodID methodID, ...) { - va_list args; - jint result; - va_start(args,methodID); - result = functions->CallNonvirtualIntMethodV(this,obj,clazz, - methodID,args); - va_end(args); - return result; - } - jint CallNonvirtualIntMethodV(jobject obj, jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallNonvirtualIntMethodV(this,obj,clazz, - methodID,args); - } - jint CallNonvirtualIntMethodA(jobject obj, jclass clazz, - jmethodID methodID, const jvalue * args) { - return functions->CallNonvirtualIntMethodA(this,obj,clazz, - methodID,args); - } - - jlong CallNonvirtualLongMethod(jobject obj, jclass clazz, - jmethodID methodID, ...) { - va_list args; - jlong result; - va_start(args,methodID); - result = functions->CallNonvirtualLongMethodV(this,obj,clazz, - methodID,args); - va_end(args); - return result; - } - jlong CallNonvirtualLongMethodV(jobject obj, jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallNonvirtualLongMethodV(this,obj,clazz, - methodID,args); - } - jlong CallNonvirtualLongMethodA(jobject obj, jclass clazz, - jmethodID methodID, const jvalue * args) { - return functions->CallNonvirtualLongMethodA(this,obj,clazz, - methodID,args); - } - - jfloat CallNonvirtualFloatMethod(jobject obj, jclass clazz, - jmethodID methodID, ...) { - va_list args; - jfloat result; - va_start(args,methodID); - result = functions->CallNonvirtualFloatMethodV(this,obj,clazz, - methodID,args); - va_end(args); - return result; - } - jfloat CallNonvirtualFloatMethodV(jobject obj, jclass clazz, - jmethodID methodID, - va_list args) { - return functions->CallNonvirtualFloatMethodV(this,obj,clazz, - methodID,args); - } - jfloat CallNonvirtualFloatMethodA(jobject obj, jclass clazz, - jmethodID methodID, - const jvalue * args) { - return functions->CallNonvirtualFloatMethodA(this,obj,clazz, - methodID,args); - } - - jdouble CallNonvirtualDoubleMethod(jobject obj, jclass clazz, - jmethodID methodID, ...) { - va_list args; - jdouble result; - va_start(args,methodID); - result = functions->CallNonvirtualDoubleMethodV(this,obj,clazz, - methodID,args); - va_end(args); - return result; - } - jdouble CallNonvirtualDoubleMethodV(jobject obj, jclass clazz, - jmethodID methodID, - va_list args) { - return functions->CallNonvirtualDoubleMethodV(this,obj,clazz, - methodID,args); - } - jdouble CallNonvirtualDoubleMethodA(jobject obj, jclass clazz, - jmethodID methodID, - const jvalue * args) { - return functions->CallNonvirtualDoubleMethodA(this,obj,clazz, - methodID,args); - } - - void CallNonvirtualVoidMethod(jobject obj, jclass clazz, - jmethodID methodID, ...) { - va_list args; - va_start(args,methodID); - functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args); - va_end(args); - } - void CallNonvirtualVoidMethodV(jobject obj, jclass clazz, - jmethodID methodID, - va_list args) { - functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args); - } - void CallNonvirtualVoidMethodA(jobject obj, jclass clazz, - jmethodID methodID, - const jvalue * args) { - functions->CallNonvirtualVoidMethodA(this,obj,clazz,methodID,args); - } - - jfieldID GetFieldID(jclass clazz, const char *name, - const char *sig) { - return functions->GetFieldID(this,clazz,name,sig); - } - - jobject GetObjectField(jobject obj, jfieldID fieldID) { - return functions->GetObjectField(this,obj,fieldID); - } - jboolean GetBooleanField(jobject obj, jfieldID fieldID) { - return functions->GetBooleanField(this,obj,fieldID); - } - jbyte GetByteField(jobject obj, jfieldID fieldID) { - return functions->GetByteField(this,obj,fieldID); - } - jchar GetCharField(jobject obj, jfieldID fieldID) { - return functions->GetCharField(this,obj,fieldID); - } - jshort GetShortField(jobject obj, jfieldID fieldID) { - return functions->GetShortField(this,obj,fieldID); - } - jint GetIntField(jobject obj, jfieldID fieldID) { - return functions->GetIntField(this,obj,fieldID); - } - jlong GetLongField(jobject obj, jfieldID fieldID) { - return functions->GetLongField(this,obj,fieldID); - } - jfloat GetFloatField(jobject obj, jfieldID fieldID) { - return functions->GetFloatField(this,obj,fieldID); - } - jdouble GetDoubleField(jobject obj, jfieldID fieldID) { - return functions->GetDoubleField(this,obj,fieldID); - } - - void SetObjectField(jobject obj, jfieldID fieldID, jobject val) { - functions->SetObjectField(this,obj,fieldID,val); - } - void SetBooleanField(jobject obj, jfieldID fieldID, - jboolean val) { - functions->SetBooleanField(this,obj,fieldID,val); - } - void SetByteField(jobject obj, jfieldID fieldID, - jbyte val) { - functions->SetByteField(this,obj,fieldID,val); - } - void SetCharField(jobject obj, jfieldID fieldID, - jchar val) { - functions->SetCharField(this,obj,fieldID,val); - } - void SetShortField(jobject obj, jfieldID fieldID, - jshort val) { - functions->SetShortField(this,obj,fieldID,val); - } - void SetIntField(jobject obj, jfieldID fieldID, - jint val) { - functions->SetIntField(this,obj,fieldID,val); - } - void SetLongField(jobject obj, jfieldID fieldID, - jlong val) { - functions->SetLongField(this,obj,fieldID,val); - } - void SetFloatField(jobject obj, jfieldID fieldID, - jfloat val) { - functions->SetFloatField(this,obj,fieldID,val); - } - void SetDoubleField(jobject obj, jfieldID fieldID, - jdouble val) { - functions->SetDoubleField(this,obj,fieldID,val); - } - - jmethodID GetStaticMethodID(jclass clazz, const char *name, - const char *sig) { - return functions->GetStaticMethodID(this,clazz,name,sig); - } - - jobject CallStaticObjectMethod(jclass clazz, jmethodID methodID, - ...) { - va_list args; - jobject result; - va_start(args,methodID); - result = functions->CallStaticObjectMethodV(this,clazz,methodID,args); - va_end(args); - return result; - } - jobject CallStaticObjectMethodV(jclass clazz, jmethodID methodID, - va_list args) { - return functions->CallStaticObjectMethodV(this,clazz,methodID,args); - } - jobject CallStaticObjectMethodA(jclass clazz, jmethodID methodID, - const jvalue *args) { - return functions->CallStaticObjectMethodA(this,clazz,methodID,args); - } - - jboolean CallStaticBooleanMethod(jclass clazz, - jmethodID methodID, ...) { - va_list args; - jboolean result; - va_start(args,methodID); - result = functions->CallStaticBooleanMethodV(this,clazz,methodID,args); - va_end(args); - return result; - } - jboolean CallStaticBooleanMethodV(jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallStaticBooleanMethodV(this,clazz,methodID,args); - } - jboolean CallStaticBooleanMethodA(jclass clazz, - jmethodID methodID, const jvalue *args) { - return functions->CallStaticBooleanMethodA(this,clazz,methodID,args); - } - - jbyte CallStaticByteMethod(jclass clazz, - jmethodID methodID, ...) { - va_list args; - jbyte result; - va_start(args,methodID); - result = functions->CallStaticByteMethodV(this,clazz,methodID,args); - va_end(args); - return result; - } - jbyte CallStaticByteMethodV(jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallStaticByteMethodV(this,clazz,methodID,args); - } - jbyte CallStaticByteMethodA(jclass clazz, - jmethodID methodID, const jvalue *args) { - return functions->CallStaticByteMethodA(this,clazz,methodID,args); - } - - jchar CallStaticCharMethod(jclass clazz, - jmethodID methodID, ...) { - va_list args; - jchar result; - va_start(args,methodID); - result = functions->CallStaticCharMethodV(this,clazz,methodID,args); - va_end(args); - return result; - } - jchar CallStaticCharMethodV(jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallStaticCharMethodV(this,clazz,methodID,args); - } - jchar CallStaticCharMethodA(jclass clazz, - jmethodID methodID, const jvalue *args) { - return functions->CallStaticCharMethodA(this,clazz,methodID,args); - } - - jshort CallStaticShortMethod(jclass clazz, - jmethodID methodID, ...) { - va_list args; - jshort result; - va_start(args,methodID); - result = functions->CallStaticShortMethodV(this,clazz,methodID,args); - va_end(args); - return result; - } - jshort CallStaticShortMethodV(jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallStaticShortMethodV(this,clazz,methodID,args); - } - jshort CallStaticShortMethodA(jclass clazz, - jmethodID methodID, const jvalue *args) { - return functions->CallStaticShortMethodA(this,clazz,methodID,args); - } - - jint CallStaticIntMethod(jclass clazz, - jmethodID methodID, ...) { - va_list args; - jint result; - va_start(args,methodID); - result = functions->CallStaticIntMethodV(this,clazz,methodID,args); - va_end(args); - return result; - } - jint CallStaticIntMethodV(jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallStaticIntMethodV(this,clazz,methodID,args); - } - jint CallStaticIntMethodA(jclass clazz, - jmethodID methodID, const jvalue *args) { - return functions->CallStaticIntMethodA(this,clazz,methodID,args); - } - - jlong CallStaticLongMethod(jclass clazz, - jmethodID methodID, ...) { - va_list args; - jlong result; - va_start(args,methodID); - result = functions->CallStaticLongMethodV(this,clazz,methodID,args); - va_end(args); - return result; - } - jlong CallStaticLongMethodV(jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallStaticLongMethodV(this,clazz,methodID,args); - } - jlong CallStaticLongMethodA(jclass clazz, - jmethodID methodID, const jvalue *args) { - return functions->CallStaticLongMethodA(this,clazz,methodID,args); - } - - jfloat CallStaticFloatMethod(jclass clazz, - jmethodID methodID, ...) { - va_list args; - jfloat result; - va_start(args,methodID); - result = functions->CallStaticFloatMethodV(this,clazz,methodID,args); - va_end(args); - return result; - } - jfloat CallStaticFloatMethodV(jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallStaticFloatMethodV(this,clazz,methodID,args); - } - jfloat CallStaticFloatMethodA(jclass clazz, - jmethodID methodID, const jvalue *args) { - return functions->CallStaticFloatMethodA(this,clazz,methodID,args); - } - - jdouble CallStaticDoubleMethod(jclass clazz, - jmethodID methodID, ...) { - va_list args; - jdouble result; - va_start(args,methodID); - result = functions->CallStaticDoubleMethodV(this,clazz,methodID,args); - va_end(args); - return result; - } - jdouble CallStaticDoubleMethodV(jclass clazz, - jmethodID methodID, va_list args) { - return functions->CallStaticDoubleMethodV(this,clazz,methodID,args); - } - jdouble CallStaticDoubleMethodA(jclass clazz, - jmethodID methodID, const jvalue *args) { - return functions->CallStaticDoubleMethodA(this,clazz,methodID,args); - } - - void CallStaticVoidMethod(jclass cls, jmethodID methodID, ...) { - va_list args; - va_start(args,methodID); - functions->CallStaticVoidMethodV(this,cls,methodID,args); - va_end(args); - } - void CallStaticVoidMethodV(jclass cls, jmethodID methodID, - va_list args) { - functions->CallStaticVoidMethodV(this,cls,methodID,args); - } - void CallStaticVoidMethodA(jclass cls, jmethodID methodID, - const jvalue * args) { - functions->CallStaticVoidMethodA(this,cls,methodID,args); - } - - jfieldID GetStaticFieldID(jclass clazz, const char *name, - const char *sig) { - return functions->GetStaticFieldID(this,clazz,name,sig); - } - jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) { - return functions->GetStaticObjectField(this,clazz,fieldID); - } - jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) { - return functions->GetStaticBooleanField(this,clazz,fieldID); - } - jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) { - return functions->GetStaticByteField(this,clazz,fieldID); - } - jchar GetStaticCharField(jclass clazz, jfieldID fieldID) { - return functions->GetStaticCharField(this,clazz,fieldID); - } - jshort GetStaticShortField(jclass clazz, jfieldID fieldID) { - return functions->GetStaticShortField(this,clazz,fieldID); - } - jint GetStaticIntField(jclass clazz, jfieldID fieldID) { - return functions->GetStaticIntField(this,clazz,fieldID); - } - jlong GetStaticLongField(jclass clazz, jfieldID fieldID) { - return functions->GetStaticLongField(this,clazz,fieldID); - } - jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) { - return functions->GetStaticFloatField(this,clazz,fieldID); - } - jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) { - return functions->GetStaticDoubleField(this,clazz,fieldID); - } - - void SetStaticObjectField(jclass clazz, jfieldID fieldID, - jobject value) { - functions->SetStaticObjectField(this,clazz,fieldID,value); - } - void SetStaticBooleanField(jclass clazz, jfieldID fieldID, - jboolean value) { - functions->SetStaticBooleanField(this,clazz,fieldID,value); - } - void SetStaticByteField(jclass clazz, jfieldID fieldID, - jbyte value) { - functions->SetStaticByteField(this,clazz,fieldID,value); - } - void SetStaticCharField(jclass clazz, jfieldID fieldID, - jchar value) { - functions->SetStaticCharField(this,clazz,fieldID,value); - } - void SetStaticShortField(jclass clazz, jfieldID fieldID, - jshort value) { - functions->SetStaticShortField(this,clazz,fieldID,value); - } - void SetStaticIntField(jclass clazz, jfieldID fieldID, - jint value) { - functions->SetStaticIntField(this,clazz,fieldID,value); - } - void SetStaticLongField(jclass clazz, jfieldID fieldID, - jlong value) { - functions->SetStaticLongField(this,clazz,fieldID,value); - } - void SetStaticFloatField(jclass clazz, jfieldID fieldID, - jfloat value) { - functions->SetStaticFloatField(this,clazz,fieldID,value); - } - void SetStaticDoubleField(jclass clazz, jfieldID fieldID, - jdouble value) { - functions->SetStaticDoubleField(this,clazz,fieldID,value); - } - - jstring NewString(const jchar *unicode, jsize len) { - return functions->NewString(this,unicode,len); - } - jsize GetStringLength(jstring str) { - return functions->GetStringLength(this,str); - } - const jchar *GetStringChars(jstring str, jboolean *isCopy) { - return functions->GetStringChars(this,str,isCopy); - } - void ReleaseStringChars(jstring str, const jchar *chars) { - functions->ReleaseStringChars(this,str,chars); - } - - jstring NewStringUTF(const char *utf) { - return functions->NewStringUTF(this,utf); - } - jsize GetStringUTFLength(jstring str) { - return functions->GetStringUTFLength(this,str); - } - const char* GetStringUTFChars(jstring str, jboolean *isCopy) { - return functions->GetStringUTFChars(this,str,isCopy); - } - void ReleaseStringUTFChars(jstring str, const char* chars) { - functions->ReleaseStringUTFChars(this,str,chars); - } - - jsize GetArrayLength(jarray array) { - return functions->GetArrayLength(this,array); - } - - jobjectArray NewObjectArray(jsize len, jclass clazz, - jobject init) { - return functions->NewObjectArray(this,len,clazz,init); - } - jobject GetObjectArrayElement(jobjectArray array, jsize index) { - return functions->GetObjectArrayElement(this,array,index); - } - void SetObjectArrayElement(jobjectArray array, jsize index, - jobject val) { - functions->SetObjectArrayElement(this,array,index,val); - } - - jbooleanArray NewBooleanArray(jsize len) { - return functions->NewBooleanArray(this,len); - } - jbyteArray NewByteArray(jsize len) { - return functions->NewByteArray(this,len); - } - jcharArray NewCharArray(jsize len) { - return functions->NewCharArray(this,len); - } - jshortArray NewShortArray(jsize len) { - return functions->NewShortArray(this,len); - } - jintArray NewIntArray(jsize len) { - return functions->NewIntArray(this,len); - } - jlongArray NewLongArray(jsize len) { - return functions->NewLongArray(this,len); - } - jfloatArray NewFloatArray(jsize len) { - return functions->NewFloatArray(this,len); - } - jdoubleArray NewDoubleArray(jsize len) { - return functions->NewDoubleArray(this,len); - } - - jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy) { - return functions->GetBooleanArrayElements(this,array,isCopy); - } - jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy) { - return functions->GetByteArrayElements(this,array,isCopy); - } - jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy) { - return functions->GetCharArrayElements(this,array,isCopy); - } - jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy) { - return functions->GetShortArrayElements(this,array,isCopy); - } - jint * GetIntArrayElements(jintArray array, jboolean *isCopy) { - return functions->GetIntArrayElements(this,array,isCopy); - } - jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy) { - return functions->GetLongArrayElements(this,array,isCopy); - } - jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy) { - return functions->GetFloatArrayElements(this,array,isCopy); - } - jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy) { - return functions->GetDoubleArrayElements(this,array,isCopy); - } - - void ReleaseBooleanArrayElements(jbooleanArray array, - jboolean *elems, - jint mode) { - functions->ReleaseBooleanArrayElements(this,array,elems,mode); - } - void ReleaseByteArrayElements(jbyteArray array, - jbyte *elems, - jint mode) { - functions->ReleaseByteArrayElements(this,array,elems,mode); - } - void ReleaseCharArrayElements(jcharArray array, - jchar *elems, - jint mode) { - functions->ReleaseCharArrayElements(this,array,elems,mode); - } - void ReleaseShortArrayElements(jshortArray array, - jshort *elems, - jint mode) { - functions->ReleaseShortArrayElements(this,array,elems,mode); - } - void ReleaseIntArrayElements(jintArray array, - jint *elems, - jint mode) { - functions->ReleaseIntArrayElements(this,array,elems,mode); - } - void ReleaseLongArrayElements(jlongArray array, - jlong *elems, - jint mode) { - functions->ReleaseLongArrayElements(this,array,elems,mode); - } - void ReleaseFloatArrayElements(jfloatArray array, - jfloat *elems, - jint mode) { - functions->ReleaseFloatArrayElements(this,array,elems,mode); - } - void ReleaseDoubleArrayElements(jdoubleArray array, - jdouble *elems, - jint mode) { - functions->ReleaseDoubleArrayElements(this,array,elems,mode); - } - - void GetBooleanArrayRegion(jbooleanArray array, - jsize start, jsize len, jboolean *buf) { - functions->GetBooleanArrayRegion(this,array,start,len,buf); - } - void GetByteArrayRegion(jbyteArray array, - jsize start, jsize len, jbyte *buf) { - functions->GetByteArrayRegion(this,array,start,len,buf); - } - void GetCharArrayRegion(jcharArray array, - jsize start, jsize len, jchar *buf) { - functions->GetCharArrayRegion(this,array,start,len,buf); - } - void GetShortArrayRegion(jshortArray array, - jsize start, jsize len, jshort *buf) { - functions->GetShortArrayRegion(this,array,start,len,buf); - } - void GetIntArrayRegion(jintArray array, - jsize start, jsize len, jint *buf) { - functions->GetIntArrayRegion(this,array,start,len,buf); - } - void GetLongArrayRegion(jlongArray array, - jsize start, jsize len, jlong *buf) { - functions->GetLongArrayRegion(this,array,start,len,buf); - } - void GetFloatArrayRegion(jfloatArray array, - jsize start, jsize len, jfloat *buf) { - functions->GetFloatArrayRegion(this,array,start,len,buf); - } - void GetDoubleArrayRegion(jdoubleArray array, - jsize start, jsize len, jdouble *buf) { - functions->GetDoubleArrayRegion(this,array,start,len,buf); - } - - void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len, - const jboolean *buf) { - functions->SetBooleanArrayRegion(this,array,start,len,buf); - } - void SetByteArrayRegion(jbyteArray array, jsize start, jsize len, - const jbyte *buf) { - functions->SetByteArrayRegion(this,array,start,len,buf); - } - void SetCharArrayRegion(jcharArray array, jsize start, jsize len, - const jchar *buf) { - functions->SetCharArrayRegion(this,array,start,len,buf); - } - void SetShortArrayRegion(jshortArray array, jsize start, jsize len, - const jshort *buf) { - functions->SetShortArrayRegion(this,array,start,len,buf); - } - void SetIntArrayRegion(jintArray array, jsize start, jsize len, - const jint *buf) { - functions->SetIntArrayRegion(this,array,start,len,buf); - } - void SetLongArrayRegion(jlongArray array, jsize start, jsize len, - const jlong *buf) { - functions->SetLongArrayRegion(this,array,start,len,buf); - } - void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, - const jfloat *buf) { - functions->SetFloatArrayRegion(this,array,start,len,buf); - } - void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, - const jdouble *buf) { - functions->SetDoubleArrayRegion(this,array,start,len,buf); - } - - jint RegisterNatives(jclass clazz, const JNINativeMethod *methods, - jint nMethods) { - return functions->RegisterNatives(this,clazz,methods,nMethods); - } - jint UnregisterNatives(jclass clazz) { - return functions->UnregisterNatives(this,clazz); - } - - jint MonitorEnter(jobject obj) { - return functions->MonitorEnter(this,obj); - } - jint MonitorExit(jobject obj) { - return functions->MonitorExit(this,obj); - } - - jint GetJavaVM(JavaVM **vm) { - return functions->GetJavaVM(this,vm); - } - - void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf) { - functions->GetStringRegion(this,str,start,len,buf); - } - void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf) { - functions->GetStringUTFRegion(this,str,start,len,buf); - } - - void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy) { - return functions->GetPrimitiveArrayCritical(this,array,isCopy); - } - void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode) { - functions->ReleasePrimitiveArrayCritical(this,array,carray,mode); - } - - const jchar * GetStringCritical(jstring string, jboolean *isCopy) { - return functions->GetStringCritical(this,string,isCopy); - } - void ReleaseStringCritical(jstring string, const jchar *cstring) { - functions->ReleaseStringCritical(this,string,cstring); - } - - jweak NewWeakGlobalRef(jobject obj) { - return functions->NewWeakGlobalRef(this,obj); - } - void DeleteWeakGlobalRef(jweak ref) { - functions->DeleteWeakGlobalRef(this,ref); - } - - jboolean ExceptionCheck() { - return functions->ExceptionCheck(this); - } - - jobject NewDirectByteBuffer(void* address, jlong capacity) { - return functions->NewDirectByteBuffer(this, address, capacity); - } - void* GetDirectBufferAddress(jobject buf) { - return functions->GetDirectBufferAddress(this, buf); - } - jlong GetDirectBufferCapacity(jobject buf) { - return functions->GetDirectBufferCapacity(this, buf); - } - jobjectRefType GetObjectRefType(jobject obj) { - return functions->GetObjectRefType(this, obj); - } - -#endif /* __cplusplus */ -}; - -typedef struct JavaVMOption { - char *optionString; - void *extraInfo; -} JavaVMOption; - -typedef struct JavaVMInitArgs { - jint version; - - jint nOptions; - JavaVMOption *options; - jboolean ignoreUnrecognized; -} JavaVMInitArgs; - -typedef struct JavaVMAttachArgs { - jint version; - - char *name; - jobject group; -} JavaVMAttachArgs; - -/* These will be VM-specific. */ - -#define JDK1_2 -#define JDK1_4 - -/* End VM-specific. */ - -struct JNIInvokeInterface_ { - void *reserved0; - void *reserved1; - void *reserved2; - - jint (JNICALL *DestroyJavaVM)(JavaVM *vm); - - jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args); - - jint (JNICALL *DetachCurrentThread)(JavaVM *vm); - - jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version); - - jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args); -}; - -struct JavaVM_ { - const struct JNIInvokeInterface_ *functions; -#ifdef __cplusplus - - jint DestroyJavaVM() { - return functions->DestroyJavaVM(this); - } - jint AttachCurrentThread(void **penv, void *args) { - return functions->AttachCurrentThread(this, penv, args); - } - jint DetachCurrentThread() { - return functions->DetachCurrentThread(this); - } - - jint GetEnv(void **penv, jint version) { - return functions->GetEnv(this, penv, version); - } - jint AttachCurrentThreadAsDaemon(void **penv, void *args) { - return functions->AttachCurrentThreadAsDaemon(this, penv, args); - } -#endif -}; - -#ifdef _JNI_IMPLEMENTATION_ -#define _JNI_IMPORT_OR_EXPORT_ JNIEXPORT -#else -#define _JNI_IMPORT_OR_EXPORT_ JNIIMPORT -#endif -_JNI_IMPORT_OR_EXPORT_ jint JNICALL -JNI_GetDefaultJavaVMInitArgs(void *args); - -_JNI_IMPORT_OR_EXPORT_ jint JNICALL -JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args); - -_JNI_IMPORT_OR_EXPORT_ jint JNICALL -JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *); - -/* Defined by native libraries. */ -JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM *vm, void *reserved); - -JNIEXPORT void JNICALL -JNI_OnUnload(JavaVM *vm, void *reserved); - -#define JNI_VERSION_1_1 0x00010001 -#define JNI_VERSION_1_2 0x00010002 -#define JNI_VERSION_1_4 0x00010004 -#define JNI_VERSION_1_6 0x00010006 - -#ifdef __cplusplus -} /* extern "C" */ -#endif /* __cplusplus */ - -#endif /* !_JAVASOFT_JNI_H_ */ - - - diff --git a/native/IdeaWin32/jni_md.h b/native/IdeaWin32/jni_md.h deleted file mode 100644 index 9f0cfa463837..000000000000 --- a/native/IdeaWin32/jni_md.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * @(#)jni_md.h 1.15 05/11/17 - * - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -#ifndef _JAVASOFT_JNI_MD_H_ -#define _JAVASOFT_JNI_MD_H_ - -#define JNIEXPORT __declspec(dllexport) -#define JNIIMPORT __declspec(dllimport) -#define JNICALL __stdcall - -typedef long jint; -typedef __int64 jlong; -typedef signed char jbyte; - -#endif /* !_JAVASOFT_JNI_MD_H_ */ diff --git a/native/IdeaWin32/jni_util.h b/native/IdeaWin32/jni_util.h deleted file mode 100644 index a1ae06ad4447..000000000000 --- a/native/IdeaWin32/jni_util.h +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright 1997-2004 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -#ifndef JNI_UTIL_H -#define JNI_UTIL_H - -#include "jni.h" -#include "jlong.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * This file contains utility functions that can be implemented in pure JNI. - * - * Caution: Callers of functions declared in this file should be - * particularly aware of the fact that these functions are convenience - * functions, and as such are often compound operations, each one of - * which may throw an exception. Therefore, the functions this file - * will often return silently if an exception has occured, and callers - * must check for exception themselves. - */ - -/* Throw a Java exception by name. Similar to SignalError. */ -JNIEXPORT void JNICALL -JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg); - -/* Throw common exceptions */ -JNIEXPORT void JNICALL -JNU_ThrowNullPointerException(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowArrayIndexOutOfBoundsException(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowOutOfMemoryError(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowIllegalArgumentException(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowIllegalAccessError(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowIllegalAccessException(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowInternalError(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowIOException(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowNoSuchFieldException(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowNoSuchMethodException(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowClassNotFoundException(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowNumberFormatException(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowNoSuchFieldError(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowNoSuchMethodError(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowStringIndexOutOfBoundsException(JNIEnv *env, const char *msg); - -JNIEXPORT void JNICALL -JNU_ThrowInstantiationException(JNIEnv *env, const char *msg); - -/* Throw an exception by name, using the string returned by - * JVM_LastErrorString for the detail string. If the last-error - * string is NULL, use the given default detail string. - */ -JNIEXPORT void JNICALL -JNU_ThrowByNameWithLastError(JNIEnv *env, const char *name, - const char *defaultMessage); - -/* Throw an IOException, using the last-error string for the detail - * string. If the last-error string is NULL, use the given default - * detail string. - */ -JNIEXPORT void JNICALL -JNU_ThrowIOExceptionWithLastError(JNIEnv *env, const char *defaultDetail); - -/* Convert between Java strings and i18n C strings */ -JNIEXPORT jstring -NewStringPlatform(JNIEnv *env, const char *str); - -JNIEXPORT const char * -GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy); - -JNIEXPORT jstring JNICALL -JNU_NewStringPlatform(JNIEnv *env, const char *str); - -JNIEXPORT const char * JNICALL -JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy); - -JNIEXPORT void JNICALL -JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str); - -/* Class constants */ -JNIEXPORT jclass JNICALL -JNU_ClassString(JNIEnv *env); - -JNIEXPORT jclass JNICALL -JNU_ClassClass(JNIEnv *env); - -JNIEXPORT jclass JNICALL -JNU_ClassObject(JNIEnv *env); - -JNIEXPORT jclass JNICALL -JNU_ClassThrowable(JNIEnv *env); - -/* Copy count number of arguments from src to dst. Array bounds - * and ArrayStoreException are checked. - */ -JNIEXPORT jint JNICALL -JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src, - jint count); - -/* Invoke a object-returning static method, based on class name, - * method name, and signature string. - * - * The caller should check for exceptions by setting hasException - * argument. If the caller is not interested in whether an exception - * has occurred, pass in NULL. - */ -JNIEXPORT jvalue JNICALL -JNU_CallStaticMethodByName(JNIEnv *env, - jboolean *hasException, - const char *class_name, - const char *name, - const char *signature, - ...); - -/* Invoke an instance method by name. - */ -JNIEXPORT jvalue JNICALL -JNU_CallMethodByName(JNIEnv *env, - jboolean *hasException, - jobject obj, - const char *name, - const char *signature, - ...); - -JNIEXPORT jvalue JNICALL -JNU_CallMethodByNameV(JNIEnv *env, - jboolean *hasException, - jobject obj, - const char *name, - const char *signature, - va_list args); - -/* Construct a new object of class, specifying the class by name, - * and specififying which constructor to run and what arguments to - * pass to it. - * - * The method will return an initialized instance if successful. - * It will return NULL if an error has occured (for example if - * it ran out of memory) and the appropriate Java exception will - * have been thrown. - */ -JNIEXPORT jobject JNICALL -JNU_NewObjectByName(JNIEnv *env, const char *class_name, - const char *constructor_sig, ...); - -/* returns: - * 0: object is not an instance of the class named by classname. - * 1: object is an instance of the class named by classname. - * -1: the class named by classname cannot be found. An exception - * has been thrown. - */ -JNIEXPORT jint JNICALL -JNU_IsInstanceOfByName(JNIEnv *env, jobject object, char *classname); - - -/* Get or set class and instance fields. - * Note that set functions take a variable number of arguments, - * but only one argument of the appropriate type can be passed. - * For example, to set an integer field i to 100: - * - * JNU_SetFieldByName(env, &exc, obj, "i", "I", 100); - * - * To set a float field f to 12.3: - * - * JNU_SetFieldByName(env, &exc, obj, "f", "F", 12.3); - * - * The caller should check for exceptions by setting hasException - * argument. If the caller is not interested in whether an exception - * has occurred, pass in NULL. - */ -JNIEXPORT jvalue JNICALL -JNU_GetFieldByName(JNIEnv *env, - jboolean *hasException, - jobject obj, - const char *name, - const char *sig); -JNIEXPORT void JNICALL -JNU_SetFieldByName(JNIEnv *env, - jboolean *hasException, - jobject obj, - const char *name, - const char *sig, - ...); - -JNIEXPORT jvalue JNICALL -JNU_GetStaticFieldByName(JNIEnv *env, - jboolean *hasException, - const char *classname, - const char *name, - const char *sig); -JNIEXPORT void JNICALL -JNU_SetStaticFieldByName(JNIEnv *env, - jboolean *hasException, - const char *classname, - const char *name, - const char *sig, - ...); - - -/* - * Calls the .equals method. - */ -JNIEXPORT jboolean JNICALL -JNU_Equals(JNIEnv *env, jobject object1, jobject object2); - - -/************************************************************************ - * Thread calls - * - * Convenience thread-related calls on the java.lang.Object class. - */ - -JNIEXPORT void JNICALL -JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout); - -JNIEXPORT void JNICALL -JNU_Notify(JNIEnv *env, jobject object); - -JNIEXPORT void JNICALL -JNU_NotifyAll(JNIEnv *env, jobject object); - - -/************************************************************************ - * Miscellaneous utilities used by the class libraries - */ - -#define IS_NULL(obj) ((obj) == NULL) -#define JNU_IsNull(env,obj) ((obj) == NULL) - - -/************************************************************************ - * Debugging utilities - */ - -JNIEXPORT void JNICALL -JNU_PrintString(JNIEnv *env, char *hdr, jstring string); - -JNIEXPORT void JNICALL -JNU_PrintClass(JNIEnv *env, char *hdr, jobject object); - -JNIEXPORT jstring JNICALL -JNU_ToString(JNIEnv *env, jobject object); - -/* - * Package shorthand for use by native libraries - */ -#define JNU_JAVAPKG "java/lang/" -#define JNU_JAVAIOPKG "java/io/" -#define JNU_JAVANETPKG "java/net/" - -/* - * Check if the current thread is attached to the VM, and returns - * the JNIEnv of the specified version if the thread is attached. - * - * If the current thread is not attached, this function returns 0. - * - * If the current thread is attached, this function returns the - * JNI environment, or returns (void *)JNI_ERR if the specified - * version is not supported. - */ -JNIEXPORT void * JNICALL -JNU_GetEnv(JavaVM *vm, jint version); - -/* - * Warning free access to pointers stored in Java long fields. - */ -#define JNU_GetLongFieldAsPtr(env,obj,id) \ - (jlong_to_ptr((*(env))->GetLongField((env),(obj),(id)))) -#define JNU_SetLongFieldFromPtr(env,obj,id,val) \ - (*(env))->SetLongField((env),(obj),(id),ptr_to_jlong(val)) - -/* - * Internal use only. - */ -enum { - NO_ENCODING_YET = 0, /* "sun.jnu.encoding" not yet set */ - NO_FAST_ENCODING, /* Platform encoding is not fast */ - FAST_8859_1, /* ISO-8859-1 */ - FAST_CP1252, /* MS-DOS Cp1252 */ - FAST_646_US /* US-ASCII : ISO646-US */ -}; - -jstring nativeNewStringPlatform(JNIEnv *env, const char *str); - -char* nativeGetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy); - -int getFastEncoding(); - -void initializeEncoding(); - - -#ifdef __cplusplus -} /* extern "C" */ -#endif /* __cplusplus */ - -#endif /* JNI_UTIL_H */ diff --git a/native/IdeaWin32/readme.txt b/native/IdeaWin32/readme.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/native/IdeaWin32/stdafx.cpp b/native/IdeaWin32/stdafx.cpp deleted file mode 100644 index 9a99d3a2049d..000000000000 --- a/native/IdeaWin32/stdafx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// IdeaWin32.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/native/IdeaWin32/stdafx.h b/native/IdeaWin32/stdafx.h deleted file mode 100644 index 5cb1cb9f9e68..000000000000 --- a/native/IdeaWin32/stdafx.h +++ /dev/null @@ -1,30 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - -// Modify the following defines if you have to target a platform prior to the ones specified below. -// Refer to MSDN for the latest info on corresponding values for different platforms. -#ifndef WINVER // Allow use of features specific to Windows XP or later. -#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. -#endif - -#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. -#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. -#endif - -#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. -#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. -#endif - -#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. -#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE. -#endif - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files: -#include - -#include diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/IdeaWin32.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/IdeaWin32.java deleted file mode 100644 index 3e5e0cf6048a..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/IdeaWin32.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2000-2011 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.vfs.impl.win32; - -/** - * @author Dmitry Avdeev - */ -public class IdeaWin32 { - public native FileInfo getInfo(String path); - - public native FileInfo[] listChildren(String path); -} diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java index 6440e70f5565..09c21e205a1c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java @@ -16,6 +16,8 @@ package com.intellij.openapi.vfs.impl.win32; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.win32.FileInfo; +import com.intellij.openapi.util.io.win32.IdeaWin32; import com.intellij.util.ArrayUtil; import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; @@ -29,14 +31,13 @@ import java.util.Map; * @author Dmitry Avdeev */ public class Win32Kernel { - public static final int FILE_ATTRIBUTE_READONLY = 0x0001; - public static final int FILE_ATTRIBUTE_HIDDEN = 0x0002; - public static final int FILE_ATTRIBUTE_DIRECTORY = 0x0010; - public static final int FILE_ATTRIBUTE_DEVICE = 0x0040; - public static final int FILE_ATTRIBUTE_REPARSE_POINT = 0x0400; - - private final IdeaWin32 myKernel = new IdeaWin32(); + public static final int FILE_ATTRIBUTE_READONLY = FileInfo.FILE_ATTRIBUTE_READONLY; + public static final int FILE_ATTRIBUTE_HIDDEN = FileInfo.FILE_ATTRIBUTE_HIDDEN; + public static final int FILE_ATTRIBUTE_DIRECTORY = FileInfo.FILE_ATTRIBUTE_DIRECTORY; + public static final int FILE_ATTRIBUTE_DEVICE = FileInfo.FILE_ATTRIBUTE_DEVICE; + public static final int FILE_ATTRIBUTE_REPARSE_POINT = FileInfo.FILE_ATTRIBUTE_REPARSE_POINT; + private final IdeaWin32 myKernel = IdeaWin32.getInstance(); private final Map myCache = new THashMap(); void clearCache() { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java index 0cec37f27b18..113926d3e8bd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java @@ -15,11 +15,11 @@ */ package com.intellij.openapi.vfs.impl.win32; -import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileAttributes; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.win32.FileInfo; +import com.intellij.openapi.util.io.win32.IdeaWin32; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.impl.local.LocalFileSystemBase; import com.intellij.util.ArrayUtil; @@ -39,40 +39,8 @@ import static com.intellij.util.BitUtil.isSet; public class Win32LocalFileSystem extends LocalFileSystemBase { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.win32.Win32LocalFileSystem"); - private static final boolean ourIsAvailable; - - static { - boolean available = false; - if (SystemInfo.isWindows) { - String libName = SystemInfo.is64Bit ? "IdeaWin64" : "IdeaWin32"; - try { - System.load(PathManager.getHomePath() + "/community/bin/win/" + libName + ".dll"); - available = true; - } - catch (Throwable t0) { - try { - System.load(PathManager.getHomePath() + "/bin/win/" + libName + ".dll"); - available = true; - } - catch (Throwable t1) { - try { - System.loadLibrary(libName); - available = true; - } - catch (Throwable t2) { - LOG.warn("Failed to load native filesystem for Windows", t2); - } - } - } - } - ourIsAvailable = available; - if (available) { - LOG.info("Native filesystem for Windows is operational"); - } - } - public static boolean isAvailable() { - return ourIsAvailable; + return IdeaWin32.isAvailable(); } private static final ThreadLocal THREAD_LOCAL = new ThreadLocal() { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/FileInfo.java b/platform/util/src/com/intellij/openapi/util/io/win32/FileInfo.java similarity index 61% rename from platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/FileInfo.java rename to platform/util/src/com/intellij/openapi/util/io/win32/FileInfo.java index 52cdc416ac7f..88693715ac78 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/FileInfo.java +++ b/platform/util/src/com/intellij/openapi/util/io/win32/FileInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -13,26 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.openapi.vfs.impl.win32; +package com.intellij.openapi.util.io.win32; import org.intellij.lang.annotations.MagicConstant; /** + * Do not use this class directly. + * * @author Dmitry Avdeev + * @since 12.0 */ public class FileInfo { - - static { - initIDs(); - } - - private static native void initIDs(); + public static final int FILE_ATTRIBUTE_READONLY = 0x0001; + public static final int FILE_ATTRIBUTE_HIDDEN = 0x0002; + public static final int FILE_ATTRIBUTE_DIRECTORY = 0x0010; + public static final int FILE_ATTRIBUTE_DEVICE = 0x0040; + public static final int FILE_ATTRIBUTE_REPARSE_POINT = 0x0400; // is set only for symlinks public String name; - - @MagicConstant(flagsFromClass = Win32Kernel.class) + @MagicConstant(flagsFromClass = FileInfo.class) public int attributes; - public long timestamp; public long length; diff --git a/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java b/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java new file mode 100644 index 000000000000..2e81a993d365 --- /dev/null +++ b/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java @@ -0,0 +1,95 @@ +/* + * 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.openapi.util.io.win32; + +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.SystemInfo; +import org.jetbrains.annotations.NotNull; + +/** + * Do not use this class directly. + * + * @author Dmitry Avdeev + * @since 12.0 + */ +public class IdeaWin32 { + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.io.win32.Win32LocalFileSystem"); + + private static final IdeaWin32 ourInstance; + + static { + boolean available = false; + if (SystemInfo.isWindows) { + String libName = SystemInfo.is64Bit ? "IdeaWin64" : "IdeaWin32"; + try { + System.load(PathManager.getHomePath() + "/community/bin/win/" + libName + ".dll"); + available = true; + } + catch (Throwable t0) { + try { + System.load(PathManager.getHomePath() + "/bin/win/" + libName + ".dll"); + available = true; + } + catch (Throwable t1) { + try { + System.loadLibrary(libName); + available = true; + } + catch (Throwable t2) { + LOG.warn("Failed to load native filesystem for Windows", t2); + } + } + } + } + + IdeaWin32 instance = null; + if (available) { + try { + instance = new IdeaWin32(); + LOG.info("Native filesystem for Windows is operational"); + } + catch (Throwable t) { + LOG.warn("Failed to initialize native filesystem for Windows", t); + } + } + ourInstance = instance; + } + + public static boolean isAvailable() { + return ourInstance != null; + } + + @NotNull + public static IdeaWin32 getInstance() { + if (!isAvailable()) { + throw new IllegalStateException("Native filesystem for Windows is not loaded"); + } + return ourInstance; + } + + private IdeaWin32() { + initIDs(); + } + + private static native void initIDs(); + + public native FileInfo getInfo(String path); + + public native String resolveSymLink(String path); + + public native FileInfo[] listChildren(String path); +} From 05f7376c64dbe40b61b3c9ac6f067ebabfea67e1 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 23 Jul 2012 17:41:04 +0200 Subject: [PATCH 21/35] Fix test expectations --- .../openapi/util/io/FileAttributesNio2ReadingTest.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesNio2ReadingTest.java b/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesNio2ReadingTest.java index 68f2e88ae01e..d1d2c395ef53 100644 --- a/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesNio2ReadingTest.java +++ b/platform/util/testSrc/com/intellij/openapi/util/io/FileAttributesNio2ReadingTest.java @@ -17,7 +17,6 @@ package com.intellij.openapi.util.io; import com.intellij.openapi.util.SystemInfo; import org.junit.AfterClass; -import org.junit.Before; import org.junit.BeforeClass; import static org.junit.Assert.assertEquals; @@ -26,6 +25,8 @@ import static org.junit.Assume.assumeTrue; public class FileAttributesNio2ReadingTest extends FileAttributesReadingTest { @BeforeClass public static void setUpClass() throws Exception { + assumeTrue(SystemInfo.isJavaVersionAtLeast("1.7")); + System.setProperty(FileSystemUtil.FORCE_USE_NIO2_KEY, "true"); FileSystemUtil.resetMediator(); assertEquals("NIO2", FileSystemUtil.getMediatorName()); @@ -36,11 +37,4 @@ public class FileAttributesNio2ReadingTest extends FileAttributesReadingTest { System.setProperty(FileSystemUtil.FORCE_USE_NIO2_KEY, ""); FileSystemUtil.resetMediator(); } - - @Override - @Before - public void setUp() throws Exception { - assumeTrue(SystemInfo.isJavaVersionAtLeast("1.7")); - super.setUp(); - } } From 610c108de50df586afbe23751f3ad2d7a404db15 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 23 Jul 2012 17:46:08 +0200 Subject: [PATCH 22/35] Read file attributes through IdeaWin32 --- .../com/intellij/openapi/util/SystemInfo.java | 2 +- .../openapi/util/io/FileSystemUtil.java | 52 ++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/util/SystemInfo.java b/platform/util/src/com/intellij/openapi/util/SystemInfo.java index b2e0e9fb2c2e..2f86c51de7d8 100644 --- a/platform/util/src/com/intellij/openapi/util/SystemInfo.java +++ b/platform/util/src/com/intellij/openapi/util/SystemInfo.java @@ -56,7 +56,7 @@ public class SystemInfo extends SystemInfoRt { public static final boolean isFileSystemCaseSensitive = SystemInfoRt.isFileSystemCaseSensitive; public static final boolean areSymLinksSupported = isUnix || - isWindows && OS_VERSION.compareTo("6.0") >= 0 && isJavaVersionAtLeast("1.7"); + isWindows && OS_VERSION.compareTo("6.0") >= 0; public static final boolean is32Bit = ARCH_DATA_MODEL == null || ARCH_DATA_MODEL.equals("32"); public static final boolean is64Bit = !is32Bit; diff --git a/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java index e38a99e630a1..abf9063d28ad 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java @@ -17,6 +17,8 @@ package com.intellij.openapi.util.io; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.win32.FileInfo; +import com.intellij.openapi.util.io.win32.IdeaWin32; import com.intellij.util.ArrayUtil; import com.intellij.util.SystemProperties; import com.sun.jna.Library; @@ -65,7 +67,17 @@ public class FileSystemUtil { final String quickTestPath = SystemInfo.isWindows ? "C:\\" : "/"; if (!forceUseNio2) { - if (SystemInfo.isLinux || SystemInfo.isMac || SystemInfo.isSolaris || SystemInfo.isFreeBSD) { + if (SystemInfo.isWindows) { + try { + final Mediator mediator = new IdeaWin32MediatorImpl(); + mediator.getAttributes(quickTestPath); + return mediator; + } + catch (Throwable t) { + LOG.warn(t); + } + } + else if (SystemInfo.isLinux || SystemInfo.isMac || SystemInfo.isSolaris || SystemInfo.isFreeBSD) { try { final Mediator mediator = new JnaUnixMediatorImpl(); mediator.getAttributes(quickTestPath); @@ -330,6 +342,44 @@ public class FileSystemUtil { } + private static class IdeaWin32MediatorImpl implements Mediator { + private static final String PATH_PREFIX = "\\\\?\\"; + private static final int PREFIX_SIZE = PATH_PREFIX.length(); + + private IdeaWin32 myInstance = IdeaWin32.getInstance(); + + @Override + public FileAttributes getAttributes(@NotNull final String path) throws Exception { + final FileInfo fileInfo = myInstance.getInfo(path); + if (fileInfo == null) return null; + + final boolean isDirectory = isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_DIRECTORY); + final boolean isSpecial = isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_DEVICE); + final boolean isSymlink = isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_REPARSE_POINT); + final boolean isHidden = isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_HIDDEN); + final boolean isWritable = !isSet(fileInfo.attributes, FileInfo.FILE_ATTRIBUTE_READONLY); + final long timestamp = fileInfo.timestamp / 10000 - 11644473600000l; + return new FileAttributes(isDirectory, isSpecial, isSymlink, isHidden, fileInfo.length, timestamp, isWritable); + } + + @Override + public String resolveSymLink(@NotNull final String path) throws Exception { + final String result = myInstance.resolveSymLink(path); + return result != null && result.startsWith(PATH_PREFIX) ? result.substring(PREFIX_SIZE) : result; + } + + @Override + public void setPermissions(@NotNull final String path, final int permissions) throws Exception { + } + + @NotNull + @Override + public String getName() { + return "IdeaWin32"; + } + } + + // thanks to SVNKit for the idea private static class JnaUnixMediatorImpl implements Mediator { @SuppressWarnings("OctalInteger") From eda444e8e5f46f75663e8fe439754f3ae39d8fe7 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 23 Jul 2012 18:22:48 +0200 Subject: [PATCH 23/35] Future-proof Nautilus version comparison --- .../src/com/intellij/ide/actions/ShowFilePathAction.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java index 7d29e02c02a6..a1c851382371 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java @@ -38,6 +38,7 @@ import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.awt.RelativePoint; @@ -52,6 +53,8 @@ import java.awt.event.MouseEvent; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class ShowFilePathAction extends AnAction { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.ShowFilePathAction"); @@ -61,7 +64,9 @@ public class ShowFilePathAction extends AnAction { @Override protected Boolean compute() { final String version = ExecUtil.execAndReadLine("nautilus", "--version"); - return version != null && version.startsWith("GNOME nautilus 3"); + if (version == null) return false; + final Matcher m = Pattern.compile("GNOME nautilus ([0-9.]+)").matcher(version); + return m.find() && StringUtil.compareVersionNumbers(m.group(1), "3") >= 0; } }; From c3fd99f063298d7467e3249e816ddbace6d5dc85 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 24 Jul 2012 11:33:00 +0200 Subject: [PATCH 24/35] Fix update scripts for Macs --- build/update.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/update.sh b/build/update.sh index cc2471313c2e..61f009e28087 100755 --- a/build/update.sh +++ b/build/update.sh @@ -9,7 +9,7 @@ # 3. DEV_IDEA_HOME points to the directory of the project you built at step 1 # 4. You quit IntelliJ IDEA -if [ ! -f "$WORK_IDEA_HOME/bin/idea.sh" ]; then +if [ ! -f "$WORK_IDEA_HOME/bin/inspect.sh" ]; then echo "WORK_IDEA_HOME must be defined and point to build you're updating." exit fi From 7b78f7b1101eb14df88bcd7d3bdeb7a04c6a57de Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 24 Jul 2012 11:36:51 +0200 Subject: [PATCH 25/35] Fix test expectations --- .../util/testSrc/com/intellij/openapi/util/io/IoTestUtil.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/util/testSrc/com/intellij/openapi/util/io/IoTestUtil.java b/platform/util/testSrc/com/intellij/openapi/util/io/IoTestUtil.java index da880c0560f3..c763ffa657db 100644 --- a/platform/util/testSrc/com/intellij/openapi/util/io/IoTestUtil.java +++ b/platform/util/testSrc/com/intellij/openapi/util/io/IoTestUtil.java @@ -47,7 +47,8 @@ public class IoTestUtil { assertEquals(commandLine.command().toString(), 0, res); final File targetFile = new File(target); - assertEquals("target=" + target + ", link=" + linkFile, targetFile.exists(), linkFile.exists()); + final boolean shouldExist = targetFile.exists() || SystemInfo.isWindows && SystemInfo.JAVA_VERSION.startsWith("1.6"); + assertEquals("target=" + target + ", link=" + linkFile, shouldExist, linkFile.exists()); return linkFile; } } From 6880a08a7cbc2d9aec2393d6003e5ec080a81424 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 24 Jul 2012 11:58:04 +0200 Subject: [PATCH 26/35] analyze cyclic dependencies: dialog tweaks (IDEA-88935;IDEA-88936) --- .../actions/CyclicDependenciesAction.java | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/java/java-impl/src/com/intellij/cyclicDependencies/actions/CyclicDependenciesAction.java b/java/java-impl/src/com/intellij/cyclicDependencies/actions/CyclicDependenciesAction.java index cd222246348c..77c39c581c2f 100644 --- a/java/java-impl/src/com/intellij/cyclicDependencies/actions/CyclicDependenciesAction.java +++ b/java/java-impl/src/com/intellij/cyclicDependencies/actions/CyclicDependenciesAction.java @@ -21,7 +21,8 @@ import com.intellij.analysis.JavaAnalysisScope; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.psi.*; @@ -49,7 +50,8 @@ public class CyclicDependenciesAction extends AnAction{ public void update(AnActionEvent event) { Presentation presentation = event.getPresentation(); presentation.setEnabled( - getInspectionScope(event.getDataContext()) != null || event.getData(LangDataKeys.PSI_FILE) != null); + getInspectionScope(event.getDataContext()) != null || + event.getData(PlatformDataKeys.PROJECT) != null); } public void actionPerformed(AnActionEvent e) { @@ -57,15 +59,11 @@ public class CyclicDependenciesAction extends AnAction{ final Project project = PlatformDataKeys.PROJECT.getData(dataContext); final Module module = LangDataKeys.MODULE.getData(dataContext); if (project != null) { - PsiFile psiFile = LangDataKeys.PSI_FILE.getData(dataContext); - if (psiFile != null && !(psiFile instanceof PsiJavaFile)) { - return; - } AnalysisScope scope = getInspectionScope(dataContext); if (scope == null || scope.getScopeType() != AnalysisScope.MODULES){ ProjectModuleOrPackageDialog dlg = null; if (module != null) { - dlg = new ProjectModuleOrPackageDialog(ModuleUtil.getModuleNameInReadAction(module), scope); + dlg = new ProjectModuleOrPackageDialog(ModuleManager.getInstance(project).getModules().length == 1 ? null : ModuleUtilCore.getModuleNameInReadAction(module), scope); dlg.show(); if (!dlg.isOK()) return; } @@ -104,12 +102,12 @@ public class CyclicDependenciesAction extends AnAction{ //Possible scopes: package, project, module. Project projectContext = PlatformDataKeys.PROJECT_CONTEXT.getData(dataContext); if (projectContext != null) { - return new AnalysisScope(projectContext); + return null; } Module moduleContext = LangDataKeys.MODULE_CONTEXT.getData(dataContext); if (moduleContext != null) { - return new AnalysisScope(moduleContext); + return null; } Module [] modulesArray = LangDataKeys.MODULE_CONTEXT_ARRAY.getData(dataContext); @@ -128,12 +126,9 @@ public class CyclicDependenciesAction extends AnAction{ PsiDirectory[] dirs = pack.getDirectories(GlobalSearchScope.projectScope(pack.getProject())); if (dirs.length == 0) return null; return new JavaAnalysisScope(pack, LangDataKeys.MODULE.getData(dataContext)); - } else if (psiTarget != null){ - return null; } - - return getProjectScope(dataContext); + return null; } @Nullable @@ -173,7 +168,6 @@ public class CyclicDependenciesAction extends AnAction{ init(); setTitle(AnalysisScopeBundle.message("cyclic.dependencies.scope.dialog.title", myTitle)); setHorizontalStretch(1.75f); - myModuleButton.setSelected(true); } public boolean isIncludeTestSources() { @@ -190,11 +184,19 @@ public class CyclicDependenciesAction extends AnAction{ myModuleButton.setText(AnalysisScopeBundle.message("cyclic.dependencies.scope.dialog.module.button", myAnalysisVerb, myModuleName)); group.add(myModuleButton); } + myModuleButton.setVisible(myModuleName != null); mySelectedScopeButton.setVisible(mySelectedScope != null); if (mySelectedScope != null) { mySelectedScopeButton.setText(mySelectedScope.getShortenName()); group.add(mySelectedScopeButton); } + if (mySelectedScope != null) { + mySelectedScopeButton.setSelected(true); + } else if (myModuleName != null) { + myModuleButton.setSelected(true); + } else { + myProjectButton.setSelected(true); + } return myWholePanel; } From 1c1e1522b3ec0b576c4b7098a73eda24e498c020 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 24 Jul 2012 14:02:06 +0400 Subject: [PATCH 27/35] EA-37337 - assert: FileManagerImpl.findFile --- .../org/jetbrains/idea/maven/navigator/MavenNavigationUtil.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenNavigationUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenNavigationUtil.java index c78438e07754..0d665347ae29 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenNavigationUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenNavigationUtil.java @@ -72,6 +72,8 @@ public class MavenNavigationUtil { public static Navigatable createNavigatableForDependency(final Project project, final VirtualFile file, final MavenArtifact artifact) { return new NavigatableAdapter() { public void navigate(boolean requestFocus) { + if (!file.isValid()) return; + final PsiFile pom = PsiManager.getInstance(project).findFile(file); if (pom instanceof XmlFile) { final XmlTag id = findDependency((XmlFile)pom, artifact.getArtifactId()); From 05c56bd35f33498077535b960a45bb1ea53fc4c0 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 24 Jul 2012 14:09:00 +0400 Subject: [PATCH 28/35] Add additional diagnostic --- .../idea/maven/importing/MavenModuleNameMapper.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java index c125e65db08e..c9736b2926d0 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java @@ -102,7 +102,10 @@ public class MavenModuleNameMapper { mavenProjectToModuleName.put(each.project, each.getResultName()); } - assert new HashSet(mavenProjectToModuleName.values()).size() == mavenProjectToModuleName.size(); + assert new HashSet(mavenProjectToModuleName.values()).size() == mavenProjectToModuleName.size() : mavenProjectToModuleName + .values() + + "\n||\n" + + mavenProjectToModuleName; } public static class NameItem implements Comparable { From 97ef06692d7fd6193b380b74eec5026f40dd3fe8 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 24 Jul 2012 14:15:57 +0400 Subject: [PATCH 29/35] Add additional diagnostic --- .../idea/maven/importing/MavenModuleNameMapper.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java index c9736b2926d0..877fd771e545 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java @@ -102,10 +102,7 @@ public class MavenModuleNameMapper { mavenProjectToModuleName.put(each.project, each.getResultName()); } - assert new HashSet(mavenProjectToModuleName.values()).size() == mavenProjectToModuleName.size() : mavenProjectToModuleName - .values() + - "\n||\n" + - mavenProjectToModuleName; + assert new HashSet(mavenProjectToModuleName.values()).size() == mavenProjectToModuleName.size() : mavenProjectToModuleName; } public static class NameItem implements Comparable { From 8927880846cdc84dc61453b42b771420c1a9e034 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 24 Jul 2012 11:53:16 +0200 Subject: [PATCH 30/35] Cleanup --- .../vfs/impl/jar/JarFileSystemImpl.java | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java index 1ab273622a04..743dbcb93d69 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java @@ -20,7 +20,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.ApplicationComponent; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileAttributes; import com.intellij.openapi.util.io.FileUtil; @@ -43,23 +42,18 @@ import java.io.OutputStream; import java.util.*; public class JarFileSystemImpl extends JarFileSystem implements ApplicationComponent { + @NonNls private static final String IDEA_JARS_NOCOPY = "idea.jars.nocopy"; + + private static final class JarFileSystemImplLock { } + private static final Object LOCK = new JarFileSystemImplLock(); + private final Set myNoCopyJarPaths = SystemInfo.isFileSystemCaseSensitive ? new ConcurrentHashSet() : new ConcurrentHashSet(CaseInsensitiveStringHashingStrategy.INSTANCE); - - private final static Logger LOG = Logger.getInstance(JarFileSystemImpl.class); - - @NonNls private static final String IDEA_JARS_NOCOPY = "idea.jars.nocopy"; - private File myNoCopyJarDir; - private final Map myHandlers = new HashMap(); + private File myNoCopyJarDir; private String[] jarPathsCache; // jarPathsCache = myHandlers.keySet() - private static final class JarFileSystemImplLock { - } - - private static final Object LOCK = new JarFileSystemImplLock(); - public JarFileSystemImpl(MessageBus bus) { bus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() { @Override @@ -107,7 +101,7 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo } } - VirtualFile[] roots = VfsUtil.toVirtualFileArray(rootsToRefresh); + VirtualFile[] roots = VfsUtilCore.toVirtualFileArray(rootsToRefresh); RefreshQueue.getInstance().refresh(false, true, null, roots); } }; @@ -301,8 +295,8 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo } @Override - public void setTimeStamp(@NotNull final VirtualFile file, final long modstamp) throws IOException { - getHandler(file).setTimeStamp(file, modstamp); + public void setTimeStamp(@NotNull final VirtualFile file, final long modStamp) throws IOException { + getHandler(file).setTimeStamp(file, modStamp); } @Override From d901cd9d5da4c82d8d25ba28a1ecab6cbc91604d Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 24 Jul 2012 12:20:44 +0200 Subject: [PATCH 31/35] Lost changes --- native/IdeaWin32/readme.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/native/IdeaWin32/readme.txt b/native/IdeaWin32/readme.txt index e69de29bb2d1..d3a99b387d3c 100644 --- a/native/IdeaWin32/readme.txt +++ b/native/IdeaWin32/readme.txt @@ -0,0 +1,9 @@ +Prerequisites: +- Visual Studio C++ 2010 Express +- Windows SDK 7.1 (native: Windows Headers, x86 Libraries, x64 Libraries, Tools, Visual C++ Compilers) +- JDK 1.6+ + +To build: +- open Property Manager, expand any configuration, open IdeaWin32 property page, and edit JAVA_HOME user macro + to point to a valid JDK installation +- build Release/Win32 and Release/x64 configurations From 8e87fb2551919197849a1d8de4ded1695115df51 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 24 Jul 2012 12:11:28 +0200 Subject: [PATCH 32/35] IDEA-89175 Completing an annotation on an @interface class should always suggest meta-annotations --- .../completion/JavaNoVariantsDelegator.java | 16 +- .../PreferApplicableAnnotations.java | 14 +- .../NormalCompletionOrderingTest.groovy | 11 +- .../completion/GroovyNoVariantsDelegator.java | 364 +++++++++--------- .../completion/GroovyCompletionTest.groovy | 16 +- 5 files changed, 220 insertions(+), 201 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java index 78a87644b8ed..af6dc31c8482 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java @@ -30,6 +30,9 @@ import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; +import static com.intellij.patterns.PsiJavaPatterns.psiClass; +import static com.intellij.patterns.PsiJavaPatterns.psiElement; + /** * @author peter */ @@ -37,17 +40,24 @@ public class JavaNoVariantsDelegator extends CompletionContributor { @Override public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) { - final boolean empty = containsOnlyPackages(result.runRemainingContributors(parameters, true)); + final boolean empty = containsOnlyPackages(result.runRemainingContributors(parameters, true)) || + suggestMetaAnnotations(parameters); if (!empty && parameters.getInvocationCount() == 0) { result.restartCompletionWhenNothingMatches(); } if (empty) { - delegate(parameters, result); + delegate(parameters, JavaCompletionSorting.addJavaSorting(parameters, result)); } } + private static boolean suggestMetaAnnotations(CompletionParameters parameters) { + PsiElement position = parameters.getPosition(); + return psiElement().withParents(PsiJavaCodeReferenceElement.class, PsiAnnotation.class, PsiModifierList.class, PsiClass.class).accepts( position) && + psiElement().withSuperParent(4, psiClass().isAnnotationType()).accepts(position); + } + public static boolean containsOnlyPackages(LinkedHashSet results) { for (CompletionResult result : results) { if (!(CompletionUtil.getTargetElement(result.getLookupElement()) instanceof PsiPackage)) { @@ -152,7 +162,7 @@ public class JavaNoVariantsDelegator extends CompletionContributor { final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result); JavaClassNameCompletionContributor.addAllClasses(parameters, - true, JavaCompletionSorting.addJavaSorting(parameters, result).getPrefixMatcher(), new Consumer() { + true, result.getPrefixMatcher(), new Consumer() { @Override public void consume(LookupElement element) { JavaPsiClassReferenceElement classElement = element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY); diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/PreferApplicableAnnotations.java b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferApplicableAnnotations.java index 75ba46a656f5..fe6080708ee9 100644 --- a/java/java-tests/testData/codeInsight/completion/normalSorting/PreferApplicableAnnotations.java +++ b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferApplicableAnnotations.java @@ -1,12 +1,2 @@ -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; - -@Z -@interface Foo { -} - -@Target({ElementType.ANNOTATION_TYPE}) -@interface ZMetaAnno {} - -@Target({ElementType.LOCAL_VARIABLE}) -@interface ZLocalAnno {} \ No newline at end of file +@T +@interface Foo { } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy index aa532f06acb5..df1588a69eab 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy @@ -343,7 +343,16 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase { } public void testPreferApplicableAnnotations() throws Throwable { - checkPreferredItems 0, 'ZMetaAnno', 'ZLocalAnno' + myFixture.addClass ''' +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +@Target({ElementType.ANNOTATION_TYPE}) +@interface TMetaAnno {} + +@Target({ElementType.LOCAL_VARIABLE}) +@interface TLocalAnno {}''' + checkPreferredItems 0, 'TMetaAnno', 'Target', 'TreeSelectionMode', 'TLocalAnno' } public void testJComponentAddNewWithStats() throws Throwable { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java index ed5c200dac8c..0c485f1bfa63 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java @@ -1,176 +1,188 @@ -/* - * Copyright 2000-2011 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.plugins.groovy.lang.completion; - -import com.intellij.codeInsight.completion.*; -import com.intellij.codeInsight.completion.impl.CamelHumpMatcher; -import com.intellij.codeInsight.lookup.AutoCompletionPolicy; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.psi.*; -import com.intellij.psi.search.PsiShortNamesCache; -import com.intellij.util.Consumer; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; - -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Set; - -/** - * @author peter - */ -public class GroovyNoVariantsDelegator extends CompletionContributor { - - @Override - public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) { - final boolean empty = JavaNoVariantsDelegator.containsOnlyPackages(result.runRemainingContributors(parameters, true)); - - if (!empty && parameters.getInvocationCount() == 0) { - result.restartCompletionWhenNothingMatches(); - } - - if (empty) { - delegate(parameters, result); - } - } - - private static void delegate(CompletionParameters parameters, CompletionResultSet result) { - if (parameters.getCompletionType() == CompletionType.BASIC) { - if (parameters.getInvocationCount() <= 1 && - JavaCompletionContributor.mayStartClassName(result) && - GroovyCompletionContributor.isClassNamePossible(parameters.getPosition()) && - !MapArgumentCompletionProvider.isMapKeyCompletion(parameters)) { - suggestNonImportedClasses(parameters, result); - } - - suggestChainedCalls(parameters, result); - } - } - - private static void suggestNonImportedClasses(CompletionParameters parameters, CompletionResultSet result) { - final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result); - - GroovyCompletionContributor.addAllClasses(parameters, new Consumer() { - @Override - public void consume(LookupElement element) { - JavaPsiClassReferenceElement classElement = - element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY); - if (classElement != null) { - classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); - } - merger.consume(classElement); - } - }, new InheritorsHolder(parameters.getPosition(), result), result.getPrefixMatcher()); - - merger.finishedClassProcessing(); - } - - private static void suggestChainedCalls(CompletionParameters parameters, CompletionResultSet result) { - PsiElement position = parameters.getPosition(); - PsiElement parent = position.getParent(); - if (!(parent instanceof GrReferenceElement)) { - return; - } - PsiElement qualifier = ((GrReferenceElement)parent).getQualifier(); - if (!(qualifier instanceof GrReferenceElement) || - ((GrReferenceElement)qualifier).getQualifier() != null) { - return; - } - PsiElement target = ((GrReferenceElement)qualifier).resolve(); - if (target != null && !(target instanceof PsiPackage)) { - return; - } - - String fullPrefix = position.getContainingFile().getText().substring(parent.getTextRange().getStartOffset(), parameters.getOffset()); - final CompletionResultSet qualifiedCollector = result.withPrefixMatcher(fullPrefix); - InheritorsHolder inheritors = new InheritorsHolder(position, result); - for (final LookupElement base : suggestQualifierItems(parameters, (GrReferenceElement)qualifier, inheritors)) { - final PsiType type = JavaCompletionUtil.getLookupElementType(base); - if (type != null && !PsiType.VOID.equals(type)) { - GrReferenceElement ref = createMockReference(position, type, base); - PsiElement refName = ref.getReferenceNameElement(); - assert refName != null; - CompletionParameters newParams = parameters.withPosition(refName, refName.getTextRange().getStartOffset()); - GroovyCompletionContributor.completeReference(newParams, ref, inheritors, result.getPrefixMatcher(), new Consumer() { - @Override - public void consume(LookupElement element) { - qualifiedCollector.addElement(new JavaChainLookupElement(base, element) { - @Override - protected boolean shouldParenthesizeQualifier(PsiFile file, int startOffset, int endOffset) { - return false; - } - }); - } - }); - } - } - } - - private static GrReferenceElement createMockReference(final PsiElement place, @NotNull PsiType qualifierType, LookupElement qualifierItem) { - GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(place.getProject()); - if (qualifierItem.getObject() instanceof PsiClass) { - return factory - .createReferenceExpressionFromText(((PsiClass)qualifierItem.getObject()).getQualifiedName() + ".xxx", place); - } - - return factory.createReferenceExpressionFromText("xxx.xxx", - JavaCompletionUtil - .createContextWithXxxVariable(place, qualifierType)); - } - - - private static Set suggestQualifierItems(CompletionParameters _parameters, - GrReferenceElement qualifier, - InheritorsHolder inheritors) { - CompletionParameters parameters = - _parameters.withPosition(qualifier.getReferenceNameElement(), qualifier.getTextRange().getEndOffset()); - String referenceName = qualifier.getReferenceName(); - if (referenceName == null) { - return Collections.emptySet(); - } - - final PrefixMatcher qMatcher = new CamelHumpMatcher(referenceName); - final Set variants = new LinkedHashSet(); - GroovyCompletionContributor.completeReference(parameters, qualifier, inheritors, qMatcher, new Consumer() { - @Override - public void consume(LookupElement element) { - if (qMatcher.prefixMatches(element)) { - variants.add(element); - } - } - }); - - for (PsiClass aClass : PsiShortNamesCache.getInstance(qualifier.getProject()).getClassesByName(referenceName, qualifier.getResolveScope())) { - variants.add(GroovyCompletionUtil.createClassLookupItem(aClass)); - } - - - if (variants.isEmpty()) { - GroovyCompletionContributor.addAllClasses(parameters, new Consumer() { - @Override - public void consume(LookupElement element) { - if (qMatcher.prefixMatches(element)) { - variants.add(element); - } - } - }, inheritors, qMatcher); - } - return variants; - } - - -} +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.lang.completion; + +import com.intellij.codeInsight.completion.*; +import com.intellij.codeInsight.completion.impl.CamelHumpMatcher; +import com.intellij.codeInsight.lookup.AutoCompletionPolicy; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.psi.*; +import com.intellij.psi.search.PsiShortNamesCache; +import com.intellij.util.Consumer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnnotationTypeDefinition; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + +import static com.intellij.patterns.PsiJavaPatterns.psiElement; + +/** + * @author peter + */ +public class GroovyNoVariantsDelegator extends CompletionContributor { + + private static boolean suggestMetaAnnotations(CompletionParameters parameters) { + PsiElement position = parameters.getPosition(); + return psiElement().withParents(GrCodeReferenceElement.class, GrAnnotation.class, GrModifierList.class, GrAnnotationTypeDefinition.class).accepts(position); + } + + @Override + public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) { + final boolean empty = JavaNoVariantsDelegator.containsOnlyPackages(result.runRemainingContributors(parameters, true)) || + suggestMetaAnnotations(parameters); + + if (!empty && parameters.getInvocationCount() == 0) { + result.restartCompletionWhenNothingMatches(); + } + + if (empty) { + delegate(parameters, result); + } + } + + private static void delegate(CompletionParameters parameters, CompletionResultSet result) { + if (parameters.getCompletionType() == CompletionType.BASIC) { + if (parameters.getInvocationCount() <= 1 && + JavaCompletionContributor.mayStartClassName(result) && + GroovyCompletionContributor.isClassNamePossible(parameters.getPosition()) && + !MapArgumentCompletionProvider.isMapKeyCompletion(parameters)) { + suggestNonImportedClasses(parameters, result); + } + + suggestChainedCalls(parameters, result); + } + } + + private static void suggestNonImportedClasses(CompletionParameters parameters, CompletionResultSet result) { + final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result); + + GroovyCompletionContributor.addAllClasses(parameters, new Consumer() { + @Override + public void consume(LookupElement element) { + JavaPsiClassReferenceElement classElement = + element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY); + if (classElement != null) { + classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); + } + merger.consume(classElement); + } + }, new InheritorsHolder(parameters.getPosition(), result), result.getPrefixMatcher()); + + merger.finishedClassProcessing(); + } + + private static void suggestChainedCalls(CompletionParameters parameters, CompletionResultSet result) { + PsiElement position = parameters.getPosition(); + PsiElement parent = position.getParent(); + if (!(parent instanceof GrReferenceElement)) { + return; + } + PsiElement qualifier = ((GrReferenceElement)parent).getQualifier(); + if (!(qualifier instanceof GrReferenceElement) || + ((GrReferenceElement)qualifier).getQualifier() != null) { + return; + } + PsiElement target = ((GrReferenceElement)qualifier).resolve(); + if (target != null && !(target instanceof PsiPackage)) { + return; + } + + String fullPrefix = position.getContainingFile().getText().substring(parent.getTextRange().getStartOffset(), parameters.getOffset()); + final CompletionResultSet qualifiedCollector = result.withPrefixMatcher(fullPrefix); + InheritorsHolder inheritors = new InheritorsHolder(position, result); + for (final LookupElement base : suggestQualifierItems(parameters, (GrReferenceElement)qualifier, inheritors)) { + final PsiType type = JavaCompletionUtil.getLookupElementType(base); + if (type != null && !PsiType.VOID.equals(type)) { + GrReferenceElement ref = createMockReference(position, type, base); + PsiElement refName = ref.getReferenceNameElement(); + assert refName != null; + CompletionParameters newParams = parameters.withPosition(refName, refName.getTextRange().getStartOffset()); + GroovyCompletionContributor.completeReference(newParams, ref, inheritors, result.getPrefixMatcher(), new Consumer() { + @Override + public void consume(LookupElement element) { + qualifiedCollector.addElement(new JavaChainLookupElement(base, element) { + @Override + protected boolean shouldParenthesizeQualifier(PsiFile file, int startOffset, int endOffset) { + return false; + } + }); + } + }); + } + } + } + + private static GrReferenceElement createMockReference(final PsiElement place, @NotNull PsiType qualifierType, LookupElement qualifierItem) { + GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(place.getProject()); + if (qualifierItem.getObject() instanceof PsiClass) { + return factory + .createReferenceExpressionFromText(((PsiClass)qualifierItem.getObject()).getQualifiedName() + ".xxx", place); + } + + return factory.createReferenceExpressionFromText("xxx.xxx", + JavaCompletionUtil + .createContextWithXxxVariable(place, qualifierType)); + } + + + private static Set suggestQualifierItems(CompletionParameters _parameters, + GrReferenceElement qualifier, + InheritorsHolder inheritors) { + CompletionParameters parameters = + _parameters.withPosition(qualifier.getReferenceNameElement(), qualifier.getTextRange().getEndOffset()); + String referenceName = qualifier.getReferenceName(); + if (referenceName == null) { + return Collections.emptySet(); + } + + final PrefixMatcher qMatcher = new CamelHumpMatcher(referenceName); + final Set variants = new LinkedHashSet(); + GroovyCompletionContributor.completeReference(parameters, qualifier, inheritors, qMatcher, new Consumer() { + @Override + public void consume(LookupElement element) { + if (qMatcher.prefixMatches(element)) { + variants.add(element); + } + } + }); + + for (PsiClass aClass : PsiShortNamesCache.getInstance(qualifier.getProject()).getClassesByName(referenceName, qualifier.getResolveScope())) { + variants.add(GroovyCompletionUtil.createClassLookupItem(aClass)); + } + + + if (variants.isEmpty()) { + GroovyCompletionContributor.addAllClasses(parameters, new Consumer() { + @Override + public void consume(LookupElement element) { + if (qMatcher.prefixMatches(element)) { + variants.add(element); + } + } + }, inheritors, qMatcher); + } + return variants; + } + + +} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index 4b2c458e6d94..1effb9ba323f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -1399,21 +1399,19 @@ def bar(){}''') } public void testPreferApplicableAnnotations() { - configure(''' + myFixture.addClass ''' import java.lang.annotation.ElementType; import java.lang.annotation.Target; -@Z -@interface Foo { -} +@Target({ElementType.ANNOTATION_TYPE}) +@interface TMetaAnno {} -@Target(ElementType.ANNOTATION_TYPE) -@interface ZMetaAnno {} +@Target({ElementType.LOCAL_VARIABLE}) +@interface TLocalAnno {}''' -@Target(ElementType.LOCAL_VARIABLE) -@interface ZLocalAnno {}''') + configure('@T @interface Foo {}') myFixture.completeBasic() - myFixture.assertPreferredCompletionItems 0, 'ZMetaAnno', 'ZLocalAnno' + myFixture.assertPreferredCompletionItems 0, 'TMetaAnno', 'Target', 'TreeSelectionMode', 'TLocalAnno' } } \ No newline at end of file From 8b19d329d20a7535c803624ff52f439b7b4187b1 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 24 Jul 2012 14:33:08 +0400 Subject: [PATCH 33/35] EA-36585 - ISE: ComponentManagerImpl.getPicoContainer --- .../idea/maven/project/MavenProjectsManager.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java index 4cea7a342eb8..c566f537d32c 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java @@ -18,6 +18,7 @@ package org.jetbrains.idea.maven.project; import com.intellij.ide.startup.StartupManagerEx; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.components.*; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.module.Module; @@ -334,10 +335,21 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent if (shouldScheduleProject(projectWithChanges)) { scheduleForNextImport(projectWithChanges); + MavenImportingSettings importingSettings; + + AccessToken token = ReadAction.start(); + try { + if (myProject.isDisposed()) return; + importingSettings = getImportingSettings(); + } + finally { + token.finish(); + } + scheduleArtifactsDownloading(Collections.singleton(projectWithChanges.first), null, - getImportingSettings().isDownloadSourcesAutomatically(), - getImportingSettings().isDownloadDocsAutomatically(), + importingSettings.isDownloadSourcesAutomatically(), + importingSettings.isDownloadDocsAutomatically(), null); } From 5a3327e431e4a4d2e07d65ff4aa9ff55c5c816fe Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 24 Jul 2012 14:41:31 +0400 Subject: [PATCH 34/35] EA-36393 - NPE: EncodingProjectManager.getInstance --- .../maven/importing/MavenModuleImporter.java | 492 +++++++++--------- 1 file changed, 246 insertions(+), 246 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java index 5eee5a640775..a319b64bac20 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java @@ -1,246 +1,246 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.maven.importing; - -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleType; -import com.intellij.openapi.roots.*; -import com.intellij.openapi.roots.libraries.Library; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.JarFileSystem; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.encoding.EncodingManager; -import com.intellij.pom.java.LanguageLevel; -import org.jdom.Element; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.model.MavenArtifact; -import org.jetbrains.idea.maven.model.MavenConstants; -import org.jetbrains.idea.maven.project.*; -import org.jetbrains.idea.maven.utils.MavenUtil; - -import java.nio.charset.Charset; -import java.nio.charset.IllegalCharsetNameException; -import java.nio.charset.UnsupportedCharsetException; -import java.util.List; -import java.util.Map; - -public class MavenModuleImporter { - private final Module myModule; - private final MavenProjectsTree myMavenTree; - private final MavenProject myMavenProject; - - @Nullable - private final MavenProjectChanges myMavenProjectChanges; - private final Map myMavenProjectToModuleName; - private final MavenImportingSettings mySettings; - private final MavenModifiableModelsProvider myModifiableModelsProvider; - private MavenRootModelAdapter myRootModelAdapter; - - public MavenModuleImporter(Module module, - MavenProjectsTree mavenTree, - MavenProject mavenProject, - @Nullable MavenProjectChanges changes, - Map mavenProjectToModuleName, - MavenImportingSettings settings, - MavenModifiableModelsProvider modifiableModelsProvider) { - myModule = module; - myMavenTree = mavenTree; - myMavenProject = mavenProject; - myMavenProjectChanges = changes; - myMavenProjectToModuleName = mavenProjectToModuleName; - mySettings = settings; - myModifiableModelsProvider = modifiableModelsProvider; - } - - public ModifiableRootModel getRootModel() { - return myRootModelAdapter.getRootModel(); - } - - public void config(boolean isNewlyCreatedModule) { - myRootModelAdapter = new MavenRootModelAdapter(myMavenProject, myModule, myModifiableModelsProvider); - myRootModelAdapter.init(isNewlyCreatedModule); - - configFolders(); - configDependencies(); - configLanguageLevel(); - configEncoding(); - } - - public void preConfigFacets() { - final ModuleType moduleType = ModuleType.get(myModule); - - for (final MavenImporter importer : getSuitableImporters()) { - final MavenProjectChanges changes; - if (myMavenProjectChanges == null) { - if (importer.processChangedModulesOnly()) continue; - changes = MavenProjectChanges.NONE; - } - else { - changes = myMavenProjectChanges; - } - - if (importer.getModuleType() == moduleType) { - // facets use FacetConfiguration and like that do not have modifiable models, - // therefore we have to take write lock - MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() { - public void run() { - importer.preProcess(myModule, myMavenProject, changes, myModifiableModelsProvider); - } - }); - } - } - } - - public void configFacets(final List postTasks) { - final ModuleType moduleType = ModuleType.get(myModule); - - for (final MavenImporter importer : getSuitableImporters()) { - final MavenProjectChanges changes; - if (myMavenProjectChanges == null) { - if (importer.processChangedModulesOnly()) continue; - changes = MavenProjectChanges.NONE; - } - else { - changes = myMavenProjectChanges; - } - - if (importer.getModuleType() == moduleType) { - // facets use FacetConfiguration and like that do not have modifiable models, - // therefore we have to take write lock - MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() { - public void run() { - importer.process(myModifiableModelsProvider, - myModule, - myRootModelAdapter, - myMavenTree, - myMavenProject, - changes, - myMavenProjectToModuleName, - postTasks); - } - }); - } - } - } - - private List getSuitableImporters() { - return myMavenProject.getSuitableImporters(); - } - - private void configFolders() { - new MavenFoldersImporter(myMavenProject, mySettings, myRootModelAdapter).config(); - } - - private void configDependencies() { - for (MavenArtifact artifact : myMavenProject.getDependencies()) { - if (!myMavenProject.isSupportedDependency(artifact, SupportedRequestType.FOR_IMPORT)) continue; - - DependencyScope scope = selectScope(artifact.getScope()); - MavenProject depProject = myMavenTree.findProject(artifact.getMavenId()); - - if (depProject != null) { - if (depProject == myMavenProject) continue; - myRootModelAdapter.addModuleDependency(myMavenProjectToModuleName.get(depProject), scope); - - Element buildHelperCfg = depProject.getPluginGoalConfiguration("org.codehaus.mojo", "build-helper-maven-plugin", "attach-artifact"); - if (buildHelperCfg != null) { - addAttachArtifactDependency(buildHelperCfg, scope, depProject, artifact); - } - } - else { - myRootModelAdapter.addLibraryDependency(artifact, scope, myModifiableModelsProvider, myMavenProject); - } - } - } - - private void addAttachArtifactDependency(@NotNull Element buildHelperCfg, - @NotNull DependencyScope scope, - @NotNull MavenProject mavenProject, - @NotNull MavenArtifact artifact) { - Library.ModifiableModel libraryModel = null; - - for (Element artifactsElement : (List)buildHelperCfg.getChildren("artifacts")) { - for (Element artifactElement : (List)artifactsElement.getChildren("artifact")) { - String typeString = artifactElement.getChildTextTrim("type"); - if (typeString != null && !typeString.equals("jar")) continue; - - OrderRootType rootType = OrderRootType.CLASSES; - - String classifier = artifactElement.getChildTextTrim("classifier"); - if ("sources".equals(classifier)) { - rootType = OrderRootType.SOURCES; - } - else if ("javadoc".equals(classifier)) { - rootType = JavadocOrderRootType.getInstance(); - } - - String filePath = artifactElement.getChildTextTrim("file"); - if (StringUtil.isEmpty(filePath)) continue; - - VirtualFile file = VfsUtil.findRelativeFile(filePath, mavenProject.getDirectoryFile()); - if (file == null) continue; - - file = JarFileSystem.getInstance().getJarRootForLocalFile(file); - if (file == null) continue; - - if (libraryModel == null) { - String libraryName = artifact.getLibraryName(); - assert libraryName.startsWith(MavenArtifact.MAVEN_LIB_PREFIX); - libraryName = MavenArtifact.MAVEN_LIB_PREFIX + "ATTACHED-JAR: " + libraryName.substring(MavenArtifact.MAVEN_LIB_PREFIX.length()); - - Library library = myModifiableModelsProvider.getLibraryByName(libraryName); - if (library == null) { - library = myModifiableModelsProvider.createLibrary(libraryName); - } - libraryModel = myModifiableModelsProvider.getLibraryModel(library); - - LibraryOrderEntry entry = myRootModelAdapter.getRootModel().addLibraryEntry(library); - entry.setScope(scope); - } - - libraryModel.addRoot(file, rootType); - } - } - } - - @NotNull - private static DependencyScope selectScope(String mavenScope) { - if (MavenConstants.SCOPE_RUNTIME.equals(mavenScope)) return DependencyScope.RUNTIME; - if (MavenConstants.SCOPE_TEST.equals(mavenScope)) return DependencyScope.TEST; - if (MavenConstants.SCOPE_PROVIDEED.equals(mavenScope)) return DependencyScope.PROVIDED; - return DependencyScope.COMPILE; - } - - private void configEncoding() { - if (Boolean.parseBoolean(System.getProperty("maven.disable.encode.import"))) return; - - String encoding = myMavenProject.getEncoding(); - if (encoding != null) { - try { - EncodingManager.getInstance().setEncoding(myMavenProject.getDirectoryFile(), Charset.forName(encoding)); - } - catch (UnsupportedCharsetException ignored) {/**/} - catch (IllegalCharsetNameException ignored) {/**/} - } - } - - private void configLanguageLevel() { - final LanguageLevel level = LanguageLevel.parse(myMavenProject.getSourceLevel()); - myRootModelAdapter.setLanguageLevel(level); - } -} +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.importing; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleType; +import com.intellij.openapi.roots.*; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.JarFileSystem; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.encoding.EncodingProjectManager; +import com.intellij.pom.java.LanguageLevel; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.model.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenConstants; +import org.jetbrains.idea.maven.project.*; +import org.jetbrains.idea.maven.utils.MavenUtil; + +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; +import java.util.List; +import java.util.Map; + +public class MavenModuleImporter { + private final Module myModule; + private final MavenProjectsTree myMavenTree; + private final MavenProject myMavenProject; + + @Nullable + private final MavenProjectChanges myMavenProjectChanges; + private final Map myMavenProjectToModuleName; + private final MavenImportingSettings mySettings; + private final MavenModifiableModelsProvider myModifiableModelsProvider; + private MavenRootModelAdapter myRootModelAdapter; + + public MavenModuleImporter(Module module, + MavenProjectsTree mavenTree, + MavenProject mavenProject, + @Nullable MavenProjectChanges changes, + Map mavenProjectToModuleName, + MavenImportingSettings settings, + MavenModifiableModelsProvider modifiableModelsProvider) { + myModule = module; + myMavenTree = mavenTree; + myMavenProject = mavenProject; + myMavenProjectChanges = changes; + myMavenProjectToModuleName = mavenProjectToModuleName; + mySettings = settings; + myModifiableModelsProvider = modifiableModelsProvider; + } + + public ModifiableRootModel getRootModel() { + return myRootModelAdapter.getRootModel(); + } + + public void config(boolean isNewlyCreatedModule) { + myRootModelAdapter = new MavenRootModelAdapter(myMavenProject, myModule, myModifiableModelsProvider); + myRootModelAdapter.init(isNewlyCreatedModule); + + configFolders(); + configDependencies(); + configLanguageLevel(); + configEncoding(); + } + + public void preConfigFacets() { + final ModuleType moduleType = ModuleType.get(myModule); + + for (final MavenImporter importer : getSuitableImporters()) { + final MavenProjectChanges changes; + if (myMavenProjectChanges == null) { + if (importer.processChangedModulesOnly()) continue; + changes = MavenProjectChanges.NONE; + } + else { + changes = myMavenProjectChanges; + } + + if (importer.getModuleType() == moduleType) { + // facets use FacetConfiguration and like that do not have modifiable models, + // therefore we have to take write lock + MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() { + public void run() { + importer.preProcess(myModule, myMavenProject, changes, myModifiableModelsProvider); + } + }); + } + } + } + + public void configFacets(final List postTasks) { + final ModuleType moduleType = ModuleType.get(myModule); + + for (final MavenImporter importer : getSuitableImporters()) { + final MavenProjectChanges changes; + if (myMavenProjectChanges == null) { + if (importer.processChangedModulesOnly()) continue; + changes = MavenProjectChanges.NONE; + } + else { + changes = myMavenProjectChanges; + } + + if (importer.getModuleType() == moduleType) { + // facets use FacetConfiguration and like that do not have modifiable models, + // therefore we have to take write lock + MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() { + public void run() { + importer.process(myModifiableModelsProvider, + myModule, + myRootModelAdapter, + myMavenTree, + myMavenProject, + changes, + myMavenProjectToModuleName, + postTasks); + } + }); + } + } + } + + private List getSuitableImporters() { + return myMavenProject.getSuitableImporters(); + } + + private void configFolders() { + new MavenFoldersImporter(myMavenProject, mySettings, myRootModelAdapter).config(); + } + + private void configDependencies() { + for (MavenArtifact artifact : myMavenProject.getDependencies()) { + if (!myMavenProject.isSupportedDependency(artifact, SupportedRequestType.FOR_IMPORT)) continue; + + DependencyScope scope = selectScope(artifact.getScope()); + MavenProject depProject = myMavenTree.findProject(artifact.getMavenId()); + + if (depProject != null) { + if (depProject == myMavenProject) continue; + myRootModelAdapter.addModuleDependency(myMavenProjectToModuleName.get(depProject), scope); + + Element buildHelperCfg = depProject.getPluginGoalConfiguration("org.codehaus.mojo", "build-helper-maven-plugin", "attach-artifact"); + if (buildHelperCfg != null) { + addAttachArtifactDependency(buildHelperCfg, scope, depProject, artifact); + } + } + else { + myRootModelAdapter.addLibraryDependency(artifact, scope, myModifiableModelsProvider, myMavenProject); + } + } + } + + private void addAttachArtifactDependency(@NotNull Element buildHelperCfg, + @NotNull DependencyScope scope, + @NotNull MavenProject mavenProject, + @NotNull MavenArtifact artifact) { + Library.ModifiableModel libraryModel = null; + + for (Element artifactsElement : (List)buildHelperCfg.getChildren("artifacts")) { + for (Element artifactElement : (List)artifactsElement.getChildren("artifact")) { + String typeString = artifactElement.getChildTextTrim("type"); + if (typeString != null && !typeString.equals("jar")) continue; + + OrderRootType rootType = OrderRootType.CLASSES; + + String classifier = artifactElement.getChildTextTrim("classifier"); + if ("sources".equals(classifier)) { + rootType = OrderRootType.SOURCES; + } + else if ("javadoc".equals(classifier)) { + rootType = JavadocOrderRootType.getInstance(); + } + + String filePath = artifactElement.getChildTextTrim("file"); + if (StringUtil.isEmpty(filePath)) continue; + + VirtualFile file = VfsUtil.findRelativeFile(filePath, mavenProject.getDirectoryFile()); + if (file == null) continue; + + file = JarFileSystem.getInstance().getJarRootForLocalFile(file); + if (file == null) continue; + + if (libraryModel == null) { + String libraryName = artifact.getLibraryName(); + assert libraryName.startsWith(MavenArtifact.MAVEN_LIB_PREFIX); + libraryName = MavenArtifact.MAVEN_LIB_PREFIX + "ATTACHED-JAR: " + libraryName.substring(MavenArtifact.MAVEN_LIB_PREFIX.length()); + + Library library = myModifiableModelsProvider.getLibraryByName(libraryName); + if (library == null) { + library = myModifiableModelsProvider.createLibrary(libraryName); + } + libraryModel = myModifiableModelsProvider.getLibraryModel(library); + + LibraryOrderEntry entry = myRootModelAdapter.getRootModel().addLibraryEntry(library); + entry.setScope(scope); + } + + libraryModel.addRoot(file, rootType); + } + } + } + + @NotNull + private static DependencyScope selectScope(String mavenScope) { + if (MavenConstants.SCOPE_RUNTIME.equals(mavenScope)) return DependencyScope.RUNTIME; + if (MavenConstants.SCOPE_TEST.equals(mavenScope)) return DependencyScope.TEST; + if (MavenConstants.SCOPE_PROVIDEED.equals(mavenScope)) return DependencyScope.PROVIDED; + return DependencyScope.COMPILE; + } + + private void configEncoding() { + if (Boolean.parseBoolean(System.getProperty("maven.disable.encode.import"))) return; + + String encoding = myMavenProject.getEncoding(); + if (encoding != null) { + try { + EncodingProjectManager.getInstance(myModule.getProject()).setEncoding(myMavenProject.getDirectoryFile(), Charset.forName(encoding)); + } + catch (UnsupportedCharsetException ignored) {/**/} + catch (IllegalCharsetNameException ignored) {/**/} + } + } + + private void configLanguageLevel() { + final LanguageLevel level = LanguageLevel.parse(myMavenProject.getSourceLevel()); + myRootModelAdapter.setLanguageLevel(level); + } +} From a17fbd9b81e92d1a4e77c8aa6a8a82be4c504763 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 24 Jul 2012 14:56:37 +0400 Subject: [PATCH 35/35] IDEA-66333 Quick documentation lookup on mouse hover Corrected links appliance in case of partial head match --- .../navigation/DocPreviewUtil.java | 4 ++++ .../navigation/DocPreviewUtilTest.groovy | 20 ++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/DocPreviewUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/DocPreviewUtil.java index 70c485b6b1cf..63d95d730fca 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/DocPreviewUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/DocPreviewUtil.java @@ -191,6 +191,10 @@ public class DocPreviewUtil { // We don't want to perform the replacement then. continue; } + if (end - i > 1 && i > 0 && !ALLOWED_LINK_SEPARATORS.contains(text.charAt(i - 1))) { + // Similar situation but targets head match: from = 'TextRange', text = 'getTextRange()'. + continue; + } text.replace(i, end, replaceTo); int diff = replaceTo.length() - replaceFrom.length(); for (int j = 0; j < readOnlyChanges.size(); j++) { diff --git a/platform/lang-impl/testSources/com/intellij/codeInsight/navigation/DocPreviewUtilTest.groovy b/platform/lang-impl/testSources/com/intellij/codeInsight/navigation/DocPreviewUtilTest.groovy index 31b235dcd1ca..22df21db934c 100644 --- a/platform/lang-impl/testSources/com/intellij/codeInsight/navigation/DocPreviewUtilTest.groovy +++ b/platform/lang-impl/testSources/com/intellij/codeInsight/navigation/DocPreviewUtilTest.groovy @@ -147,7 +147,7 @@ Qname''' } @Test - void substrings() { + void tailSubstrings() { def header = '''\ PsiResolveHelperImpl public static com.intellij.openapi.util.Pair<com.intellij.psi.PsiType, com.intellij.psi.ConstraintType> getSubstitutionForTypeParameterConstraint (com.intellij.psi.PsiTypeParameter typeParam, com.intellij.psi.PsiType param, com.intellij.psi.PsiType arg, boolean isContraVariantPosition, com.intellij.pom.java.LanguageLevel languageLevel)''' @@ -164,4 +164,22 @@ public static com.intellij.openapi.util.Pair<com.intellij.psi.PsiType, com.in assertEquals(expected, DocPreviewUtil.buildPreview(header, null, fullText)) } + + @Test + void headSubstrings() { + def header = '''\ +ASTNode +com.intellij.openapi.util.TextRange getTextRange ()''' + + def fullText = '''\ + com.intellij.lang.ASTNode
TextRange getTextRange()
+ Returns the text range (a combination of starting offset in the document and length) for this node. + +
Returns:
the text range.
''' + + def expected = '''\ +ASTNode
TextRange getTextRange ()''' + + assertEquals(expected, DocPreviewUtil.buildPreview(header, null, fullText)) + } }