From fe756f33174e3e59d1c7787c1abef45df2253d99 Mon Sep 17 00:00:00 2001 From: Ilya Ryzhenkov Date: Wed, 25 Apr 2018 21:01:37 +0300 Subject: [PATCH] Add support for packaging Module Sources to Artifacts. (IDEA-110964) --- .../ant/artifacts/ArtifactsGenerator.java | 3 - .../impl/artifacts/ArtifactUtil.java | 4 +- .../impl/elements/ModuleElementTypeBase.java | 91 ++++++++++++++++ .../elements/ModuleOutputElementTypeBase.java | 70 ++---------- .../ModuleOutputPackagingElement.java | 37 +------ .../ModuleOutputPackagingElementBase.java | 100 +++--------------- .../impl/elements/ModulePackagingElement.java | 38 +++++++ .../elements/ModulePackagingElementBase.java | 76 +++++++++++++ .../elements/ModulePackagingElementState.java | 20 ++++ .../elements/PackagingElementFactoryImpl.java | 12 ++- .../ProductionModuleOutputElementType.java | 10 +- ...roductionModuleOutputPackagingElement.java | 9 +- .../ProductionModuleSourceElementType.kt | 29 +++++ .../ProductionModuleSourcePackagingElement.kt | 52 +++++++++ .../elements/TestModuleOutputElementType.java | 20 +++- .../TestModuleOutputPackagingElement.java | 9 +- .../impl/ui/ModuleElementPresentation.java | 27 +++-- .../openapi/compiler/CompilerBundle.java | 1 + .../elements/PackagingElementFactory.java | 3 + .../elements/PackagingElementOutputKind.java | 9 +- .../packaging/ui/SourceItemWeights.java | 1 + .../TestPackagingElementBuilder.java | 5 + .../UpdateArtifactsAfterRenameTest.java | 11 +- .../artifacts/ui/AddNewElementActionTest.java | 11 ++ .../ArtifactProjectStructureElement.java | 6 +- .../sourceItems/ModuleOutputSourceItem.java | 3 +- ...odulesAndLibrariesSourceItemsProvider.java | 36 ++++--- .../LayoutElementBuildersRegistry.java | 46 +++++++- .../artifacts/ArtifactBuilderTest.kt | 44 ++++++++ .../artifacts/LayoutElementTestUtil.java | 4 + .../model/java/JpsJavaExtensionService.java | 3 + ...roductionModuleSourcePackagingElement.java | 11 ++ .../impl/JpsJavaExtensionServiceImpl.java | 6 ++ ...ctionModuleSourcePackagingElementImpl.java | 37 +++++++ .../java/JpsJavaModelSerializerExtension.java | 22 +++- .../src/messages/CompilerBundle.properties | 2 + 36 files changed, 614 insertions(+), 254 deletions(-) create mode 100644 java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleElementTypeBase.java create mode 100644 java/compiler/impl/src/com/intellij/packaging/impl/elements/ModulePackagingElement.java create mode 100644 java/compiler/impl/src/com/intellij/packaging/impl/elements/ModulePackagingElementBase.java create mode 100644 java/compiler/impl/src/com/intellij/packaging/impl/elements/ModulePackagingElementState.java create mode 100644 java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleSourceElementType.kt create mode 100644 java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleSourcePackagingElement.kt create mode 100644 jps/model-api/src/org/jetbrains/jps/model/java/JpsProductionModuleSourcePackagingElement.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsProductionModuleSourcePackagingElementImpl.java diff --git a/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/ArtifactsGenerator.java b/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/ArtifactsGenerator.java index 4ce28f50f884..fbeacf6f13d6 100644 --- a/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/ArtifactsGenerator.java +++ b/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/ArtifactsGenerator.java @@ -25,14 +25,11 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.packaging.artifacts.Artifact; import com.intellij.packaging.artifacts.ArtifactManager; import com.intellij.packaging.artifacts.ArtifactType; -import com.intellij.packaging.elements.PackagingElement; import com.intellij.packaging.elements.PackagingElementResolvingContext; import com.intellij.packaging.impl.artifacts.ArtifactUtil; import com.intellij.packaging.impl.elements.ArtifactPackagingElement; import com.intellij.packaging.impl.elements.ModuleOutputPackagingElement; -import com.intellij.util.Processor; import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Arrays; diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java index e8017ca8dd98..f7503dc47c56 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java @@ -437,9 +437,9 @@ public class ArtifactUtil { ContainerUtil.addIfNotNull(result, sourceRoot.findFileByRelativePath(path)); } } - else if (element instanceof ModuleOutputPackagingElement) { + else if (element instanceof ModulePackagingElement) { final CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(context.getProject()); - for (VirtualFile sourceRoot : ((ModuleOutputPackagingElement)element).getSourceRoots(context)) { + for (VirtualFile sourceRoot : ((ModulePackagingElement)element).getSourceRoots(context)) { final VirtualFile sourceFile = sourceRoot.findFileByRelativePath(path); if (sourceFile != null && compilerConfiguration.isResourceFile(sourceFile)) { result.add(sourceFile); diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleElementTypeBase.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleElementTypeBase.java new file mode 100644 index 000000000000..4a5c1cf3236b --- /dev/null +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleElementTypeBase.java @@ -0,0 +1,91 @@ +/* + * 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.packaging.impl.elements; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModulePointer; +import com.intellij.openapi.module.ModulePointerManager; +import com.intellij.openapi.module.ModuleType; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectBundle; +import com.intellij.openapi.roots.ui.configuration.ModulesProvider; +import com.intellij.packaging.artifacts.Artifact; +import com.intellij.packaging.elements.CompositePackagingElement; +import com.intellij.packaging.elements.PackagingElement; +import com.intellij.packaging.elements.PackagingElementType; +import com.intellij.packaging.ui.ArtifactEditorContext; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; + +/** + * @author nik + */ +public abstract class ModuleElementTypeBase extends PackagingElementType { + public ModuleElementTypeBase(String id, String presentableName) { + super(id, presentableName); + } + + @Override + public boolean canCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact) { + return !getSuitableModules(context).isEmpty(); + } + + @NotNull + public List> chooseAndCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact, + @NotNull CompositePackagingElement parent) { + List suitableModules = getSuitableModules(context); + List selected = context.chooseModules(suitableModules, ProjectBundle.message("dialog.title.packaging.choose.module")); + + final List> elements = new ArrayList<>(); + final ModulePointerManager pointerManager = ModulePointerManager.getInstance(context.getProject()); + for (Module module : selected) { + elements.add(createElement(context.getProject(), pointerManager.create(module))); + } + return elements; + } + + protected abstract ModulePackagingElementBase createElement(@NotNull Project project, @NotNull ModulePointer pointer); + + private List getSuitableModules(ArtifactEditorContext context) { + ModulesProvider modulesProvider = context.getModulesProvider(); + ArrayList modules = new ArrayList<>(); + for (Module module : modulesProvider.getModules()) { + if (isSuitableModule(modulesProvider, module)) { + modules.add(module); + } + } + return modules; + } + + public abstract boolean isSuitableModule(@NotNull ModulesProvider modulesProvider, @NotNull Module module); + + /** + * Provides element presentation text. + * @param moduleName name of the module for which this presentation is requested. + * @return text to display. + */ + @NotNull + public abstract String getElementText(@NotNull String moduleName); + + public Icon getElementIcon(@Nullable Module module) { + return module != null ? ModuleType.get(module).getIcon() : AllIcons.Modules.Output; + } +} diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputElementTypeBase.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputElementTypeBase.java index f3ee27bf8817..37c60c44b954 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputElementTypeBase.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputElementTypeBase.java @@ -1,75 +1,17 @@ -/* - * 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.packaging.impl.elements; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModulePointer; -import com.intellij.openapi.module.ModulePointerManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectBundle; -import com.intellij.openapi.roots.ui.configuration.ModulesProvider; -import com.intellij.packaging.artifacts.Artifact; -import com.intellij.packaging.elements.CompositePackagingElement; -import com.intellij.packaging.elements.PackagingElement; -import com.intellij.packaging.elements.PackagingElementType; -import com.intellij.packaging.ui.ArtifactEditorContext; +import com.intellij.openapi.compiler.CompilerBundle; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.List; - -/** - * @author nik - */ -public abstract class ModuleOutputElementTypeBase extends PackagingElementType { +public abstract class ModuleOutputElementTypeBase extends ModuleElementTypeBase { public ModuleOutputElementTypeBase(String id, String presentableName) { super(id, presentableName); } - @Override - public boolean canCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact) { - return !getSuitableModules(context).isEmpty(); - } - @NotNull - public List> chooseAndCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact, - @NotNull CompositePackagingElement parent) { - List suitableModules = getSuitableModules(context); - List selected = context.chooseModules(suitableModules, ProjectBundle.message("dialog.title.packaging.choose.module")); - - final List> elements = new ArrayList<>(); - final ModulePointerManager pointerManager = ModulePointerManager.getInstance(context.getProject()); - for (Module module : selected) { - elements.add(createElement(context.getProject(), pointerManager.create(module))); - } - return elements; + @Override + public String getElementText(@NotNull String moduleName) { + return CompilerBundle.message("node.text.0.compile.output", moduleName); } - - protected abstract ModuleOutputPackagingElementBase createElement(@NotNull Project project, @NotNull ModulePointer pointer); - - private List getSuitableModules(ArtifactEditorContext context) { - ModulesProvider modulesProvider = context.getModulesProvider(); - ArrayList modules = new ArrayList<>(); - for (Module module : modulesProvider.getModules()) { - if (isSuitableModule(modulesProvider, module)) { - modules.add(module); - } - } - return modules; - } - - public abstract boolean isSuitableModule(ModulesProvider modulesProvider, Module module); } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElement.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElement.java index d73572d36529..eab8f6833912 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElement.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElement.java @@ -1,38 +1,5 @@ -/* - * 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.packaging.impl.elements; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.packaging.elements.PackagingElementResolvingContext; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; - -/** - * @author nik - */ -public interface ModuleOutputPackagingElement { - @Nullable - String getModuleName(); - - @Nullable - Module findModule(PackagingElementResolvingContext context); - - @NotNull - Collection getSourceRoots(PackagingElementResolvingContext context); +public interface ModuleOutputPackagingElement extends ModulePackagingElement{ } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElementBase.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElementBase.java index f23b0daa160a..ed5e9cdb0ea5 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElementBase.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElementBase.java @@ -3,119 +3,47 @@ package com.intellij.packaging.impl.elements; import com.intellij.compiler.ant.BuildProperties; import com.intellij.compiler.ant.Generator; -import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModulePointer; -import com.intellij.openapi.module.ModulePointerManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.CompilerModuleExtension; -import com.intellij.openapi.roots.ui.configuration.DefaultModulesProvider; -import com.intellij.openapi.roots.ui.configuration.ModulesProvider; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.packaging.artifacts.ArtifactType; import com.intellij.packaging.elements.*; -import com.intellij.util.ArrayUtil; -import com.intellij.util.xmlb.annotations.Attribute; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.List; -/** - * @author nik - */ -public abstract class ModuleOutputPackagingElementBase extends PackagingElement implements ModuleOutputPackagingElement { - @NonNls public static final String MODULE_NAME_ATTRIBUTE = "name"; - protected ModulePointer myModulePointer; - protected final Project myProject; - - public ModuleOutputPackagingElementBase(PackagingElementType type, Project project, ModulePointer modulePointer) { - super(type); - myProject = project; - myModulePointer = modulePointer; +public abstract class ModuleOutputPackagingElementBase extends ModulePackagingElementBase implements ModuleOutputPackagingElement { + public ModuleOutputPackagingElementBase(PackagingElementType type, + Project project, + ModulePointer modulePointer) { + super(type, project, modulePointer); } - public ModuleOutputPackagingElementBase(PackagingElementType type, Project project) { - super(type); - myProject = project; - } + @Nullable + protected abstract String getDirectoryAntProperty(ArtifactAntGenerationContext generationContext); @NotNull @Override - public List computeAntInstructions(@NotNull PackagingElementResolvingContext resolvingContext, @NotNull AntCopyInstructionCreator creator, + public List computeAntInstructions(@NotNull PackagingElementResolvingContext resolvingContext, + @NotNull AntCopyInstructionCreator creator, @NotNull ArtifactAntGenerationContext generationContext, @NotNull ArtifactType artifactType) { - if (myModulePointer != null) { - final String moduleOutput = BuildProperties.propertyRef(getModuleOutputAntProperty(generationContext)); + String property = getDirectoryAntProperty(generationContext); + if (myModulePointer != null && property != null) { + final String moduleOutput = BuildProperties.propertyRef(property); return Collections.singletonList(creator.createDirectoryContentCopyInstruction(moduleOutput)); } return Collections.emptyList(); } - protected abstract String getModuleOutputAntProperty(ArtifactAntGenerationContext generationContext); - - @Nullable - protected abstract VirtualFile getModuleOutputPath(CompilerModuleExtension extension); - @NotNull @Override public PackagingElementOutputKind getFilesKind(PackagingElementResolvingContext context) { return PackagingElementOutputKind.DIRECTORIES_WITH_CLASSES; } - @Override - public boolean isEqualTo(@NotNull PackagingElement element) { - return element.getClass() == getClass() && myModulePointer != null - && myModulePointer.equals(((ModuleOutputPackagingElementBase)element).myModulePointer); - } - - public ModuleOutputPackagingElementState getState() { - final ModuleOutputPackagingElementState state = new ModuleOutputPackagingElementState(); - if (myModulePointer != null) { - state.setModuleName(myModulePointer.getModuleName()); - } - return state; - } - - public void loadState(@NotNull ModuleOutputPackagingElementState state) { - final String moduleName = state.getModuleName(); - myModulePointer = moduleName != null ? ModulePointerManager.getInstance(myProject).create(moduleName) : null; - } - - @Override - @Nullable - public String getModuleName() { - return myModulePointer != null ? myModulePointer.getModuleName() : null; - } - - @Override - @Nullable - public Module findModule(PackagingElementResolvingContext context) { - if (myModulePointer != null) { - final Module module = myModulePointer.getModule(); - final ModulesProvider modulesProvider = context.getModulesProvider(); - if (module != null) { - if (modulesProvider instanceof DefaultModulesProvider//optimization - || ArrayUtil.contains(module, modulesProvider.getModules())) { - return module; - } - } - return modulesProvider.getModule(myModulePointer.getModuleName()); - } - return null; - } - - public static class ModuleOutputPackagingElementState { - private String myModuleName; - - @Attribute(MODULE_NAME_ATTRIBUTE) - public String getModuleName() { - return myModuleName; - } - - public void setModuleName(String moduleName) { - myModuleName = moduleName; - } + public ModuleOutputPackagingElementBase(PackagingElementType type, Project project) { + super(type, project); } } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModulePackagingElement.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModulePackagingElement.java new file mode 100644 index 000000000000..3edabb4a8f9c --- /dev/null +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModulePackagingElement.java @@ -0,0 +1,38 @@ +/* + * 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 com.intellij.packaging.impl.elements; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.packaging.elements.PackagingElementResolvingContext; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +/** + * @author nik + */ +public interface ModulePackagingElement { + @Nullable + String getModuleName(); + + @Nullable + Module findModule(PackagingElementResolvingContext context); + + @NotNull + Collection getSourceRoots(PackagingElementResolvingContext context); +} diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModulePackagingElementBase.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModulePackagingElementBase.java new file mode 100644 index 000000000000..7c46482b2fe2 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModulePackagingElementBase.java @@ -0,0 +1,76 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.packaging.impl.elements; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModulePointer; +import com.intellij.openapi.module.ModulePointerManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ui.configuration.DefaultModulesProvider; +import com.intellij.openapi.roots.ui.configuration.ModulesProvider; +import com.intellij.packaging.elements.PackagingElement; +import com.intellij.packaging.elements.PackagingElementResolvingContext; +import com.intellij.packaging.elements.PackagingElementType; +import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author nik + */ +public abstract class ModulePackagingElementBase extends PackagingElement implements ModulePackagingElement { + protected final Project myProject; + protected ModulePointer myModulePointer; + + public ModulePackagingElementBase(PackagingElementType type, Project project, ModulePointer modulePointer) { + super(type); + myProject = project; + myModulePointer = modulePointer; + } + + public ModulePackagingElementBase(PackagingElementType type, Project project) { + super(type); + myProject = project; + } + + @Override + public boolean isEqualTo(@NotNull PackagingElement element) { + return element.getClass() == getClass() && myModulePointer != null + && myModulePointer.equals(((ModulePackagingElementBase)element).myModulePointer); + } + + public ModulePackagingElementState getState() { + final ModulePackagingElementState state = new ModulePackagingElementState(); + if (myModulePointer != null) { + state.setModuleName(myModulePointer.getModuleName()); + } + return state; + } + + public void loadState(@NotNull ModulePackagingElementState state) { + final String moduleName = state.getModuleName(); + myModulePointer = moduleName != null ? ModulePointerManager.getInstance(myProject).create(moduleName) : null; + } + + @Override + @Nullable + public String getModuleName() { + return myModulePointer != null ? myModulePointer.getModuleName() : null; + } + + @Override + @Nullable + public Module findModule(PackagingElementResolvingContext context) { + if (myModulePointer != null) { + final Module module = myModulePointer.getModule(); + final ModulesProvider modulesProvider = context.getModulesProvider(); + if (module != null) { + if (modulesProvider instanceof DefaultModulesProvider//optimization + || ArrayUtil.contains(module, modulesProvider.getModules())) { + return module; + } + } + return modulesProvider.getModule(myModulePointer.getModuleName()); + } + return null; + } +} diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModulePackagingElementState.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModulePackagingElementState.java new file mode 100644 index 000000000000..9cf96b0791f8 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModulePackagingElementState.java @@ -0,0 +1,20 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.packaging.impl.elements; + +import com.intellij.util.xmlb.annotations.Attribute; +import org.jetbrains.annotations.NonNls; + +public class ModulePackagingElementState { + @NonNls public static final String MODULE_NAME_ATTRIBUTE = "name"; + + private String myModuleName; + + @Attribute(MODULE_NAME_ATTRIBUTE) + public String getModuleName() { + return myModuleName; + } + + public void setModuleName(String moduleName) { + myModuleName = moduleName; + } +} diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/PackagingElementFactoryImpl.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/PackagingElementFactoryImpl.java index 66f059213247..24ddc7c9365e 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/PackagingElementFactoryImpl.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/PackagingElementFactoryImpl.java @@ -58,7 +58,10 @@ public class PackagingElementFactoryImpl extends PackagingElementFactory { public static final PackagingElementType> ARTIFACT_ROOT_ELEMENT_TYPE = new ArtifactRootElementType(); private static final PackagingElementType[] STANDARD_TYPES = { DIRECTORY_ELEMENT_TYPE, ARCHIVE_ELEMENT_TYPE, - LibraryElementType.LIBRARY_ELEMENT_TYPE, ProductionModuleOutputElementType.ELEMENT_TYPE, TestModuleOutputElementType.ELEMENT_TYPE, + LibraryElementType.LIBRARY_ELEMENT_TYPE, + ProductionModuleOutputElementType.ELEMENT_TYPE, + TestModuleOutputElementType.ELEMENT_TYPE, + ProductionModuleSourceElementType.ELEMENT_TYPE, ArtifactElementType.ARTIFACT_ELEMENT_TYPE, FILE_COPY_ELEMENT_TYPE, DIRECTORY_COPY_ELEMENT_TYPE, EXTRACTED_DIRECTORY_ELEMENT_TYPE }; @@ -191,6 +194,13 @@ public class PackagingElementFactoryImpl extends PackagingElementFactory { return new ProductionModuleOutputPackagingElement(module.getProject(), modulePointer); } + @NotNull + @Override + public PackagingElement createModuleSource(@NotNull Module module) { + final ModulePointer modulePointer = ModulePointerManager.getInstance(module.getProject()).create(module); + return new ProductionModuleSourcePackagingElement(module.getProject(), modulePointer); + } + @NotNull @Override public PackagingElement createTestModuleOutput(@NotNull Module module) { diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputElementType.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputElementType.java index 3ec8f0cb5403..56d22a90d489 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputElementType.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputElementType.java @@ -31,7 +31,7 @@ import javax.swing.*; public class ProductionModuleOutputElementType extends ModuleOutputElementTypeBase { public static final ProductionModuleOutputElementType ELEMENT_TYPE = new ProductionModuleOutputElementType(); - ProductionModuleOutputElementType() { + private ProductionModuleOutputElementType() { super("module-output", CompilerBundle.message("element.type.name.module.output")); } @@ -49,8 +49,14 @@ public class ProductionModuleOutputElementType extends ModuleOutputElementTypeBa return AllIcons.Nodes.Module; } + @NotNull @Override - public boolean isSuitableModule(ModulesProvider modulesProvider, Module module) { + public String getElementText(@NotNull String moduleName) { + return CompilerBundle.message("node.text.0.compile.output", moduleName); + } + + @Override + public boolean isSuitableModule(@NotNull ModulesProvider modulesProvider, @NotNull Module module) { return modulesProvider.getRootModel(module).getSourceRootUrls(false).length > 0; } } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputPackagingElement.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputPackagingElement.java index 900cdb850979..c09702adbd03 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputPackagingElement.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputPackagingElement.java @@ -18,7 +18,6 @@ package com.intellij.packaging.impl.elements; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModulePointer; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.CompilerModuleExtension; import com.intellij.openapi.roots.ModuleRootModel; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.packaging.elements.ArtifactAntGenerationContext; @@ -51,14 +50,10 @@ public class ProductionModuleOutputPackagingElement extends ModuleOutputPackagin return "module:" + getModuleName(); } - protected String getModuleOutputAntProperty(ArtifactAntGenerationContext generationContext) { + protected String getDirectoryAntProperty(ArtifactAntGenerationContext generationContext) { return generationContext.getModuleOutputPath(myModulePointer.getModuleName()); } - protected VirtualFile getModuleOutputPath(CompilerModuleExtension extension) { - return extension.getCompilerOutputPath(); - } - @NotNull @Override public Collection getSourceRoots(PackagingElementResolvingContext context) { @@ -71,6 +66,6 @@ public class ProductionModuleOutputPackagingElement extends ModuleOutputPackagin @NotNull public PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) { - return new DelegatedPackagingElementPresentation(new ModuleElementPresentation(myModulePointer, context, false)); + return new DelegatedPackagingElementPresentation(new ModuleElementPresentation(myModulePointer, context, ProductionModuleOutputElementType.ELEMENT_TYPE)); } } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleSourceElementType.kt b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleSourceElementType.kt new file mode 100644 index 000000000000..dda08b8573ae --- /dev/null +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleSourceElementType.kt @@ -0,0 +1,29 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.packaging.impl.elements + +import com.intellij.icons.AllIcons +import com.intellij.openapi.compiler.CompilerBundle +import com.intellij.openapi.module.Module +import com.intellij.openapi.module.ModulePointer +import com.intellij.openapi.project.Project +import com.intellij.openapi.roots.ui.configuration.ModulesProvider +import javax.swing.Icon + +class ProductionModuleSourceElementType private constructor() : ModuleElementTypeBase( + "module-source", CompilerBundle.message("element.type.name.module.source")) { + + override fun isSuitableModule(modulesProvider: ModulesProvider, module: Module): Boolean { + return modulesProvider.getRootModel(module).getSourceRootUrls(false).isNotEmpty() + } + + override fun createElement(project: Project, pointer: ModulePointer) = ProductionModuleSourcePackagingElement(project, pointer) + override fun createEmpty(project: Project) = ProductionModuleSourcePackagingElement(project) + override fun getCreateElementIcon(): Icon = AllIcons.Modules.SourceFolder + override fun getElementIcon(module: Module?): Icon = AllIcons.Modules.SourceFolder + override fun getElementText(moduleName: String) = CompilerBundle.message("node.text.0.module.sources", moduleName) + + companion object { + @JvmField + val ELEMENT_TYPE = ProductionModuleSourceElementType() + } +} diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleSourcePackagingElement.kt b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleSourcePackagingElement.kt new file mode 100644 index 000000000000..5036415232d3 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleSourcePackagingElement.kt @@ -0,0 +1,52 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.packaging.impl.elements + +import com.intellij.compiler.ant.Generator +import com.intellij.openapi.module.ModulePointer +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.packaging.artifacts.ArtifactType +import com.intellij.packaging.elements.AntCopyInstructionCreator +import com.intellij.packaging.elements.ArtifactAntGenerationContext +import com.intellij.packaging.elements.PackagingElementOutputKind +import com.intellij.packaging.elements.PackagingElementResolvingContext +import com.intellij.packaging.impl.ui.DelegatedPackagingElementPresentation +import com.intellij.packaging.impl.ui.ModuleElementPresentation +import com.intellij.packaging.ui.ArtifactEditorContext +import com.intellij.packaging.ui.PackagingElementPresentation +import org.jetbrains.annotations.NonNls +import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes + +class ProductionModuleSourcePackagingElement : ModulePackagingElementBase { + constructor(project: Project) : super(ProductionModuleSourceElementType.ELEMENT_TYPE, project) {} + constructor(project: Project, modulePointer: ModulePointer) : super(ProductionModuleSourceElementType.ELEMENT_TYPE, + project, + modulePointer) + + override fun getSourceRoots(context: PackagingElementResolvingContext): Collection { + val module = findModule(context) ?: return emptyList() + + val rootModel = context.modulesProvider.getRootModel(module) + return rootModel.getSourceRoots(JavaModuleSourceRootTypes.PRODUCTION) + } + + override fun createPresentation(context: ArtifactEditorContext): PackagingElementPresentation { + return DelegatedPackagingElementPresentation( + ModuleElementPresentation(myModulePointer, context, ProductionModuleSourceElementType.ELEMENT_TYPE)) + } + + override fun computeAntInstructions(resolvingContext: PackagingElementResolvingContext, + creator: AntCopyInstructionCreator, + generationContext: ArtifactAntGenerationContext, + artifactType: ArtifactType): List { + return getSourceRoots(resolvingContext).map { + creator.createDirectoryContentCopyInstruction(it.path) + } + } + + override fun getFilesKind(context: PackagingElementResolvingContext) = PackagingElementOutputKind.OTHER + + @NonNls + override fun toString() = "module sources:" + moduleName!! +} + diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/TestModuleOutputElementType.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/TestModuleOutputElementType.java index 3e0700068215..34297f60f87f 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/TestModuleOutputElementType.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/TestModuleOutputElementType.java @@ -15,13 +15,14 @@ */ package com.intellij.packaging.impl.elements; +import com.intellij.icons.AllIcons; import com.intellij.openapi.compiler.CompilerBundle; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModulePointer; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ui.configuration.ModulesProvider; -import com.intellij.util.PlatformIcons; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; import javax.swing.*; @@ -32,7 +33,7 @@ import javax.swing.*; public class TestModuleOutputElementType extends ModuleOutputElementTypeBase { public static final TestModuleOutputElementType ELEMENT_TYPE = new TestModuleOutputElementType(); - public TestModuleOutputElementType() { + private TestModuleOutputElementType() { super("module-test-output", CompilerBundle.message("element.type.name.module.test.output")); } @@ -48,10 +49,21 @@ public class TestModuleOutputElementType extends ModuleOutputElementTypeBase getSourceRoots(PackagingElementResolvingContext context) { @@ -68,6 +63,6 @@ public class TestModuleOutputPackagingElement extends ModuleOutputPackagingEleme @NotNull public PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) { - return new DelegatedPackagingElementPresentation(new ModuleElementPresentation(myModulePointer, context, true)); + return new DelegatedPackagingElementPresentation(new ModuleElementPresentation(myModulePointer, context, TestModuleOutputElementType.ELEMENT_TYPE)); } } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/ui/ModuleElementPresentation.java b/java/compiler/impl/src/com/intellij/packaging/impl/ui/ModuleElementPresentation.java index 0ed75b5d4fce..9378c2827ed1 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/ui/ModuleElementPresentation.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/ui/ModuleElementPresentation.java @@ -16,16 +16,14 @@ package com.intellij.packaging.impl.ui; import com.intellij.ide.projectView.PresentationData; -import com.intellij.openapi.compiler.CompilerBundle; import com.intellij.openapi.module.ModifiableModuleModel; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModulePointer; -import com.intellij.openapi.module.ModuleType; +import com.intellij.packaging.impl.elements.ModuleElementTypeBase; import com.intellij.packaging.ui.ArtifactEditorContext; import com.intellij.packaging.ui.PackagingElementWeights; import com.intellij.packaging.ui.TreeNodePresentation; import com.intellij.ui.SimpleTextAttributes; -import com.intellij.util.PlatformIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,12 +33,14 @@ import org.jetbrains.annotations.Nullable; public class ModuleElementPresentation extends TreeNodePresentation { private final ModulePointer myModulePointer; private final ArtifactEditorContext myContext; - private final boolean myTestOutput; + private final ModuleElementTypeBase myElementType; - public ModuleElementPresentation(@Nullable ModulePointer modulePointer, @NotNull ArtifactEditorContext context, final boolean testOutput) { + public ModuleElementPresentation(@Nullable ModulePointer modulePointer, + @NotNull ArtifactEditorContext context, + @NotNull ModuleElementTypeBase elementType) { myModulePointer = modulePointer; myContext = context; - myTestOutput = testOutput; + myElementType = elementType; } public String getPresentableName() { @@ -65,14 +65,12 @@ public class ModuleElementPresentation extends TreeNodePresentation { } } - public void render(@NotNull PresentationData presentationData, SimpleTextAttributes mainAttributes, SimpleTextAttributes commentAttributes) { + public void render(@NotNull PresentationData presentationData, + SimpleTextAttributes mainAttributes, + SimpleTextAttributes commentAttributes) { final Module module = findModule(); - if (myTestOutput) { - presentationData.setIcon(PlatformIcons.TEST_SOURCE_FOLDER); - } - else if (module != null) { - presentationData.setIcon(ModuleType.get(module).getIcon()); - } + presentationData.setIcon(myElementType.getElementIcon(module)); + String moduleName; if (module != null) { ModifiableModuleModel moduleModel = myContext.getModifiableModuleModel(); @@ -90,8 +88,7 @@ public class ModuleElementPresentation extends TreeNodePresentation { moduleName = ""; } - String text = myTestOutput ? CompilerBundle.message("node.text.0.test.compile.output", moduleName) - : CompilerBundle.message("node.text.0.compile.output", moduleName); + String text = myElementType.getElementText(moduleName); presentationData.addText(text, module != null ? mainAttributes : SimpleTextAttributes.ERROR_ATTRIBUTES); } diff --git a/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerBundle.java b/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerBundle.java index 0d4ac3819ed4..8bf26a6427c9 100644 --- a/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerBundle.java +++ b/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerBundle.java @@ -30,6 +30,7 @@ import java.util.ResourceBundle; */ public class CompilerBundle { + @NotNull public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) { return CommonBundle.message(getBundle(), key, params); } diff --git a/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java b/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java index d6574fa21aa1..16feac71e0f5 100644 --- a/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java +++ b/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java @@ -54,6 +54,9 @@ public abstract class PackagingElementFactory { @NotNull public abstract PackagingElement createModuleOutput(@NotNull Module module); + @NotNull + public abstract PackagingElement createModuleSource(@NotNull Module module); + @NotNull public abstract PackagingElement createTestModuleOutput(@NotNull Module module); diff --git a/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementOutputKind.java b/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementOutputKind.java index 4ba42df83974..08df98dd1533 100644 --- a/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementOutputKind.java +++ b/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementOutputKind.java @@ -15,13 +15,16 @@ */ package com.intellij.packaging.elements; +import org.jetbrains.annotations.NotNull; + /** * @author nik */ public class PackagingElementOutputKind { - public static final PackagingElementOutputKind DIRECTORIES_WITH_CLASSES = new PackagingElementOutputKind(true, false); - public static final PackagingElementOutputKind JAR_FILES = new PackagingElementOutputKind(false, true); - public static final PackagingElementOutputKind OTHER = new PackagingElementOutputKind(false, false); + @NotNull public static final PackagingElementOutputKind DIRECTORIES_WITH_CLASSES = new PackagingElementOutputKind(true, false); + @NotNull public static final PackagingElementOutputKind JAR_FILES = new PackagingElementOutputKind(false, true); + @NotNull public static final PackagingElementOutputKind OTHER = new PackagingElementOutputKind(false, false); + private final boolean myContainsDirectoriesWithClasses; private final boolean myContainsJarFiles; diff --git a/java/compiler/openapi/src/com/intellij/packaging/ui/SourceItemWeights.java b/java/compiler/openapi/src/com/intellij/packaging/ui/SourceItemWeights.java index 70e05f0e1385..c25223af0877 100644 --- a/java/compiler/openapi/src/com/intellij/packaging/ui/SourceItemWeights.java +++ b/java/compiler/openapi/src/com/intellij/packaging/ui/SourceItemWeights.java @@ -24,6 +24,7 @@ public class SourceItemWeights { public static final int MODULE_GROUP_WEIGHT = 100; public static final int MODULE_WEIGHT = 50; public static final int MODULE_OUTPUT_WEIGHT = 30; + public static final int MODULE_SOURCE_WEIGHT = 25; public static final int LIBRARY_WEIGHT = 10; private SourceItemWeights() { diff --git a/java/compiler/tests/com/intellij/compiler/artifacts/TestPackagingElementBuilder.java b/java/compiler/tests/com/intellij/compiler/artifacts/TestPackagingElementBuilder.java index 3c1f63769c04..507d9ff4ab89 100644 --- a/java/compiler/tests/com/intellij/compiler/artifacts/TestPackagingElementBuilder.java +++ b/java/compiler/tests/com/intellij/compiler/artifacts/TestPackagingElementBuilder.java @@ -71,6 +71,11 @@ public class TestPackagingElementBuilder { return this; } + public TestPackagingElementBuilder moduleSource(Module module) { + myElement.addOrFindChild(getFactory().createModuleSource(module)); + return this; + } + public TestPackagingElementBuilder lib(Library library) { myElement.addOrFindChildren(getFactory().createLibraryElements(library)); return this; diff --git a/java/compiler/tests/com/intellij/compiler/artifacts/UpdateArtifactsAfterRenameTest.java b/java/compiler/tests/com/intellij/compiler/artifacts/UpdateArtifactsAfterRenameTest.java index b4e6d38055a5..5193e0ce8526 100644 --- a/java/compiler/tests/com/intellij/compiler/artifacts/UpdateArtifactsAfterRenameTest.java +++ b/java/compiler/tests/com/intellij/compiler/artifacts/UpdateArtifactsAfterRenameTest.java @@ -69,10 +69,11 @@ public class UpdateArtifactsAfterRenameTest extends PackagingElementsTestCase { Module res = moduleManager.newModule(getProjectBasePath() + "/myModule.iml", StdModuleTypes.JAVA.getId()); return res; }); - final Artifact artifact = addArtifact(root().module(module)); + final Artifact artifact = addArtifact(root().module(module).moduleSource(module)); assertLayout(artifact, "\n" + - " module:myModule"); + " module:myModule\n" + + " module sources:myModule"); WriteAction.runAndWait(() -> { final ModifiableModuleModel model = moduleManager.getModifiableModel(); model.renameModule(module, "newName"); @@ -80,12 +81,14 @@ public class UpdateArtifactsAfterRenameTest extends PackagingElementsTestCase { }); assertLayout(artifact, "\n" + - " module:newName"); + " module:newName\n" + + " module sources:newName"); moduleManager.disposeModule(module); assertLayout(artifact, "\n" + - " module:newName"); + " module:newName\n" + + " module sources:newName"); } private void moveFile(final VirtualFile file, final VirtualFile newParent) { diff --git a/java/compiler/tests/com/intellij/compiler/artifacts/ui/AddNewElementActionTest.java b/java/compiler/tests/com/intellij/compiler/artifacts/ui/AddNewElementActionTest.java index ecd66de0d537..ae70473952c1 100644 --- a/java/compiler/tests/com/intellij/compiler/artifacts/ui/AddNewElementActionTest.java +++ b/java/compiler/tests/com/intellij/compiler/artifacts/ui/AddNewElementActionTest.java @@ -2,6 +2,7 @@ package com.intellij.compiler.artifacts.ui; import com.intellij.packaging.artifacts.Artifact; import com.intellij.packaging.impl.elements.ProductionModuleOutputElementType; +import com.intellij.packaging.impl.elements.ProductionModuleSourceElementType; /** * @author nik @@ -26,6 +27,16 @@ public class AddNewElementActionTest extends ArtifactEditorTestCase { " module:mod"); } + public void testAddSourcesToDirectory() { + addModule(); + createEditor(addArtifact(root().dir("dir"))); + selectNode("dir"); + myArtifactEditor.addNewPackagingElement(ProductionModuleSourceElementType.ELEMENT_TYPE); + assertLayout("\n" + + " dir/\n" + + " module sources:mod"); + } + public void testAddToDirectoryInIncludedArtifact() { addModule(); Artifact included = addArtifact("included", root().dir("dir")); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProjectStructureElement.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProjectStructureElement.java index 6403d88dc0e8..7adc54de20a2 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProjectStructureElement.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProjectStructureElement.java @@ -32,7 +32,7 @@ import com.intellij.packaging.impl.artifacts.PackagingElementProcessor; import com.intellij.packaging.impl.elements.ArtifactPackagingElement; import com.intellij.packaging.impl.elements.FacetBasedPackagingElement; import com.intellij.packaging.impl.elements.LibraryPackagingElement; -import com.intellij.packaging.impl.elements.ModuleOutputPackagingElement; +import com.intellij.packaging.impl.elements.ModulePackagingElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -102,8 +102,8 @@ public class ArtifactProjectStructureElement extends ProjectStructureElement { public static ProjectStructureElement getProjectStructureElementFor(PackagingElement packagingElement, final StructureConfigurableContext context, final ArtifactsStructureConfigurableContext artifactsStructureContext) { - if (packagingElement instanceof ModuleOutputPackagingElement) { - final Module module = ((ModuleOutputPackagingElement)packagingElement).findModule(artifactsStructureContext); + if (packagingElement instanceof ModulePackagingElement) { + final Module module = ((ModulePackagingElement)packagingElement).findModule(artifactsStructureContext); if (module != null) { return new ModuleProjectStructureElement(context, module); } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModuleOutputSourceItem.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModuleOutputSourceItem.java index 90bde421b31d..8904468d1877 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModuleOutputSourceItem.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModuleOutputSourceItem.java @@ -20,6 +20,7 @@ import com.intellij.openapi.module.ModulePointer; import com.intellij.openapi.module.ModulePointerManager; import com.intellij.packaging.elements.PackagingElement; import com.intellij.packaging.elements.PackagingElementOutputKind; +import com.intellij.packaging.impl.elements.ProductionModuleOutputElementType; import com.intellij.packaging.impl.elements.ProductionModuleOutputPackagingElement; import com.intellij.packaging.impl.ui.ModuleElementPresentation; import com.intellij.packaging.ui.*; @@ -54,7 +55,7 @@ public class ModuleOutputSourceItem extends PackagingSourceItem { @Override public SourceItemPresentation createPresentation(@NotNull ArtifactEditorContext context) { final ModulePointer modulePointer = ModulePointerManager.getInstance(context.getProject()).create(myModule); - return new DelegatedSourceItemPresentation(new ModuleElementPresentation(modulePointer, context, false)) { + return new DelegatedSourceItemPresentation(new ModuleElementPresentation(modulePointer, context, ProductionModuleOutputElementType.ELEMENT_TYPE)) { @Override public int getWeight() { return SourceItemWeights.MODULE_OUTPUT_WEIGHT; diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModulesAndLibrariesSourceItemsProvider.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModulesAndLibrariesSourceItemsProvider.java index fa193aa7bb94..9608ee2bcc59 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModulesAndLibrariesSourceItemsProvider.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModulesAndLibrariesSourceItemsProvider.java @@ -23,8 +23,7 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.packaging.artifacts.Artifact; import com.intellij.packaging.impl.artifacts.ArtifactUtil; -import com.intellij.packaging.impl.elements.PackagingElementFactoryImpl; -import com.intellij.packaging.impl.elements.ProductionModuleOutputElementType; +import com.intellij.packaging.impl.elements.*; import com.intellij.packaging.ui.ArtifactEditorContext; import com.intellij.packaging.ui.PackagingSourceItem; import com.intellij.packaging.ui.PackagingSourceItemsProvider; @@ -49,17 +48,22 @@ public class ModulesAndLibrariesSourceItemsProvider extends PackagingSourceItems return createModuleItems(editorContext, ((ModuleGroupItem)parent).getPath()); } else if (parent instanceof ModuleSourceItemGroup) { - return createClasspathItems(editorContext, artifact, ((ModuleSourceItemGroup)parent).getModule()); + return createAvailableItems(editorContext, artifact, ((ModuleSourceItemGroup)parent).getModule()); } return Collections.emptyList(); } @NotNull - private static Collection createClasspathItems(@NotNull ArtifactEditorContext editorContext, + private static Collection createAvailableItems(@NotNull ArtifactEditorContext editorContext, @NotNull Artifact artifact, @NotNull Module module) { final List items = new ArrayList<>(); - final ModuleRootModel rootModel = editorContext.getModulesProvider().getRootModel(module); + + for (Module toAdd : getAvailableModules(editorContext, artifact, ProductionModuleOutputElementType.ELEMENT_TYPE, module)) { + items.add(new ModuleOutputSourceItem(toAdd)); + } + List libraries = new ArrayList<>(); + final ModuleRootModel rootModel = editorContext.getModulesProvider().getRootModel(module); for (OrderEntry orderEntry : rootModel.getOrderEntries()) { if (orderEntry instanceof LibraryOrderEntry) { final LibraryOrderEntry libraryEntry = (LibraryOrderEntry)orderEntry; @@ -71,10 +75,6 @@ public class ModulesAndLibrariesSourceItemsProvider extends PackagingSourceItems } } - for (Module toAdd : getNotAddedModules(editorContext, artifact, module)) { - items.add(new ModuleOutputSourceItem(toAdd)); - } - for (Library library : getNotAddedLibraries(editorContext, artifact, libraries)) { items.add(new LibrarySourceItem(library)); } @@ -102,11 +102,19 @@ public class ModulesAndLibrariesSourceItemsProvider extends PackagingSourceItems } @NotNull - private static List getNotAddedModules(@NotNull final ArtifactEditorContext context, @NotNull Artifact artifact, - final Module... allModules) { - final Set modules = new HashSet<>(Arrays.asList(allModules)); - ArtifactUtil.processPackagingElements(artifact, ProductionModuleOutputElementType.ELEMENT_TYPE, moduleOutputPackagingElement -> { - modules.remove(moduleOutputPackagingElement.findModule(context)); + private static List getAvailableModules(@NotNull final ArtifactEditorContext context, + @NotNull Artifact artifact, + @NotNull ModuleElementTypeBase elementType, + final Module... allModules) { + final Set modules = new HashSet<>(); + for (Module module : allModules) { + if (elementType.isSuitableModule(context.getModulesProvider(), module)) { + modules.add(module); + } + } + + ArtifactUtil.processPackagingElements(artifact, elementType, moduleElement -> { + modules.remove(moduleElement.findModule(context)); return true; }, context, true); return new ArrayList<>(modules); 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 b90a80dba1a9..885d1802d71c 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 @@ -29,9 +29,10 @@ import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactInstructions import org.jetbrains.jps.incremental.artifacts.instructions.CopyToDirectoryInstructionCreator; 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 org.jetbrains.jps.model.java.*; import org.jetbrains.jps.model.module.JpsModule; +import org.jetbrains.jps.model.module.JpsModuleSourceRoot; +import org.jetbrains.jps.model.module.JpsTypedModuleSourceRoot; import org.jetbrains.jps.service.JpsServiceManager; import org.jetbrains.jps.util.JpsPathUtil; @@ -62,6 +63,7 @@ public class LayoutElementBuildersRegistry { LayoutElementBuilderService[] standardBuilders = { new RootElementBuilder(), new DirectoryElementBuilder(), new ArchiveElementBuilder(), new DirectoryCopyElementBuilder(), new FileCopyElementBuilder(), new ExtractedDirectoryElementBuilder(), new ModuleOutputElementBuilder(), + new ModuleSourceElementBuilder(), new ModuleTestOutputElementBuilder(), new ComplexElementBuilder(), new ArtifactOutputElementBuilder() }; for (LayoutElementBuilderService builder : standardBuilders) { @@ -124,6 +126,24 @@ public class LayoutElementBuildersRegistry { } } + private static void generateModuleSourceInstructions(@NotNull List roots, + @NotNull ArtifactCompilerInstructionCreator creator, + @NotNull JpsPackagingElement contextElement) { + for (JpsModuleSourceRoot root : roots) { + File source = root.getFile(); + ArtifactCompilerInstructionCreator target; + JavaSourceRootProperties javaProperties = root.getProperties(JavaModuleSourceRootTypes.SOURCES); + if (javaProperties != null) { + String prefix = javaProperties.getPackagePrefix().replace('.', '/'); + target = creator.subFolderByRelativePath(prefix); + } else { + target = creator; + } + + target.addDirectoryCopyInstructions(source, null, target.getInstructionsBuilder().createCopyingHandler(source, contextElement, target)); + } + } + private static void generateModuleOutputInstructions(@Nullable String outputUrl, @NotNull ArtifactCompilerInstructionCreator creator, @NotNull JpsPackagingElement contextElement) { @@ -262,6 +282,28 @@ public class LayoutElementBuildersRegistry { } } + private static class ModuleSourceElementBuilder extends LayoutElementBuilderService { + public ModuleSourceElementBuilder() { + super(JpsProductionModuleSourcePackagingElement.class); + } + + @Override + public void generateInstructions(JpsProductionModuleSourcePackagingElement element, + ArtifactCompilerInstructionCreator instructionCreator, + ArtifactInstructionsBuilderContext builderContext) { + JpsModule module = element.getModuleReference().resolve(); + if (module != null) { + generateModuleSourceInstructions(module.getSourceRoots(), instructionCreator, element); + } + } + + @Override + public Collection> getDependencies(@NotNull JpsProductionModuleSourcePackagingElement element, + TargetOutputIndex outputIndex) { + return Collections.emptyList(); + } + } + private static class ModuleTestOutputElementBuilder extends LayoutElementBuilderService { public ModuleTestOutputElementBuilder() { super(JpsTestModuleOutputPackagingElement.class); diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.kt b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.kt index e257f6e29510..999874866632 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.kt +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.kt @@ -20,6 +20,7 @@ import com.intellij.util.PathUtil import com.intellij.util.io.directoryContent import org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.archive import org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.root +import org.jetbrains.jps.model.java.JavaSourceRootType import org.jetbrains.jps.model.java.JpsJavaExtensionService import org.jetbrains.jps.util.JpsPathUtil import java.io.BufferedOutputStream @@ -171,6 +172,49 @@ class ArtifactBuilderTest : ArtifactBuilderTestCase() { assertOutput(artifact, directoryContent { file("A.class") }) } + fun testModuleSources() { + val file = createFile("src/A.java", "class A{}") + val m = addModule("m", PathUtil.getParentPath(file)) + val a = addArtifact(root().moduleSource(m)) + buildAll() + assertOutput(a, directoryContent { + file("A.java") + }) + + val b = createFile("src/B.java", "class B{}") + + buildAll() + assertOutput(a, directoryContent { + file("A.java") + file("B.java") + }) + + delete(b) + buildAll() + assertOutput(a, directoryContent { + file("A.java") + }) + } + + fun testModuleSourcesWithPackagePrefix() { + val file = createFile("src/A.java", "class A{}") + val m = addModule("m", PathUtil.getParentPath(file)) + val sourceRoot = assertOneElement(m.sourceRoots) + val typed = sourceRoot.asTyped(JavaSourceRootType.SOURCE) + assertNotNull(typed) + typed!!.properties.packagePrefix = "org.foo" + + val a = addArtifact(root().moduleSource(m)) + buildAll() + assertOutput(a, directoryContent { + dir("org") { + dir("foo") { + file("A.java") + } + } + }) + } + fun testCopyResourcesFromModuleOutput() { val file = createFile("src/a.xml", "") JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(myProject).addResourcePattern("*.xml") 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 12d1fc9f39f4..a633700a8e6f 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 @@ -82,6 +82,10 @@ public class LayoutElementTestUtil { return element(JpsJavaExtensionService.getInstance().createProductionModuleOutput(module.createReference())); } + public LayoutElementCreator moduleSource(JpsModule module) { + return element(JpsJavaExtensionService.getInstance().createProductionModuleSource(module.createReference())); + } + public LayoutElementCreator element(JpsPackagingElement element) { myElement.addChild(element); return this; 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 7bcd5451ef74..192f8d8b88dd 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 @@ -41,6 +41,9 @@ public abstract class JpsJavaExtensionService { @NotNull public abstract JpsProductionModuleOutputPackagingElement createProductionModuleOutput(@NotNull JpsModuleReference moduleReference); + @NotNull + public abstract JpsProductionModuleSourcePackagingElement createProductionModuleSource(@NotNull JpsModuleReference moduleReference); + @NotNull public abstract JpsTestModuleOutputPackagingElement createTestModuleOutput(@NotNull JpsModuleReference moduleReference); diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JpsProductionModuleSourcePackagingElement.java b/jps/model-api/src/org/jetbrains/jps/model/java/JpsProductionModuleSourcePackagingElement.java new file mode 100644 index 000000000000..548980f8ab46 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/java/JpsProductionModuleSourcePackagingElement.java @@ -0,0 +1,11 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.jps.model.java; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; +import org.jetbrains.jps.model.module.JpsModuleReference; + +public interface JpsProductionModuleSourcePackagingElement extends JpsPackagingElement { + @NotNull + JpsModuleReference getModuleReference(); +} 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 ba9e20de5b20..aff6c299cf3e 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 @@ -206,6 +206,12 @@ public class JpsJavaExtensionServiceImpl extends JpsJavaExtensionService { return new JpsProductionModuleOutputPackagingElementImpl(moduleReference); } + @Override + @NotNull + public JpsProductionModuleSourcePackagingElement createProductionModuleSource(@NotNull JpsModuleReference moduleReference) { + return new JpsProductionModuleSourcePackagingElementImpl(moduleReference); + } + @Override @NotNull public JpsTestModuleOutputPackagingElement createTestModuleOutput(@NotNull JpsModuleReference moduleReference) { diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsProductionModuleSourcePackagingElementImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsProductionModuleSourcePackagingElementImpl.java new file mode 100644 index 000000000000..676bf57b043a --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsProductionModuleSourcePackagingElementImpl.java @@ -0,0 +1,37 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.jps.model.java.impl; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.JpsElementChildRole; +import org.jetbrains.jps.model.ex.JpsCompositeElementBase; +import org.jetbrains.jps.model.ex.JpsElementChildRoleBase; +import org.jetbrains.jps.model.java.JpsProductionModuleSourcePackagingElement; +import org.jetbrains.jps.model.module.JpsModuleReference; + +public class JpsProductionModuleSourcePackagingElementImpl extends JpsCompositeElementBase + implements JpsProductionModuleSourcePackagingElement { + + private static final JpsElementChildRole + MODULE_REFERENCE_CHILD_ROLE = JpsElementChildRoleBase.create("module reference"); + + public JpsProductionModuleSourcePackagingElementImpl(JpsModuleReference moduleReference) { + myContainer.setChild(MODULE_REFERENCE_CHILD_ROLE, moduleReference); + } + + @Override + @NotNull + public JpsModuleReference getModuleReference() { + return myContainer.getChild(MODULE_REFERENCE_CHILD_ROLE); + } + + private JpsProductionModuleSourcePackagingElementImpl(JpsProductionModuleSourcePackagingElementImpl original) { + super(original); + } + + @NotNull + @Override + public JpsProductionModuleSourcePackagingElementImpl createCopy() { + return new JpsProductionModuleSourcePackagingElementImpl(this); + } + +} diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelSerializerExtension.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelSerializerExtension.java index 56d9ce0ae4af..14bcec66fd8a 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelSerializerExtension.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelSerializerExtension.java @@ -163,7 +163,9 @@ public class JpsJavaModelSerializerExtension extends JpsModelSerializerExtension @NotNull @Override public List> getPackagingElementSerializers() { - return Arrays.asList(new JpsModuleOutputPackagingElementSerializer(), new JpsTestModuleOutputPackagingElementSerializer()); + return Arrays.asList(new JpsModuleOutputPackagingElementSerializer(), + new JpsTestModuleOutputPackagingElementSerializer(), + new JpsModuleSourcePackagingElementSerializer()); } @NotNull @@ -281,6 +283,24 @@ public class JpsJavaModelSerializerExtension extends JpsModelSerializerExtension } } + private static class JpsModuleSourcePackagingElementSerializer + extends JpsPackagingElementSerializer { + private JpsModuleSourcePackagingElementSerializer() { + super("module-source", JpsProductionModuleSourcePackagingElement.class); + } + + @Override + public JpsProductionModuleSourcePackagingElement load(Element element) { + JpsModuleReference reference = JpsElementFactory.getInstance().createModuleReference(element.getAttributeValue("name")); + return getService().createProductionModuleSource(reference); + } + + @Override + public void save(JpsProductionModuleSourcePackagingElement element, Element tag) { + tag.setAttribute("name", element.getModuleReference().getModuleName()); + } + } + private static class JpsTestModuleOutputPackagingElementSerializer extends JpsPackagingElementSerializer { private JpsTestModuleOutputPackagingElementSerializer() { super("module-test-output", JpsTestModuleOutputPackagingElement.class); diff --git a/resources-en/src/messages/CompilerBundle.properties b/resources-en/src/messages/CompilerBundle.properties index d70a36e6f34b..fec3275d4f29 100644 --- a/resources-en/src/messages/CompilerBundle.properties +++ b/resources-en/src/messages/CompilerBundle.properties @@ -121,6 +121,8 @@ element.type.name.library.files=Library Files node.text.0.compile.output=''{0}'' compile output node.text.0.test.compile.output=''{0}'' test compile output node.text.0.with.dependencies=''{0}'' with dependencies +node.text.0.module.sources=''{0}'' sources +element.type.name.module.source=Module Sources element.type.name.module.output=Module Output element.type.name.module.test.output=Module Test Output element.type.name.directory=Directory