From 3e9b3fe17af3c4777a4867a36c84af7511d0cbf0 Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 19 Sep 2012 17:52:39 +0400 Subject: [PATCH] external compiler for plugin modules: fixed references to IDEA sdk & test added --- java/compiler/impl/compiler-impl.iml | 1 + .../compiler/BaseCompilerTestCase.java | 397 ++++++++++++++++++ .../src/org/jetbrains/jps/ProjectPaths.java | 33 +- .../model/java/JpsJavaExtensionService.java | 5 + .../impl/JpsJavaExtensionServiceImpl.java | 8 + .../impl/JpsWrappedJavaSdkReferenceImpl.java | 66 +++ .../library/JpsSdkTableSerializer.java | 11 +- .../module/JpsModuleRootModelSerializer.java | 4 + .../testData/pluginProject/pluginProject.iml | 2 +- .../testData/pluginProject/pluginProject.ipr | 204 --------- .../JpsPluginProjectSerializationTest.java | 13 + .../testData/build/simple/META-INF/plugin.xml | 9 + .../testData/build/simple/pluginProject.iml | 13 + .../build/simple/src/xxx/MyAction.java | 9 + .../build/PluginModuleCompilationTest.java | 98 +++++ 15 files changed, 654 insertions(+), 219 deletions(-) create mode 100644 java/compiler/impl/testSrc/com/intellij/compiler/BaseCompilerTestCase.java create mode 100644 jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsWrappedJavaSdkReferenceImpl.java create mode 100644 plugins/devkit/testData/build/simple/META-INF/plugin.xml create mode 100644 plugins/devkit/testData/build/simple/pluginProject.iml create mode 100644 plugins/devkit/testData/build/simple/src/xxx/MyAction.java create mode 100644 plugins/devkit/testSources/build/PluginModuleCompilationTest.java diff --git a/java/compiler/impl/compiler-impl.iml b/java/compiler/impl/compiler-impl.iml index 9436236e20e1..302e47baafe1 100644 --- a/java/compiler/impl/compiler-impl.iml +++ b/java/compiler/impl/compiler-impl.iml @@ -24,6 +24,7 @@ + diff --git a/java/compiler/impl/testSrc/com/intellij/compiler/BaseCompilerTestCase.java b/java/compiler/impl/testSrc/com/intellij/compiler/BaseCompilerTestCase.java new file mode 100644 index 000000000000..a47a34aaf6b3 --- /dev/null +++ b/java/compiler/impl/testSrc/com/intellij/compiler/BaseCompilerTestCase.java @@ -0,0 +1,397 @@ +package com.intellij.compiler; + +import com.intellij.ide.highlighter.ModuleFileType; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.compiler.*; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl; +import com.intellij.openapi.roots.CompilerModuleExtension; +import com.intellij.openapi.roots.CompilerProjectExtension; +import com.intellij.openapi.roots.ModuleRootModificationUtil; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.newvfs.NewVirtualFile; +import com.intellij.packaging.artifacts.Artifact; +import com.intellij.packaging.artifacts.ArtifactManager; +import com.intellij.packaging.impl.compiler.ArtifactCompileScope; +import com.intellij.testFramework.ModuleTestCase; +import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.PsiTestUtil; +import com.intellij.testFramework.VfsTestUtil; +import com.intellij.util.ParameterizedRunnable; +import com.intellij.util.concurrency.Semaphore; +import com.intellij.util.io.TestFileSystemBuilder; +import com.intellij.util.ui.UIUtil; +import gnu.trove.THashSet; +import junit.framework.Assert; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.JpsPathUtil; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * @author nik + */ +public abstract class BaseCompilerTestCase extends ModuleTestCase { + protected boolean useExternalCompiler() { + return false; + } + + @Override + protected void setUpModule() { + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + if (useExternalCompiler()) { + CompilerTestUtil.enableExternalCompiler(myProject); + } + } + + @Override + protected Sdk getTestProjectJdk() { + if (useExternalCompiler()) { + return JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk(); + } + return super.getTestProjectJdk(); + } + + @Override + protected void tearDown() throws Exception { + for (Artifact artifact : getArtifactManager().getArtifacts()) { + final String outputPath = artifact.getOutputPath(); + if (!StringUtil.isEmpty(outputPath)) { + FileUtil.delete(new File(FileUtil.toSystemDependentName(outputPath))); + } + } + if (useExternalCompiler()) { + CompilerTestUtil.disableExternalCompiler(myProject); + } + + super.tearDown(); + } + + protected ArtifactManager getArtifactManager() { + return ArtifactManager.getInstance(myProject); + } + + protected String getProjectBasePath() { + return getBaseDir().getPath(); + } + + protected VirtualFile getBaseDir() { + final VirtualFile baseDir = myProject.getBaseDir(); + Assert.assertNotNull(baseDir); + return baseDir; + } + + protected void copyToProject(String relativePath) { + File dir = PathManagerEx.findFileUnderProjectHome(relativePath, getClass()); + final File target = new File(FileUtil.toSystemDependentName(getProjectBasePath())); + try { + FileUtil.copyDir(dir, target); + } + catch (IOException e) { + throw new RuntimeException(e); + } + new WriteAction() { + protected void run(final Result result) { + VirtualFile virtualDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(target); + assertNotNull(target.getAbsolutePath() + " not found", virtualDir); + virtualDir.refresh(false, true); + } + }.execute(); + } + + protected Module addModule(final String moduleName, final @Nullable VirtualFile sourceRoot) { + return new WriteAction() { + @Override + protected void run(final Result result) { + final Module module = createModule(moduleName); + if (sourceRoot != null) { + PsiTestUtil.addSourceContentToRoots(module, sourceRoot); + } + ModuleRootModificationUtil.setModuleSdk(module, getTestProjectJdk()); + result.setResult(module); + } + }.execute().getResultObject(); + } + + protected VirtualFile createFile(final String path) { + return createFile(path, ""); + } + + protected VirtualFile createFile(final String path, final String text) { + return VfsTestUtil.createFile(getBaseDir(), path, text); + } + + protected CompilationLog make(final Artifact... artifacts) { + final CompileScope scope = ArtifactCompileScope.createArtifactsScope(myProject, Arrays.asList(artifacts)); + return make(scope, CompilerFilter.ALL); + } + + protected CompilationLog make(Module module) { + return make(getCompilerManager().createModuleCompileScope(module, false), CompilerFilter.ALL); + } + + private CompilerManager getCompilerManager() { + return CompilerManager.getInstance(myProject); + } + + protected void assertModulesUpToDate() { + //todo[nik,jeka] uncomment this when isUpToDate become supported in external compiler + //boolean upToDate = getCompilerManager().isUpToDate(getCompilerManager().createProjectCompileScope(myProject)); + //assertTrue("Modules are not up to date", upToDate); + } + + protected CompilationLog compile(boolean force, VirtualFile... files) { + return compile(getCompilerManager().createFilesCompileScope(files), CompilerFilter.ALL, force); + } + + protected CompilationLog make(final CompileScope scope, final CompilerFilter filter) { + return compile(scope, filter, false); + } + + protected CompilationLog compile(final CompileScope scope, final CompilerFilter filter, final boolean forceCompile) { + return compile(scope, filter, forceCompile, false); + } + + protected CompilationLog compile(final CompileScope scope, final CompilerFilter filter, final boolean forceCompile, + final boolean errorsExpected) { + return compile(errorsExpected, new ParameterizedRunnable() { + @Override + public void run(CompileStatusNotification callback) { + final CompilerManager compilerManager = getCompilerManager(); + if (forceCompile) { + Assert.assertSame("Only 'ALL' filter is supported for forced compilation", CompilerFilter.ALL, filter); + compilerManager.compile(scope, callback); + } + else { + compilerManager.make(scope, filter, callback); + } + } + }); + } + + protected void rebuild() { + compile(false, new ParameterizedRunnable() { + @Override + public void run(CompileStatusNotification compileStatusNotification) { + getCompilerManager().rebuild(compileStatusNotification); + } + }); + } + + protected CompilationLog compile(final boolean errorsExpected, final ParameterizedRunnable action) { + final Ref result = Ref.create(null); + final Semaphore semaphore = new Semaphore(); + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + @Override + public void run() { + semaphore.down(); + + CompilerManagerImpl.testSetup(); + final CompileStatusNotification callback = new CompileStatusNotification() { + @Override + public void finished(boolean aborted, int errors, int warnings, CompileContext compileContext) { + try { + if (aborted) { + Assert.fail("compilation aborted"); + } + if (errorsExpected && errors == 0) { + Assert.fail("compilation finished without errors"); + } + else if (!errorsExpected && errors > 0) { + Assert + .fail("compilation finished with errors: " + Arrays.toString(compileContext.getMessages(CompilerMessageCategory.ERROR))); + } + result.set(new CompilationLog(CompilerManagerImpl.getPathsToRecompile(), CompilerManagerImpl.getPathsToDelete())); + } + finally { + semaphore.up(); + } + } + }; + if (useExternalCompiler()) { + myProject.save(); + CompilerTestUtil.saveSdkTable(); + CompilerTestUtil.scanSourceRootsToRecompile(myProject); + } + action.run(callback); + } + }); + + long start = System.currentTimeMillis(); + while (!semaphore.waitFor(10)) { + if (System.currentTimeMillis() - start > 60 * 1000) { + throw new RuntimeException("timeout"); + } + UIUtil.dispatchAllInvocationEvents(); + } + UIUtil.dispatchAllInvocationEvents(); + + return result.get(); + } + + private Set getRelativePaths(String[] paths) { + final Set set = new THashSet(); + final String basePath = myProject.getBaseDir().getPath(); + for (String path : paths) { + set.add(StringUtil.trimStart(StringUtil.trimStart(FileUtil.toSystemIndependentName(path), basePath), "/")); + } + return set; + } + + protected void changeFile(VirtualFile file) throws Exception { + changeFile(file, null); + } + + protected void changeFile(VirtualFile file, final String newText) { + try { + if (newText != null) { + VfsUtil.saveText(file, newText); + } + ((NewVirtualFile)file).setTimeStamp(file.getTimeStamp() + 10); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected void deleteFile(final VirtualFile file) { + new WriteAction() { + @Override + protected void run(final Result result) { + try { + file.delete(this); + } + catch (IOException e) { + throw new AssertionError(e); + } + } + }.execute(); + } + + @Override + protected void setUpProject() throws Exception { + super.setUpProject(); + final String baseUrl = myProject.getBaseDir().getUrl(); + CompilerProjectExtension.getInstance(myProject).setCompilerOutputUrl(baseUrl + "/out"); + } + + @Override + protected File getIprFile() throws IOException { + File iprFile = super.getIprFile(); + if (useExternalCompiler()) { + FileUtil.delete(iprFile); + } + return iprFile; + } + + @Override + protected Module doCreateRealModule(String moduleName) { + if (useExternalCompiler()) { + //todo[nik] reuse code from PlatformTestCase + final VirtualFile baseDir = myProject.getBaseDir(); + Assert.assertNotNull(baseDir); + final File moduleFile = new File(baseDir.getPath().replace('/', File.separatorChar), moduleName + ModuleFileType.DOT_DEFAULT_EXTENSION); + PlatformTestCase.myFilesToDelete.add(moduleFile); + return new WriteAction() { + @Override + protected void run(Result result) throws Throwable { + Module module = ModuleManager.getInstance(myProject) + .newModule(FileUtil.toSystemIndependentName(moduleFile.getAbsolutePath()), getModuleType().getId()); + module.getModuleFile(); + result.setResult(module); + } + }.execute().getResultObject(); + } + return super.doCreateRealModule(moduleName); + } + + @Override + protected boolean isRunInWriteAction() { + return false; + } + + protected static void assertOutput(Module module, TestFileSystemBuilder item) { + File outputDir = getOutputDir(module); + Assert.assertTrue("Output directory " + outputDir.getAbsolutePath() + " doesn't exist", outputDir.exists()); + item.build().assertDirectoryEqual(outputDir); + } + + protected static void assertNoOutput(Module module) { + File dir = getOutputDir(module); + Assert.assertFalse("Output directory " + dir.getAbsolutePath() + " does exist", dir.exists()); + } + + protected static File getOutputDir(Module module) { + CompilerModuleExtension extension = CompilerModuleExtension.getInstance(module); + Assert.assertNotNull(extension); + String outputUrl = extension.getCompilerOutputUrl(); + Assert.assertNotNull("Output directory for module '" + module.getName() + "' isn't specified", outputUrl); + return JpsPathUtil.urlToFile(outputUrl); + } + + protected class CompilationLog { + private final Set myRecompiledPaths; + private final Set myDeletedPaths; + + public CompilationLog(String[] recompiledPaths, String[] deletedPaths) { + myRecompiledPaths = getRelativePaths(recompiledPaths); + myDeletedPaths = getRelativePaths(deletedPaths); + } + + public void assertUpToDate() { + checkRecompiled(); + checkDeleted(); + } + + public void assertRecompiled(String... expected) { + checkRecompiled(expected); + checkDeleted(); + } + + public void assertDeleted(String... expected) { + checkRecompiled(); + checkDeleted(expected); + } + + public void assertRecompiledAndDeleted(String[] recompiled, String... deleted) { + checkRecompiled(recompiled); + checkDeleted(deleted); + } + + private void checkRecompiled(String... expected) { + assertSet("recompiled", myRecompiledPaths, expected); + } + + private void checkDeleted(String... expected) { + assertSet("deleted", myDeletedPaths, expected); + } + + private void assertSet(String name, Set actual, String[] expected) { + for (String path : expected) { + if (!actual.remove(path)) { + Assert.fail("'" + path + "' is not " + name + ". " + name + ": " + new HashSet(actual)); + } + } + if (!actual.isEmpty()) { + Assert.fail("'" + actual.iterator().next() + "' must not be " + name); + } + } + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/ProjectPaths.java b/jps/jps-builders/src/org/jetbrains/jps/ProjectPaths.java index fa51f45e7da0..072632a3f8c2 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/ProjectPaths.java +++ b/jps/jps-builders/src/org/jetbrains/jps/ProjectPaths.java @@ -1,7 +1,6 @@ package org.jetbrains.jps; import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Conditions; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; @@ -60,10 +59,10 @@ public class ProjectPaths { enumerator = enumerator.exportedOnly(); } if (classpathPart == ClasspathPart.BEFORE_JDK) { - enumerator = enumerator.satisfying(new BeforeSdkItemFilter(module)); + enumerator = enumerator.satisfying(new BeforeJavaSdkItemFilter(module)); } else if (classpathPart == ClasspathPart.AFTER_JDK) { - enumerator = enumerator.satisfying(Conditions.not(new BeforeSdkItemFilter(module))).withoutSdk(); + enumerator = enumerator.satisfying(new AfterJavaSdkItemFilter(module)); } JpsJavaDependenciesRootsEnumerator rootsEnumerator = enumerator.classes(); if (excludeMainModuleOutput) { @@ -179,20 +178,40 @@ public class ProjectPaths { private enum ClasspathPart {WHOLE, BEFORE_JDK, AFTER_JDK} - private static class BeforeSdkItemFilter implements Condition { + private static class BeforeJavaSdkItemFilter implements Condition { private JpsModule myModule; private boolean mySdkFound; - private BeforeSdkItemFilter(JpsModule module) { + private BeforeJavaSdkItemFilter(JpsModule module) { myModule = module; } @Override public boolean value(JpsDependencyElement dependency) { - if (myModule.equals(dependency.getContainingModule()) && dependency instanceof JpsSdkDependency) { + boolean isJavaSdk = dependency instanceof JpsSdkDependency && ((JpsSdkDependency)dependency).getSdkType().equals(JpsJavaSdkType.INSTANCE); + if (myModule.equals(dependency.getContainingModule()) && isJavaSdk) { mySdkFound = true; } - return !mySdkFound && !(dependency instanceof JpsSdkDependency); + return !mySdkFound && !isJavaSdk; + } + } + + private static class AfterJavaSdkItemFilter implements Condition { + private JpsModule myModule; + private boolean mySdkFound; + + private AfterJavaSdkItemFilter(JpsModule module) { + myModule = module; + } + + @Override + public boolean value(JpsDependencyElement dependency) { + if (myModule.equals(dependency.getContainingModule()) && + dependency instanceof JpsSdkDependency && ((JpsSdkDependency)dependency).getSdkType().equals(JpsJavaSdkType.INSTANCE)) { + mySdkFound = true; + return false; + } + return mySdkFound; } } 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 c2fe89391d79..48b54edce03f 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 @@ -8,6 +8,7 @@ import org.jetbrains.jps.model.JpsProject; import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration; import org.jetbrains.jps.model.library.JpsTypedLibrary; import org.jetbrains.jps.model.library.sdk.JpsSdk; +import org.jetbrains.jps.model.library.sdk.JpsSdkReference; import org.jetbrains.jps.model.module.JpsDependencyElement; import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.model.module.JpsModuleReference; @@ -93,4 +94,8 @@ public abstract class JpsJavaExtensionService { @NotNull public abstract JpsJavaCompilerConfiguration getOrCreateCompilerConfiguration(@NotNull JpsProject project); + + @NotNull + public abstract JpsSdkReference createWrappedJavaSdkReference(@NotNull JpsJavaSdkTypeWrapper sdkType, + @NotNull JpsSdkReference wrapperReference); } 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 86018efbb23d..323a0b1e34fc 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 @@ -14,6 +14,7 @@ import org.jetbrains.jps.model.java.impl.compiler.JpsJavaCompilerConfigurationIm import org.jetbrains.jps.model.library.JpsOrderRootType; import org.jetbrains.jps.model.library.JpsTypedLibrary; import org.jetbrains.jps.model.library.sdk.JpsSdk; +import org.jetbrains.jps.model.library.sdk.JpsSdkReference; import org.jetbrains.jps.model.module.*; import java.io.File; @@ -161,6 +162,13 @@ public class JpsJavaExtensionServiceImpl extends JpsJavaExtensionService { return configuration; } + @NotNull + @Override + public JpsSdkReference createWrappedJavaSdkReference(@NotNull JpsJavaSdkTypeWrapper sdkType, + @NotNull JpsSdkReference wrapperReference) { + return new JpsWrappedJavaSdkReferenceImpl(sdkType, wrapperReference); + } + @Override @NotNull public JpsProductionModuleOutputPackagingElement createProductionModuleOutput(@NotNull JpsModuleReference moduleReference) { diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsWrappedJavaSdkReferenceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsWrappedJavaSdkReferenceImpl.java new file mode 100644 index 000000000000..7950b063eca0 --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JpsWrappedJavaSdkReferenceImpl.java @@ -0,0 +1,66 @@ +package org.jetbrains.jps.model.java.impl; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.JpsDummyElement; +import org.jetbrains.jps.model.JpsElement; +import org.jetbrains.jps.model.JpsElementReference; +import org.jetbrains.jps.model.JpsModel; +import org.jetbrains.jps.model.impl.JpsCompositeElementBase; +import org.jetbrains.jps.model.impl.JpsElementChildRoleBase; +import org.jetbrains.jps.model.java.JpsJavaSdkType; +import org.jetbrains.jps.model.java.JpsJavaSdkTypeWrapper; +import org.jetbrains.jps.model.library.JpsLibrary; +import org.jetbrains.jps.model.library.JpsTypedLibrary; +import org.jetbrains.jps.model.library.sdk.JpsSdk; +import org.jetbrains.jps.model.library.sdk.JpsSdkReference; + +/** + * @author nik + */ +public class JpsWrappedJavaSdkReferenceImpl extends JpsCompositeElementBase implements JpsSdkReference { + private static final JpsElementChildRoleBase> WRAPPER_ROLE = JpsElementChildRoleBase.create("wrapper reference"); + private final JpsJavaSdkTypeWrapper mySdkType; + + public JpsWrappedJavaSdkReferenceImpl(JpsJavaSdkTypeWrapper sdkType, JpsSdkReference wrapperReference) { + mySdkType = sdkType; + myContainer.setChild(WRAPPER_ROLE, wrapperReference); + } + + private JpsWrappedJavaSdkReferenceImpl(JpsWrappedJavaSdkReferenceImpl original) { + super(original); + mySdkType = original.mySdkType; + } + + @NotNull + @Override + public JpsWrappedJavaSdkReferenceImpl createCopy() { + return new JpsWrappedJavaSdkReferenceImpl(this); + } + + @Override + public String getSdkName() { + JpsTypedLibrary> sdk = resolve(); + return sdk != null ? sdk.getName() : ""; + } + + @Nullable + @Override + public JpsTypedLibrary> resolve() { + JpsTypedLibrary> wrapper = myContainer.getChild(WRAPPER_ROLE).resolve(); + if (wrapper == null) return null; + JpsModel model = getModel(); + if (model == null) return null; + String sdkName = mySdkType.getJavaSdkName(wrapper.getProperties().getSdkProperties()); + if (sdkName == null) return null; + + JpsLibrary library = model.getGlobal().getLibraryCollection().findLibrary(sdkName); + return library != null ? library.asTyped(JpsJavaSdkType.INSTANCE) : null; + } + + @Override + public JpsElementReference>> asExternal(@NotNull JpsModel model) { + model.registerExternalReference(this); + return this; + } +} diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsSdkTableSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsSdkTableSerializer.java index 8541f904377b..00f70f329703 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsSdkTableSerializer.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/library/JpsSdkTableSerializer.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.JpsDummyElement; import org.jetbrains.jps.model.JpsElement; import org.jetbrains.jps.model.JpsElementFactory; +import org.jetbrains.jps.model.java.JpsJavaExtensionService; import org.jetbrains.jps.model.java.JpsJavaSdkType; import org.jetbrains.jps.model.java.JpsJavaSdkTypeWrapper; import org.jetbrains.jps.model.library.*; @@ -219,13 +220,9 @@ public class JpsSdkTableSerializer { JpsSdkReference

reference = JpsElementFactory.getInstance().createSdkReference(sdkName, sdkType); table.setSdkReference(sdkType, reference); if (sdkType instanceof JpsJavaSdkTypeWrapper) { - JpsLibrary jpsLibrary = reference.resolve(); - if (jpsLibrary != null) { - String name = ((JpsJavaSdkTypeWrapper)sdkType).getJavaSdkName(((JpsSdk)jpsLibrary.getProperties()).getSdkProperties()); - if (name != null) { - table.setSdkReference(JpsJavaSdkType.INSTANCE, JpsElementFactory.getInstance().createSdkReference(name, JpsJavaSdkType.INSTANCE)); - } - } + JpsSdkReference

wrapperRef = JpsElementFactory.getInstance().createSdkReference(sdkName, sdkType); + table.setSdkReference(JpsJavaSdkType.INSTANCE, JpsJavaExtensionService.getInstance().createWrappedJavaSdkReference((JpsJavaSdkTypeWrapper)sdkType, + wrapperRef)); } } } diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java index cba1b3a103da..a1fef5c3be7b 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java @@ -10,6 +10,7 @@ import org.jetbrains.jps.model.JpsSimpleElement; import org.jetbrains.jps.model.java.JavaSourceRootProperties; import org.jetbrains.jps.model.java.JavaSourceRootType; import org.jetbrains.jps.model.java.JpsJavaSdkType; +import org.jetbrains.jps.model.java.JpsJavaSdkTypeWrapper; import org.jetbrains.jps.model.library.JpsLibrary; import org.jetbrains.jps.model.library.JpsLibraryReference; import org.jetbrains.jps.model.library.sdk.JpsSdkType; @@ -82,6 +83,9 @@ public class JpsModuleRootModelSerializer { final JpsSdkType sdkType = JpsSdkTableSerializer.getSdkType(sdkTypeId); dependenciesList.addSdkDependency(sdkType); JpsSdkTableSerializer.setSdkReference(module.getSdkReferencesTable(), sdkName, sdkType); + if (sdkType instanceof JpsJavaSdkTypeWrapper) { + dependenciesList.addSdkDependency(JpsJavaSdkType.INSTANCE); + } } else if (INHERITED_JDK_TYPE.equals(type)) { dependenciesList.addSdkDependency(projectSdkType != null ? projectSdkType : JpsJavaSdkType.INSTANCE); diff --git a/plugins/devkit/jps-plugin/testData/pluginProject/pluginProject.iml b/plugins/devkit/jps-plugin/testData/pluginProject/pluginProject.iml index b1dfece3abbb..953b0b8577d1 100644 --- a/plugins/devkit/jps-plugin/testData/pluginProject/pluginProject.iml +++ b/plugins/devkit/jps-plugin/testData/pluginProject/pluginProject.iml @@ -6,7 +6,7 @@ - + diff --git a/plugins/devkit/jps-plugin/testData/pluginProject/pluginProject.ipr b/plugins/devkit/jps-plugin/testData/pluginProject/pluginProject.ipr index e586236c5521..a2be79a932b7 100644 --- a/plugins/devkit/jps-plugin/testData/pluginProject/pluginProject.ipr +++ b/plugins/devkit/jps-plugin/testData/pluginProject/pluginProject.ipr @@ -1,8 +1,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - http://www.w3.org/1999/xhtml - - - - - - - - - - - - - - diff --git a/plugins/devkit/jps-plugin/testSrc/org/jetbrains/jps/devkit/model/JpsPluginProjectSerializationTest.java b/plugins/devkit/jps-plugin/testSrc/org/jetbrains/jps/devkit/model/JpsPluginProjectSerializationTest.java index 35df069c3a08..39de4803bf1c 100644 --- a/plugins/devkit/jps-plugin/testSrc/org/jetbrains/jps/devkit/model/JpsPluginProjectSerializationTest.java +++ b/plugins/devkit/jps-plugin/testSrc/org/jetbrains/jps/devkit/model/JpsPluginProjectSerializationTest.java @@ -15,7 +15,12 @@ */ package org.jetbrains.jps.devkit.model; +import org.jetbrains.jps.model.JpsDummyElement; +import org.jetbrains.jps.model.JpsElementFactory; import org.jetbrains.jps.model.JpsSimpleElement; +import org.jetbrains.jps.model.java.JpsJavaSdkType; +import org.jetbrains.jps.model.library.JpsTypedLibrary; +import org.jetbrains.jps.model.library.sdk.JpsSdk; import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.model.module.JpsTypedModule; import org.jetbrains.jps.model.serialization.JpsSerializationTestCase; @@ -32,5 +37,13 @@ public class JpsPluginProjectSerializationTest extends JpsSerializationTestCase assertNotNull(pluginModule); String url = pluginModule.getProperties().getData().getPluginXmlUrl(); assertEquals(getUrl("META-INF/plugin.xml"), url); + + JpsTypedLibrary> javaSdk = myModel.getGlobal().addSdk("1.6", null, null, JpsJavaSdkType.INSTANCE); + JpsSimpleElement properties = + JpsElementFactory.getInstance().createSimpleElement(new JpsIdeaSdkProperties(null, "1.6")); + JpsTypedLibrary>> pluginSdk = myModel.getGlobal() + .addSdk("IDEA plugin SDK", null, null, JpsIdeaSdkType.INSTANCE, properties); + assertSame(pluginSdk.getProperties(), module.getSdk(JpsIdeaSdkType.INSTANCE)); + assertSame(javaSdk.getProperties(), module.getSdk(JpsJavaSdkType.INSTANCE)); } } diff --git a/plugins/devkit/testData/build/simple/META-INF/plugin.xml b/plugins/devkit/testData/build/simple/META-INF/plugin.xml new file mode 100644 index 000000000000..e5b561ad0423 --- /dev/null +++ b/plugins/devkit/testData/build/simple/META-INF/plugin.xml @@ -0,0 +1,9 @@ + + test.plugin + Test Plugin + 1.0 + + + + + \ No newline at end of file diff --git a/plugins/devkit/testData/build/simple/pluginProject.iml b/plugins/devkit/testData/build/simple/pluginProject.iml new file mode 100644 index 000000000000..953b0b8577d1 --- /dev/null +++ b/plugins/devkit/testData/build/simple/pluginProject.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/plugins/devkit/testData/build/simple/src/xxx/MyAction.java b/plugins/devkit/testData/build/simple/src/xxx/MyAction.java new file mode 100644 index 000000000000..997befe3f867 --- /dev/null +++ b/plugins/devkit/testData/build/simple/src/xxx/MyAction.java @@ -0,0 +1,9 @@ +package xxx; + +import com.intellij.openapi.util.io.FileUtilRt ; + +public class MyAction { + public void actionPerformed() { + FileUtilRt.toSystemDependentName("myPath"); + } +} diff --git a/plugins/devkit/testSources/build/PluginModuleCompilationTest.java b/plugins/devkit/testSources/build/PluginModuleCompilationTest.java new file mode 100644 index 000000000000..fedae6eff720 --- /dev/null +++ b/plugins/devkit/testSources/build/PluginModuleCompilationTest.java @@ -0,0 +1,98 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.devkit.build; + +import com.intellij.compiler.BaseCompilerTestCase; +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.impl.ModuleImpl; +import com.intellij.openapi.projectRoots.ProjectJdkTable; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.SdkModificator; +import com.intellij.openapi.projectRoots.SdkType; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.FileUtilRt; +import com.intellij.openapi.vfs.LocalFileSystem; +import org.jetbrains.idea.devkit.projectRoots.IdeaJdk; +import org.jetbrains.idea.devkit.projectRoots.Sandbox; + +import java.io.File; + +import static com.intellij.util.io.TestFileSystemBuilder.fs; + +/** + * @author nik + */ +public class PluginModuleCompilationTest extends BaseCompilerTestCase { + private Sdk myPluginSdk; + + @Override + protected void setUpJdk() { + super.setUpJdk(); + new WriteAction() { + protected void run(final Result result) { + ProjectJdkTable table = ProjectJdkTable.getInstance(); + myPluginSdk = table.createSdk("IDEA plugin SDK", SdkType.findInstance(IdeaJdk.class)); + SdkModificator modificator = myPluginSdk.getSdkModificator(); + modificator.setSdkAdditionalData(new Sandbox(getSandboxPath(), getTestProjectJdk(), myPluginSdk)); + String rootPath = FileUtil.toSystemIndependentName(PathManager.getJarPathForClass(FileUtilRt.class)); + modificator.addRoot(LocalFileSystem.getInstance().refreshAndFindFileByPath(rootPath), OrderRootType.CLASSES); + modificator.commitChanges(); + table.addJdk(myPluginSdk); + } + }.execute(); + } + + private String getSandboxPath() { + return getProjectBasePath() + "/sandbox"; + } + + @Override + protected boolean useExternalCompiler() { + return true; + } + + @Override + protected void tearDown() throws Exception { + new WriteAction() { + protected void run(final Result result) { + ProjectJdkTable.getInstance().removeJdk(myPluginSdk); + } + }.execute(); + + super.tearDown(); + } + + public void testMakeModule() { + copyToProject("plugins/devkit/testData/build/simple"); + Module module = loadModule(getProjectBasePath() + "/pluginProject.iml"); + readJdomExternalizables((ModuleImpl)module); + make(module); + assertOutput(module, fs().dir("xxx").file("MyAction.class")); + + File sandbox = new File(FileUtil.toSystemDependentName(getSandboxPath())); + assertTrue(sandbox.exists()); + fs().dir("plugins") + .dir("pluginProject") + .dir("META-INF").file("plugin.xml").end() + .dir("classes") + .dir("xxx").file("MyAction.class") + .build().assertDirectoryEqual(sandbox); + } +}