From 7f43853129db9ab8ad06ecd0cb7198719ae78f2c Mon Sep 17 00:00:00 2001 From: nik Date: Mon, 16 Feb 2015 18:03:37 +0300 Subject: [PATCH] resource java roots: added 'for generated resources' and 'relative output path' properties --- .../JavaResourceRootEditHandlerBase.java | 117 +++++++++++++++++- .../openapi/roots/JavaProjectRootsUtil.java | 4 +- .../jps/incremental/ResourcesTarget.java | 10 +- .../jps/builders/rebuild/ModuleRebuildTest.kt | 19 +++ .../java/JavaResourceRootProperties.java | 71 +++++++++++ .../jps/model/java/JavaResourceRootType.java | 11 +- .../model/java/JpsJavaExtensionService.java | 3 + .../impl/JpsJavaExtensionServiceImpl.java | 6 + .../java/JpsJavaModelSerializerExtension.java | 34 ++++- .../testData/resourceRoots/resourceRoots.iml | 15 +++ .../testData/resourceRoots/resourceRoots.ipr | 12 ++ .../JpsProjectSerializationTest.java | 26 +++- .../ContentEntryTreeCellRenderer.java | 14 ++- .../openapi/roots/impl/SourceFolderImpl.java | 33 +++-- 14 files changed, 338 insertions(+), 37 deletions(-) create mode 100644 jps/model-api/src/org/jetbrains/jps/model/java/JavaResourceRootProperties.java create mode 100644 jps/model-serialization/testData/resourceRoots/resourceRoots.iml create mode 100644 jps/model-serialization/testData/resourceRoots/resourceRoots.ipr diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaResourceRootEditHandlerBase.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaResourceRootEditHandlerBase.java index ba7778da6397..ca72f1376e55 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaResourceRootEditHandlerBase.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaResourceRootEditHandlerBase.java @@ -15,18 +15,30 @@ */ package com.intellij.openapi.roots.ui.configuration; +import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.project.ProjectBundle; +import com.intellij.openapi.roots.SourceFolder; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.roots.IconActionComponent; +import com.intellij.util.ui.FormBuilder; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jps.model.JpsDummyElement; +import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; +import org.jetbrains.jps.model.java.JavaResourceRootProperties; import org.jetbrains.jps.model.module.JpsModuleSourceRootType; import javax.swing.*; +import java.awt.*; /** * @author nik */ -public abstract class JavaResourceRootEditHandlerBase extends ModuleSourceRootEditHandler { - protected JavaResourceRootEditHandlerBase(JpsModuleSourceRootType rootType) { +public abstract class JavaResourceRootEditHandlerBase extends ModuleSourceRootEditHandler { + public JavaResourceRootEditHandlerBase(JpsModuleSourceRootType rootType) { super(rootType); } @@ -41,4 +53,103 @@ public abstract class JavaResourceRootEditHandlerBase extends ModuleSourceRootEd public CustomShortcutSet getMarkRootShortcutSet() { return null; } + + @NotNull + @Override + public Icon getRootIcon(@NotNull JavaResourceRootProperties properties) { + return properties.isForGeneratedSources() ? getGeneratedRootIcon() : getRootIcon(); + } + + @NotNull + protected Icon getGeneratedRootIcon() { + return getRootIcon(); + } + + @Nullable + @Override + public String getPropertiesString(@NotNull JavaResourceRootProperties properties) { + StringBuilder buffer = new StringBuilder(); + if (properties.isForGeneratedSources()) { + buffer.append(" [generated]"); + } + String relativeOutputPath = properties.getRelativeOutputPath(); + if (!relativeOutputPath.isEmpty()) { + buffer.append(" (").append(relativeOutputPath).append(")"); + } + return buffer.length() > 0 ? buffer.toString() : null; + } + + @Nullable + @Override + public JComponent createPropertiesEditor(@NotNull final SourceFolder folder, + @NotNull final JComponent parentComponent, + @NotNull final ContentRootPanel.ActionCallback callback) { + final IconActionComponent iconComponent = new IconActionComponent(AllIcons.Modules.SetPackagePrefix, + AllIcons.Modules.SetPackagePrefixRollover, + ProjectBundle.message("module.paths.edit.properties.tooltip"), + new Runnable() { + @Override + public void run() { + JavaResourceRootProperties properties = folder.getJpsElement().getProperties( JavaModuleSourceRootTypes.RESOURCES); + assert properties != null; + ResourceRootPropertiesDialog + dialog = new ResourceRootPropertiesDialog(parentComponent, properties); + if (dialog.showAndGet()) { + callback.onSourceRootPropertiesChanged(folder); + } + } + }); + final JPanel panel = new JPanel(new BorderLayout()); + panel.setOpaque(false); + panel.add(iconComponent, BorderLayout.CENTER); + panel.add(Box.createHorizontalStrut(3), BorderLayout.EAST); + return panel; + } + + private static class ResourceRootPropertiesDialog extends DialogWrapper { + private final JTextField myRelativeOutputPathField; + private final JCheckBox myIsGeneratedCheckBox; + private final JPanel myMainPanel; + @NotNull private final JavaResourceRootProperties myProperties; + + private ResourceRootPropertiesDialog(@NotNull JComponent parentComponent, @NotNull JavaResourceRootProperties properties) { + super(parentComponent, true); + myProperties = properties; + setTitle(ProjectBundle.message("module.paths.edit.properties.title")); + myRelativeOutputPathField = new JTextField(); + myIsGeneratedCheckBox = new JCheckBox(UIUtil.replaceMnemonicAmpersand("For &generated resources")); + myMainPanel = FormBuilder.createFormBuilder() + .addLabeledComponent("Relative output &path:", myRelativeOutputPathField) + .addComponent(myIsGeneratedCheckBox) + .getPanel(); + myRelativeOutputPathField.setText(myProperties.getRelativeOutputPath()); + myRelativeOutputPathField.setColumns(25); + myIsGeneratedCheckBox.setSelected(myProperties.isForGeneratedSources()); + init(); + } + + @Nullable + @Override + public JComponent getPreferredFocusedComponent() { + return myRelativeOutputPathField; + } + + @Override + protected void doOKAction() { + myProperties.setRelativeOutputPath(normalizePath(myRelativeOutputPathField.getText())); + myProperties.setForGeneratedSources(myIsGeneratedCheckBox.isSelected()); + super.doOKAction(); + } + + @NotNull + private static String normalizePath(String path) { + return StringUtil.trimEnd(StringUtil.trimStart(FileUtil.toSystemIndependentName(path.trim()), "/"), "/"); + } + + @Nullable + @Override + protected JComponent createCenterPanel() { + return myMainPanel; + } + } } diff --git a/java/java-analysis-impl/src/com/intellij/openapi/roots/JavaProjectRootsUtil.java b/java/java-analysis-impl/src/com/intellij/openapi/roots/JavaProjectRootsUtil.java index f7666eb21ffb..767bc5cc948d 100644 --- a/java/java-analysis-impl/src/com/intellij/openapi/roots/JavaProjectRootsUtil.java +++ b/java/java-analysis-impl/src/com/intellij/openapi/roots/JavaProjectRootsUtil.java @@ -12,6 +12,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; +import org.jetbrains.jps.model.java.JavaResourceRootProperties; import org.jetbrains.jps.model.java.JavaSourceRootProperties; import java.util.ArrayList; @@ -51,7 +52,8 @@ public class JavaProjectRootsUtil { private static boolean isForGeneratedSources(SourceFolder sourceFolder) { JavaSourceRootProperties properties = sourceFolder.getJpsElement().getProperties(JavaModuleSourceRootTypes.SOURCES); - return properties != null && properties.isForGeneratedSources(); + JavaResourceRootProperties resourceProperties = sourceFolder.getJpsElement().getProperties(JavaModuleSourceRootTypes.RESOURCES); + return properties != null && properties.isForGeneratedSources() || resourceProperties != null && resourceProperties.isForGeneratedSources(); } public static boolean isInGeneratedCode(@NotNull VirtualFile file, @NotNull Project project) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java index 21c329149400..cb74bf7cfd78 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java @@ -32,10 +32,7 @@ import org.jetbrains.jps.cmdline.ProjectDescriptor; import org.jetbrains.jps.indices.IgnoredFileIndex; import org.jetbrains.jps.indices.ModuleExcludeIndex; import org.jetbrains.jps.model.JpsModel; -import org.jetbrains.jps.model.java.JavaResourceRootType; -import org.jetbrains.jps.model.java.JavaSourceRootProperties; -import org.jetbrains.jps.model.java.JavaSourceRootType; -import org.jetbrains.jps.model.java.JpsJavaExtensionService; +import org.jetbrains.jps.model.java.*; import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.model.module.JpsModuleSourceRoot; import org.jetbrains.jps.model.module.JpsTypedModuleSourceRoot; @@ -101,10 +98,11 @@ public final class ResourcesTarget extends JVMModuleBuildTarget root : myModule.getSourceRoots(resourceType)) { if (!isExcludedFromCompilation(excludedRootProviders, root)) { File rootFile = root.getFile(); - roots.add(new ResourceRootDescriptor(rootFile, this, "", computeRootExcludes(rootFile, index))); + String relativeOutputPath = root.getProperties().getRelativeOutputPath(); + roots.add(new ResourceRootDescriptor(rootFile, this, relativeOutputPath.replace('/', '.'), computeRootExcludes(rootFile, index))); } } diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.kt b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.kt index 09e72b77cf2a..4c8e1cd13216 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.kt +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.kt @@ -14,6 +14,12 @@ * limitations under the License. */ package org.jetbrains.jps.builders.rebuild + +import org.jetbrains.jps.util.JpsPathUtil +import com.intellij.util.PathUtil +import org.jetbrains.jps.model.java.JavaResourceRootType +import org.jetbrains.jps.model.java.JpsJavaExtensionService + /** * @author nik */ @@ -71,4 +77,17 @@ public class ModuleRebuildTest: JpsRebuildTestCase() { } }) } + + fun testResourceRootWithRelativeOutputPath() { + val m = addModule("m") + val res = PathUtil.getParentPath(createFile("res/a.txt", "42")) + val url = JpsPathUtil.pathToUrl(res) + m.addSourceRoot(url, JavaResourceRootType.RESOURCE, JpsJavaExtensionService.getInstance().createResourceRootProperties("foo", false)) + rebuild() + assertOutput(getAbsolutePath("out/production/m"), fs { + dir("foo") { + file("a.txt", "42") + } + }) + } } diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JavaResourceRootProperties.java b/jps/model-api/src/org/jetbrains/jps/model/java/JavaResourceRootProperties.java new file mode 100644 index 000000000000..838e2d81a1ac --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/java/JavaResourceRootProperties.java @@ -0,0 +1,71 @@ +/* + * Copyright 2000-2015 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.jps.model.java; + +import com.intellij.openapi.util.Comparing; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.ex.JpsElementBase; + +/** + * @author nik + */ +public class JavaResourceRootProperties extends JpsElementBase { + private String myRelativeOutputPath = ""; + private boolean myForGeneratedSources; + + public JavaResourceRootProperties(@NotNull String relativeOutputPath, boolean forGeneratedSources) { + myRelativeOutputPath = relativeOutputPath; + myForGeneratedSources = forGeneratedSources; + } + + /** + * @return relative path to the target directory under the module output directory for resource files from this root + */ + @NotNull + public String getRelativeOutputPath() { + return myRelativeOutputPath; + } + + @NotNull + @Override + public JavaResourceRootProperties createCopy() { + return new JavaResourceRootProperties(myRelativeOutputPath, myForGeneratedSources); + } + + public boolean isForGeneratedSources() { + return myForGeneratedSources; + } + + public void setRelativeOutputPath(@NotNull String relativeOutputPath) { + if (!Comparing.equal(myRelativeOutputPath, relativeOutputPath)) { + myRelativeOutputPath = relativeOutputPath; + fireElementChanged(); + } + } + + public void setForGeneratedSources(boolean forGeneratedSources) { + if (myForGeneratedSources != forGeneratedSources) { + myForGeneratedSources = forGeneratedSources; + fireElementChanged(); + } + } + + @Override + public void applyChanges(@NotNull JavaResourceRootProperties modified) { + setRelativeOutputPath(modified.myRelativeOutputPath); + setForGeneratedSources(modified.myForGeneratedSources); + } +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JavaResourceRootType.java b/jps/model-api/src/org/jetbrains/jps/model/java/JavaResourceRootType.java index 33adf96ebf1f..d3e122aa957d 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/java/JavaResourceRootType.java +++ b/jps/model-api/src/org/jetbrains/jps/model/java/JavaResourceRootType.java @@ -16,15 +16,14 @@ package org.jetbrains.jps.model.java; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.model.JpsDummyElement; -import org.jetbrains.jps.model.JpsElementFactory; -import org.jetbrains.jps.model.ex.JpsElementTypeWithDummyProperties; +import org.jetbrains.jps.model.ex.JpsElementTypeBase; import org.jetbrains.jps.model.module.JpsModuleSourceRootType; /** * @author nik */ -public class JavaResourceRootType extends JpsElementTypeWithDummyProperties implements JpsModuleSourceRootType { +public class JavaResourceRootType extends JpsElementTypeBase implements + JpsModuleSourceRootType { public static final JavaResourceRootType RESOURCE = new JavaResourceRootType(); public static final JavaResourceRootType TEST_RESOURCE = new JavaResourceRootType(); @@ -33,7 +32,7 @@ public class JavaResourceRootType extends JpsElementTypeWithDummyProperties impl @NotNull @Override - public JpsDummyElement createDefaultProperties() { - return JpsElementFactory.getInstance().createDummyElement(); + public JavaResourceRootProperties createDefaultProperties() { + return JpsJavaExtensionService.getInstance().createResourceRootProperties("", false); } } 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 bcd5eeff098b..5c5d42e4a6c2 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 @@ -121,4 +121,7 @@ public abstract class JpsJavaExtensionService { @NotNull public abstract JavaSourceRootProperties createSourceRootProperties(@NotNull String packagePrefix); + + @NotNull + public abstract JavaResourceRootProperties createResourceRootProperties(@NotNull String relativeOutputPath, boolean forGeneratedResource); } 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 40179134c921..5ace6adc46b5 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 @@ -188,6 +188,12 @@ public class JpsJavaExtensionServiceImpl extends JpsJavaExtensionService { return createSourceRootProperties(packagePrefix, false); } + @NotNull + @Override + public JavaResourceRootProperties createResourceRootProperties(@NotNull String relativeOutputPath, boolean forGeneratedResource) { + return new JavaResourceRootProperties(relativeOutputPath, forGeneratedResource); + } + @Override @NotNull public JpsProductionModuleOutputPackagingElement createProductionModuleOutput(@NotNull JpsModuleReference moduleReference) { 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 22188be46e2d..3cb6f8478239 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 @@ -19,7 +19,9 @@ import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.text.StringUtil; import org.jdom.Element; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.model.*; +import org.jetbrains.jps.model.JpsElementFactory; +import org.jetbrains.jps.model.JpsProject; +import org.jetbrains.jps.model.JpsUrlList; import org.jetbrains.jps.model.java.*; import org.jetbrains.jps.model.library.JpsOrderRootType; import org.jetbrains.jps.model.module.JpsDependencyElement; @@ -32,7 +34,6 @@ import org.jetbrains.jps.model.serialization.artifact.JpsPackagingElementSeriali import org.jetbrains.jps.model.serialization.java.compiler.*; import org.jetbrains.jps.model.serialization.library.JpsLibraryRootTypeSerializer; import org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer; -import org.jetbrains.jps.model.serialization.module.JpsModuleSourceRootDummyPropertiesSerializer; import org.jetbrains.jps.model.serialization.module.JpsModuleSourceRootPropertiesSerializer; import java.util.Arrays; @@ -56,6 +57,7 @@ public class JpsJavaModelSerializerExtension extends JpsModelSerializerExtension private static final String JAVADOC_PATHS_TAG = "javadoc-paths"; private static final String MODULE_LANGUAGE_LEVEL_ATTRIBUTE = "LANGUAGE_LEVEL"; public static final String ROOT_TAG = "root"; + private static final String RELATIVE_OUTPUT_PATH_ATTRIBUTE = "relativeOutputPath"; private static final String IS_GENERATED_ATTRIBUTE = "generated"; public static final JavaSourceRootPropertiesSerializer JAVA_SOURCE_ROOT_PROPERTIES_SERIALIZER = new JavaSourceRootPropertiesSerializer(JavaSourceRootType.SOURCE, JpsModuleRootModelSerializer.JAVA_SOURCE_ROOT_TYPE_ID); @@ -88,8 +90,8 @@ public class JpsJavaModelSerializerExtension extends JpsModelSerializerExtension public List> getModuleSourceRootPropertiesSerializers() { return Arrays.asList(JAVA_SOURCE_ROOT_PROPERTIES_SERIALIZER, new JavaSourceRootPropertiesSerializer(JavaSourceRootType.TEST_SOURCE, JpsModuleRootModelSerializer.JAVA_TEST_ROOT_TYPE_ID), - new JpsModuleSourceRootDummyPropertiesSerializer(JavaResourceRootType.RESOURCE, "java-resource"), - new JpsModuleSourceRootDummyPropertiesSerializer(JavaResourceRootType.TEST_RESOURCE, "java-test-resource")); + new JavaResourceRootPropertiesSerializer(JavaResourceRootType.RESOURCE, "java-resource"), + new JavaResourceRootPropertiesSerializer(JavaResourceRootType.TEST_RESOURCE, "java-test-resource")); } @Override @@ -328,4 +330,28 @@ public class JpsJavaModelSerializerExtension extends JpsModelSerializerExtension } } } + + private static class JavaResourceRootPropertiesSerializer extends JpsModuleSourceRootPropertiesSerializer { + private JavaResourceRootPropertiesSerializer(JpsModuleSourceRootType type, String typeId) { + super(type, typeId); + } + + @Override + public JavaResourceRootProperties loadProperties(@NotNull Element sourceRootTag) { + String relativeOutputPath = StringUtil.notNullize(sourceRootTag.getAttributeValue(RELATIVE_OUTPUT_PATH_ATTRIBUTE)); + boolean isGenerated = Boolean.parseBoolean(sourceRootTag.getAttributeValue(IS_GENERATED_ATTRIBUTE)); + return getService().createResourceRootProperties(relativeOutputPath, isGenerated); + } + + @Override + public void saveProperties(@NotNull JavaResourceRootProperties properties, @NotNull Element sourceRootTag) { + String relativeOutputPath = properties.getRelativeOutputPath(); + if (!relativeOutputPath.isEmpty()) { + sourceRootTag.setAttribute(RELATIVE_OUTPUT_PATH_ATTRIBUTE, relativeOutputPath); + } + if (properties.isForGeneratedSources()) { + sourceRootTag.setAttribute(IS_GENERATED_ATTRIBUTE, Boolean.TRUE.toString()); + } + } + } } diff --git a/jps/model-serialization/testData/resourceRoots/resourceRoots.iml b/jps/model-serialization/testData/resourceRoots/resourceRoots.iml new file mode 100644 index 000000000000..a13d44de4666 --- /dev/null +++ b/jps/model-serialization/testData/resourceRoots/resourceRoots.iml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/jps/model-serialization/testData/resourceRoots/resourceRoots.ipr b/jps/model-serialization/testData/resourceRoots/resourceRoots.ipr new file mode 100644 index 000000000000..81a4d8d2aa51 --- /dev/null +++ b/jps/model-serialization/testData/resourceRoots/resourceRoots.ipr @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsProjectSerializationTest.java b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsProjectSerializationTest.java index 2567927c87e9..11fd9c14a968 100644 --- a/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsProjectSerializationTest.java +++ b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsProjectSerializationTest.java @@ -151,11 +151,31 @@ public class JpsProjectSerializationTest extends JpsSerializationTestCase { assertEquals("UTF-8", configuration.getEncoding(new File(getAbsolutePath("other")))); } + public void testResourceRoots() { + String projectPath = "/jps/model-serialization/testData/resourceRoots/"; + loadProject(projectPath + "resourceRoots.ipr"); + JpsModule module = assertOneElement(myProject.getModules()); + List roots = module.getSourceRoots(); + assertSame(JavaSourceRootType.SOURCE, roots.get(0).getRootType()); + checkResourceRoot(roots.get(1), false, ""); + checkResourceRoot(roots.get(2), true, ""); + checkResourceRoot(roots.get(3), true, "foo"); + doTestSaveModule(module, projectPath + "resourceRoots.iml"); + } + + private static void checkResourceRoot(JpsModuleSourceRoot root, boolean forGenerated, String relativeOutput) { + assertSame(JavaResourceRootType.RESOURCE, root.getRootType()); + JavaResourceRootProperties properties = root.getProperties(JavaResourceRootType.RESOURCE); + assertNotNull(properties); + assertEquals(forGenerated, properties.isForGeneratedSources()); + assertEquals(relativeOutput, properties.getRelativeOutputPath()); + } + public void testSaveProject() { loadProject(SAMPLE_PROJECT_PATH); List modules = myProject.getModules(); - doTestSaveModule(modules.get(0), "main.iml"); - doTestSaveModule(modules.get(1), "util/util.iml"); + doTestSaveModule(modules.get(0), SAMPLE_PROJECT_PATH + "/main.iml"); + doTestSaveModule(modules.get(1), SAMPLE_PROJECT_PATH + "/util/util.iml"); //tod[nik] remember that test output root wasn't specified and doesn't save it to avoid unnecessary modifications of iml files //doTestSaveModule(modules.get(2), "xxx/xxx.iml"); @@ -188,7 +208,7 @@ public class JpsProjectSerializationTest extends JpsSerializationTestCase { try { Element actual = JDomSerializationUtil.createComponentElement("NewModuleRootManager"); JpsModuleRootModelSerializer.saveRootModel(module, actual); - File imlFile = getFileInSampleProject(moduleFilePath); + File imlFile = new File(getTestDataFileAbsolutePath(moduleFilePath)); Element rootElement = loadModuleRootTag(imlFile); Element expected = JDomSerializationUtil.findComponent(rootElement, "NewModuleRootManager"); PlatformTestUtil.assertElementsEqual(expected, actual); diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeCellRenderer.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeCellRenderer.java index bdbc44babd83..a349558422a0 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeCellRenderer.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryTreeCellRenderer.java @@ -28,6 +28,10 @@ import com.intellij.ui.JBColor; import com.intellij.ui.SimpleTextAttributes; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; +import org.jetbrains.jps.model.java.JavaResourceRootProperties; +import org.jetbrains.jps.model.java.JavaSourceRootProperties; +import org.jetbrains.jps.model.module.JpsModuleSourceRoot; import org.jetbrains.jps.model.module.JpsModuleSourceRootType; import javax.swing.*; @@ -58,7 +62,7 @@ public class ContentEntryTreeCellRenderer extends NodeRenderer { if (file != null && file.isDirectory()) { final ContentEntry contentEntry = editor.getContentEntry(); if (contentEntry != null) { - final String prefix = getPrefix(contentEntry, file); + final String prefix = getPresentablePrefix(contentEntry, file); if (!prefix.isEmpty()) { append(" (" + prefix + ")", new SimpleTextAttributes(Font.PLAIN, JBColor.GRAY)); } @@ -70,10 +74,14 @@ public class ContentEntryTreeCellRenderer extends NodeRenderer { } } - private static String getPrefix(final ContentEntry entry, final VirtualFile file) { + private static String getPresentablePrefix(final ContentEntry entry, final VirtualFile file) { for (final SourceFolder sourceFolder : entry.getSourceFolders()) { if (file.equals(sourceFolder.getFile())) { - return sourceFolder.getPackagePrefix(); + JpsModuleSourceRoot element = sourceFolder.getJpsElement(); + JavaSourceRootProperties properties = element.getProperties(JavaModuleSourceRootTypes.SOURCES); + if (properties != null) return properties.getPackagePrefix(); + JavaResourceRootProperties resourceRootProperties = element.getProperties(JavaModuleSourceRootTypes.RESOURCES); + if (resourceRootProperties != null) return resourceRootProperties.getRelativeOutputPath(); } } return ""; diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/SourceFolderImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/SourceFolderImpl.java index 4f153d396405..3c217205509b 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/SourceFolderImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/SourceFolderImpl.java @@ -27,10 +27,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.JpsElement; import org.jetbrains.jps.model.JpsElementFactory; -import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; -import org.jetbrains.jps.model.java.JavaResourceRootType; -import org.jetbrains.jps.model.java.JavaSourceRootProperties; -import org.jetbrains.jps.model.java.JavaSourceRootType; +import org.jetbrains.jps.model.java.*; import org.jetbrains.jps.model.module.JpsModuleSourceRoot; import org.jetbrains.jps.model.module.JpsModuleSourceRootType; import org.jetbrains.jps.model.module.JpsTypedModuleSourceRoot; @@ -78,7 +75,14 @@ public class SourceFolderImpl extends ContentFolderBaseImpl implements SourceFol @Override public String getPackagePrefix() { JavaSourceRootProperties properties = getJavaProperties(); - return properties != null ? properties.getPackagePrefix() : DEFAULT_PACKAGE_PREFIX; + if (properties != null) { + return properties.getPackagePrefix(); + } + JavaResourceRootProperties resourceJavaProperties = getResourceJavaProperties(); + if (resourceJavaProperties != null) { + return resourceJavaProperties.getRelativeOutputPath().replace('/', '.'); + } + return DEFAULT_PACKAGE_PREFIX; } @Nullable @@ -86,6 +90,11 @@ public class SourceFolderImpl extends ContentFolderBaseImpl implements SourceFol return myJpsElement.getProperties(JavaModuleSourceRootTypes.SOURCES); } + @Nullable + private JavaResourceRootProperties getResourceJavaProperties() { + return myJpsElement.getProperties(JavaModuleSourceRootTypes.RESOURCES); + } + @Override public void setPackagePrefix(@NotNull String packagePrefix) { JavaSourceRootProperties properties = getJavaProperties(); @@ -112,6 +121,12 @@ public class SourceFolderImpl extends ContentFolderBaseImpl implements SourceFol return myJpsElement; } + private boolean isForGeneratedSources() { + JavaSourceRootProperties properties = getJavaProperties(); + JavaResourceRootProperties resourceJavaProperties = getResourceJavaProperties(); + return properties != null && properties.isForGeneratedSources() || resourceJavaProperties != null && resourceJavaProperties.isForGeneratedSources(); + } + @Override public int compareTo(ContentFolderBaseImpl folder) { if (!(folder instanceof SourceFolderImpl)) return -1; @@ -124,12 +139,8 @@ public class SourceFolderImpl extends ContentFolderBaseImpl implements SourceFol if (i!= 0) return i; i = Boolean.valueOf(isTestSource()).compareTo(sourceFolder.isTestSource()); if (i != 0) return i; - JavaSourceRootProperties properties1 = getJavaProperties(); - JavaSourceRootProperties properties2 = sourceFolder.getJavaProperties(); - if (properties1 != null && properties2 != null) { - i = Boolean.valueOf(properties1.isForGeneratedSources()).compareTo(properties2.isForGeneratedSources()); - if (i != 0) return i; - } + i = Boolean.valueOf(isForGeneratedSources()).compareTo(sourceFolder.isForGeneratedSources()); + if (i != 0) return i; //todo[nik] perhaps we should use LinkedSet instead of SortedSet and get rid of this method return myJpsElement.getRootType().getClass().getName().compareTo(sourceFolder.getRootType().getClass().getName()); }