diff --git a/java/java-runtime/src/com/intellij/rt/execution/application/AppMainV2.java b/java/java-runtime/src/com/intellij/rt/execution/application/AppMainV2.java index d8dd87677f3c..e1390d703ff1 100644 --- a/java/java-runtime/src/com/intellij/rt/execution/application/AppMainV2.java +++ b/java/java-runtime/src/com/intellij/rt/execution/application/AppMainV2.java @@ -150,16 +150,21 @@ public class AppMainV2 { public static class Agent { public static void premain(String args, Instrumentation i) { - try { - int p = args.indexOf(':'); - if (p < 0) throw new IllegalArgumentException("incorrect parameter: " + args); - boolean helperLibLoaded = loadHelper(args.substring(p + 1)); - int portNumber = Integer.parseInt(args.substring(0, p)); - startMonitor(portNumber, helperLibLoaded); - } - catch (Throwable t) { - System.err.println("Launcher failed - \"Dump Threads\" and \"Exit\" actions are unavailable (" + t.getMessage() + ')'); - } + AppMainV2.premain(args); + } + } + + // todo[r.sh] inline some time after 2017.1.1 release + public static void premain(String args) { + try { + int p = args.indexOf(':'); + if (p < 0) throw new IllegalArgumentException("incorrect parameter: " + args); + boolean helperLibLoaded = loadHelper(args.substring(p + 1)); + int portNumber = Integer.parseInt(args.substring(0, p)); + startMonitor(portNumber, helperLibLoaded); + } + catch (Throwable t) { + System.err.println("Launcher failed - \"Dump Threads\" and \"Exit\" actions are unavailable (" + t.getMessage() + ')'); } } } \ No newline at end of file diff --git a/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/CompilerBackwardReferenceIndex.java b/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/CompilerBackwardReferenceIndex.java index 900165450b62..a6019dd6bfcc 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/CompilerBackwardReferenceIndex.java +++ b/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/CompilerBackwardReferenceIndex.java @@ -32,10 +32,8 @@ import org.jetbrains.jps.builders.storage.BuildDataCorruptedException; import java.io.*; import java.io.DataOutputStream; -import java.util.Collection; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; public class CompilerBackwardReferenceIndex { private final static Logger LOG = Logger.getInstance(CompilerBackwardReferenceIndex.class); @@ -48,6 +46,7 @@ public class CompilerBackwardReferenceIndex { private final NameEnumerator myNameEnumerator; private final PersistentStringEnumerator myFilePathEnumerator; private final File myIndicesDir; + private final boolean myReadOnly; private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() { @Override public void run() { @@ -67,6 +66,7 @@ public class CompilerBackwardReferenceIndex { public CompilerBackwardReferenceIndex(File buildDir, boolean readOnly) { myIndicesDir = getIndexDir(buildDir); + myReadOnly = readOnly; if (!myIndicesDir.exists() && !myIndicesDir.mkdirs()) { throw new RuntimeException("Can't create dir: " + buildDir.getAbsolutePath()); } @@ -74,6 +74,8 @@ public class CompilerBackwardReferenceIndex { if (versionDiffers(buildDir)) { saveVersion(buildDir); } + if (myReadOnly) logModification("open"); + myFilePathEnumerator = new PersistentStringEnumerator(new File(myIndicesDir, FILE_ENUM_TAB)) { @Override public int enumerate(@Nullable String value) throws IOException { @@ -123,6 +125,7 @@ public class CompilerBackwardReferenceIndex { for (InvertedIndex index : myIndices.values()) { close(index, exceptionProc); } + if (myReadOnly) logModification("close"); final Exception exception = exceptionProc.getFoundValue(); if (exception != null) { removeIndexFiles(myIndicesDir); @@ -199,6 +202,20 @@ public class CompilerBackwardReferenceIndex { myRebuildRequestCause = e; } + private void logModification(String state) { + try { + File[] files = myIndicesDir.listFiles(); + if (files != null) { + LOG.info("indices state on " + + state + + ": " + + Arrays.stream(files).map(f -> f.getName() + ":" + f.lastModified()).collect(Collectors.joining(", "))); + } + } + catch (Exception ignored) { + } + } + private static void close(InvertedIndex index, CommonProcessors.FindFirstProcessor exceptionProcessor) { try { index.dispose(); diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildContext.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildContext.groovy index 78783677a31d..d568daaf668c 100644 --- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildContext.groovy +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildContext.groovy @@ -27,19 +27,13 @@ import org.jetbrains.jps.model.module.JpsModule * @author nik */ @CompileStatic -abstract class BuildContext { - AntBuilder ant - BuildMessages messages - BuildPaths paths - JpsProject project +abstract class BuildContext implements CompilationContext { ApplicationInfoProperties applicationInfo - JpsGantProjectBuilder projectBuilder ProductProperties productProperties WindowsDistributionCustomizer windowsDistributionCustomizer LinuxDistributionCustomizer linuxDistributionCustomizer MacDistributionCustomizer macDistributionCustomizer ProprietaryBuildTools proprietaryBuildTools - BuildOptions options BundledJreManager bundledJreManager /** @@ -77,14 +71,8 @@ abstract class BuildContext { abstract void notifyArtifactBuilt(String artifactPath) - abstract File findApplicationInfoInSources() - abstract JpsModule findApplicationInfoModule() - abstract JpsModule findRequiredModule(String name) - - abstract JpsModule findModule(String name) - abstract File findFileInModuleSources(String moduleName, String relativePath) abstract void signExeFile(String path) @@ -115,78 +103,3 @@ abstract class BuildContext { abstract BuildContext createCopyForProduct(ProductProperties productProperties, String projectHomeForCustomizers) } - -/** - * All paths are absolute and use '/' as a separator - */ -abstract class BuildPaths { - /** - * Path to a directory where idea/community Git repository is checked out - */ - String communityHome - - /** - * Path to a base directory of the project which will be compiled - */ - String projectHome - - /** - * Path to a directory where build script will store temporary and resulting files - */ - String buildOutputRoot - - /** - * Path to a directory where resulting artifacts will be placed - */ - String artifacts - - /** - * Path to a directory containing distribution files ('bin', 'lib', 'plugins' directories) common for all operating systems - */ - String distAll - - /** - * Path to a directory where temporary files required for a particular build step can be stored - */ - String temp - - /** - * Path to a directory containing JDK (currently Java 8) which is used to compile the project - */ - String jdkHome -} - -interface BuildMessages { - void info(String message) - void warning(String message) - - /** - * Report an error and stop the build process - */ - void error(String message) - - void error(String message, Throwable cause) - - void progress(String message) - def V block(String blockName, Closure body) - - void artifactBuild(String relativeArtifactPath) - - BuildMessages forkForParallelTask(String taskName) - - /** - * Must be invoked from the main thread when all forks have been finished - */ - void onAllForksFinished() - - /** - * Must be invoked for the forked instance on the thread where it is executing before the task is started. - * It's required to correctly handle messages from Ant tasks. - */ - void onForkStarted() - - /** - * Must be invoked for the forked instance on the thread where it is executing when the task is finished - */ - void onForkFinished() -} diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildMessages.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildMessages.groovy new file mode 100644 index 000000000000..d215762579b7 --- /dev/null +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildMessages.groovy @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2017 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.intellij.build + +import groovy.transform.CompileStatic + +/** + * @author nik + */ +@CompileStatic +interface BuildMessages { + void info(String message) + + void warning(String message) + + /** + * Report an error and stop the build process + */ + void error(String message) + + void error(String message, Throwable cause) + + void progress(String message) + + def V block(String blockName, Closure body) + + void artifactBuild(String relativeArtifactPath) + + BuildMessages forkForParallelTask(String taskName) + + /** + * Must be invoked from the main thread when all forks have been finished + */ + void onAllForksFinished() + + /** + * Must be invoked for the forked instance on the thread where it is executing before the task is started. + * It's required to correctly handle messages from Ant tasks. + */ + void onForkStarted() + + /** + * Must be invoked for the forked instance on the thread where it is executing when the task is finished + */ + void onForkFinished() +} diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildPaths.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildPaths.groovy new file mode 100644 index 000000000000..0e23f8b8f0a2 --- /dev/null +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildPaths.groovy @@ -0,0 +1,61 @@ +/* + * Copyright 2000-2017 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.intellij.build + +import groovy.transform.CompileStatic + +/** + * All paths are absolute and use '/' as a separator + * + * @author nik + */ +@CompileStatic +abstract class BuildPaths { + /** + * Path to a directory where idea/community Git repository is checked out + */ + String communityHome + + /** + * Path to a base directory of the project which will be compiled + */ + String projectHome + + /** + * Path to a directory where build script will store temporary and resulting files + */ + String buildOutputRoot + + /** + * Path to a directory where resulting artifacts will be placed + */ + String artifacts + + /** + * Path to a directory containing distribution files ('bin', 'lib', 'plugins' directories) common for all operating systems + */ + String distAll + + /** + * Path to a directory where temporary files required for a particular build step can be stored + */ + String temp + + /** + * Path to a directory containing JDK (currently Java 8) which is used to compile the project + */ + String jdkHome +} diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/CompilationContext.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/CompilationContext.groovy new file mode 100644 index 000000000000..534cee54595f --- /dev/null +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/CompilationContext.groovy @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2017 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.intellij.build + +import groovy.transform.CompileStatic +import org.jetbrains.jps.gant.JpsGantProjectBuilder +import org.jetbrains.jps.model.JpsProject +import org.jetbrains.jps.model.module.JpsModule + +/** + * @author nik + */ +@CompileStatic +interface CompilationContext { + AntBuilder getAnt() + BuildOptions getOptions() + BuildMessages getMessages() + BuildPaths getPaths() + JpsProject getProject() + JpsGantProjectBuilder getProjectBuilder() + + JpsModule findRequiredModule(String name) + + JpsModule findModule(String name) +} diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/CompilationTasks.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/CompilationTasks.groovy new file mode 100644 index 000000000000..3691dd4866e2 --- /dev/null +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/CompilationTasks.groovy @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2017 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.intellij.build + +import groovy.transform.CompileStatic +import org.jetbrains.intellij.build.impl.CompilationTasksImpl + +/** + * @author nik + */ +@CompileStatic +abstract class CompilationTasks { + abstract void compileAllModulesAndTests() + + abstract void compileModules(List moduleNames, List includingTestsInModules = []) + + static CompilationTasks create(CompilationContext context) { + return new CompilationTasksImpl(context) + } +} diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy index afc81b18fe20..3d6ee5cce10c 100644 --- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy @@ -26,11 +26,9 @@ import org.jetbrains.jps.model.JpsGlobal import org.jetbrains.jps.model.JpsProject import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes import org.jetbrains.jps.model.java.JavaSourceRootProperties -import org.jetbrains.jps.model.java.JpsJavaExtensionService import org.jetbrains.jps.model.module.JpsModule -import org.jetbrains.jps.model.serialization.JpsModelSerializationDataService -import org.jetbrains.jps.model.serialization.JpsProjectLoader -import org.jetbrains.jps.util.JpsPathUtil + +import java.util.function.BiFunction /** * @author nik @@ -38,61 +36,38 @@ import org.jetbrains.jps.util.JpsPathUtil @CompileStatic class BuildContextImpl extends BuildContext { private final JpsGlobal global + private final CompilationContextImpl compilationContext static BuildContextImpl create(AntBuilder ant, JpsGantProjectBuilder projectBuilder, JpsProject project, JpsGlobal global, String communityHome, String projectHome, ProductProperties productProperties, ProprietaryBuildTools proprietaryBuildTools, BuildOptions options) { - BuildMessages messages = BuildMessagesImpl.create(projectBuilder, ant.project) - communityHome = toCanonicalPath(communityHome) - if (["platform/build-scripts", "bin/log.xml", "build.txt"].any { !new File(communityHome, it).exists() }) { - messages.error("communityHome ($communityHome) doesn't point to a directory containing IntelliJ Community sources") - } - - projectHome = toCanonicalPath(projectHome) - def jdk8Home = toCanonicalPath(JdkUtils.computeJdkHome(messages, "jdk8Home", "$projectHome/build/jdk/1.8", "JDK_18_x64")) - WindowsDistributionCustomizer windowsDistributionCustomizer = productProperties.createWindowsCustomizer(projectHome) LinuxDistributionCustomizer linuxDistributionCustomizer = productProperties.createLinuxCustomizer(projectHome) MacDistributionCustomizer macDistributionCustomizer = productProperties.createMacCustomizer(projectHome) - if (project.modules.isEmpty()) { - loadProject(communityHome, projectHome, jdk8Home, project, global, messages) - } - else { - //todo[nik] currently we need this to build IDEA CE from IDEA UI build scripts. It would be better to create a separate JpsProject instance instead - messages.info("Skipping loading project because it's already loaded") - } - - def context = new BuildContextImpl(ant, messages, communityHome, projectHome, jdk8Home, project, global, projectBuilder, productProperties, + def compilationContext = CompilationContextImpl.create(ant, projectBuilder, project, global, communityHome, projectHome, + createBuildOutputRootEvaluator(projectHome, productProperties), options) + def context = new BuildContextImpl(compilationContext, productProperties, windowsDistributionCustomizer, linuxDistributionCustomizer, macDistributionCustomizer, - proprietaryBuildTools, options) - context.prepareForBuild() + proprietaryBuildTools) return context } - private BuildContextImpl(AntBuilder ant, BuildMessages messages, String communityHome, String projectHome, String jdk8Home, - JpsProject project, JpsGlobal global, JpsGantProjectBuilder projectBuilder, ProductProperties productProperties, + private BuildContextImpl(CompilationContextImpl compilationContext, ProductProperties productProperties, WindowsDistributionCustomizer windowsDistributionCustomizer, LinuxDistributionCustomizer linuxDistributionCustomizer, MacDistributionCustomizer macDistributionCustomizer, - ProprietaryBuildTools proprietaryBuildTools, - BuildOptions options) { - this.ant = ant - this.messages = messages - this.project = project - this.global = global - this.projectBuilder = projectBuilder + ProprietaryBuildTools proprietaryBuildTools) { + this.compilationContext = compilationContext + this.global = compilationContext.global this.productProperties = productProperties this.proprietaryBuildTools = proprietaryBuildTools - this.options = options this.windowsDistributionCustomizer = windowsDistributionCustomizer this.linuxDistributionCustomizer = linuxDistributionCustomizer this.macDistributionCustomizer = macDistributionCustomizer - def appInfoFile = findApplicationInfoInSources() + def appInfoFile = findApplicationInfoInSources(project, productProperties, messages) applicationInfo = new ApplicationInfoProperties(appInfoFile.absolutePath) - String buildOutputRoot = options.outputRootPath ?: "$projectHome/out/${productProperties.getOutputDirectoryName(applicationInfo)}" - paths = new BuildPathsImpl(communityHome, projectHome, buildOutputRoot, jdk8Home) bundledJreManager = new BundledJreManager(this, paths.buildOutputRoot) buildNumber = options.buildNumber ?: readSnapshotBuildNumber() @@ -102,109 +77,23 @@ class BuildContextImpl extends BuildContext { bootClassPathJarNames = ["bootstrap.jar", "extensions.jar", "util.jar", "jdom.jar", "log4j.jar", "trove4j.jar", "jna.jar"] } - private static void loadProject(String communityHome, String projectHome, String jdkHome, JpsProject project, JpsGlobal global, - BuildMessages messages) { - def bundledKotlinPath = "$communityHome/build/kotlinc" - if (!new File(bundledKotlinPath, "lib/kotlin-runtime.jar").exists()) { - messages.error("Could not find Kotlin runtime at $bundledKotlinPath/lib/kotlin-runtime.jar: run download_kotlin.gant script to download Kotlin JARs") - } - JpsModelSerializationDataService.getOrCreatePathVariablesConfiguration(global).addPathVariable("KOTLIN_BUNDLED", bundledKotlinPath) - - JdkUtils.defineJdk(global, "IDEA jdk", JdkUtils.computeJdkHome(messages, "jdkHome", "$projectHome/build/jdk/1.6", "JDK_16_x64")) - JdkUtils.defineJdk(global, "1.8", jdkHome) - - def pathVariables = JpsModelSerializationDataService.computeAllPathVariables(global) - JpsProjectLoader.loadProject(project, pathVariables, projectHome) - messages.info("Loaded project $projectHome: ${project.modules.size()} modules, ${project.libraryCollection.libraries.size()} libraries") - } - - private void prepareForBuild() { - checkCompilationOptions() - projectBuilder.buildIncrementally = options.incrementalCompilation - def dataDirName = options.incrementalCompilation ? ".jps-build-data-incremental" : ".jps-build-data" - projectBuilder.dataStorageRoot = new File(paths.buildOutputRoot, dataDirName) - def logDir = new File(paths.buildOutputRoot, "log") - FileUtil.delete(logDir) - projectBuilder.setupAdditionalLogging(new File("$logDir/compilation.log"), System.getProperty("intellij.build.debug.logging.categories", "")) - - def classesDirName = "classes" - def classesOutput = "$paths.buildOutputRoot/$classesDirName" - List outputDirectoriesToKeep = ["log"] - if (options.pathToCompiledClassesArchive != null) { - unpackCompiledClasses(messages, ant, classesOutput, options) - outputDirectoriesToKeep.add(classesDirName) - } - if (options.incrementalCompilation) { - outputDirectoriesToKeep.add(dataDirName) - outputDirectoriesToKeep.add(classesDirName) - } - if (!options.useCompiledClassesFromProjectOutput) { - projectBuilder.targetFolder = classesOutput - } - else { - def outputDir = JpsPathUtil.urlToFile(JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(project).outputUrl) - if (!outputDir.exists()) { - messages.error("$BuildOptions.USE_COMPILED_CLASSES_PROPERTY is enabled, but the project output directory $outputDir.absolutePath doesn't exist") - } - } - - suppressWarnings(project) - projectBuilder.exportModuleOutputProperties() - cleanOutput(outputDirectoriesToKeep) - } - - void cleanOutput(List outputDirectoriesToKeep) { - messages.block("Clean output") { - def outputPath = paths.buildOutputRoot - messages.progress("Cleaning output directory $outputPath") - new File(outputPath).listFiles()?.each { File file -> - if (outputDirectoriesToKeep.contains(file.name)) { - messages.info("Skipped cleaning for $file.absolutePath") - } - else { - FileUtil.delete(file) - } - } - } - } - - @CompileDynamic - private static void unpackCompiledClasses(BuildMessages messages, AntBuilder ant, String classesOutput, BuildOptions options) { - messages.block("Unpack compiled classes archive") { - FileUtil.delete(new File(classesOutput)) - ant.unzip(src: options.pathToCompiledClassesArchive, dest: classesOutput) - } - } - - private void checkCompilationOptions() { - if (options.useCompiledClassesFromProjectOutput && options.incrementalCompilation) { - messages.warning("'${BuildOptions.USE_COMPILED_CLASSES_PROPERTY}' is specified, so 'incremental compilation' option will be ignored") - options.incrementalCompilation = false - } - if (options.pathToCompiledClassesArchive != null && options.incrementalCompilation) { - messages.warning("Paths to the compiled project output is specified, so 'incremental compilation' option will be ignored") - options.incrementalCompilation = false - } - if (options.pathToCompiledClassesArchive != null && options.useCompiledClassesFromProjectOutput) { - messages.warning("'${BuildOptions.USE_COMPILED_CLASSES_PROPERTY}' is specified, so the archive with compiled project output won't be used") - options.pathToCompiledClassesArchive = null - } - } - - private static void suppressWarnings(JpsProject project) { - def compilerOptions = JpsJavaExtensionService.instance.getOrCreateCompilerConfiguration(project).currentCompilerOptions - compilerOptions.GENERATE_NO_WARNINGS = true - compilerOptions.DEPRECATION = false - compilerOptions.ADDITIONAL_OPTIONS_STRING = compilerOptions.ADDITIONAL_OPTIONS_STRING.replace("-Xlint:unchecked", "") - } - private String readSnapshotBuildNumber() { new File(paths.communityHome, "build.txt").text.trim() } - @Override - File findApplicationInfoInSources() { - JpsModule module = findApplicationInfoModule() + private static BiFunction createBuildOutputRootEvaluator(String projectHome, ProductProperties productProperties) { + return { JpsProject project, BuildMessages messages -> + def appInfoFile = findApplicationInfoInSources(project, productProperties, messages) + def applicationInfo = new ApplicationInfoProperties(appInfoFile.absolutePath) + return "$projectHome/out/${productProperties.getOutputDirectoryName(applicationInfo)}" + } as BiFunction + } + + static File findApplicationInfoInSources(JpsProject project, ProductProperties productProperties, BuildMessages messages) { + JpsModule module = project.modules.find {it.name == productProperties.applicationInfoModule } + if (module == null) { + messages.error("Cannot find required '${productProperties.applicationInfoModule}' module") + } def appInfoRelativePath = "idea/${productProperties.platformPrefix ?: ""}ApplicationInfo.xml" def appInfoFile = module.sourceRoots.collect { new File(it.file, appInfoRelativePath) }.find { it.exists() } if (appInfoFile == null) { @@ -218,17 +107,43 @@ class BuildContextImpl extends BuildContext { return findRequiredModule(productProperties.applicationInfoModule) } + @Override + AntBuilder getAnt() { + compilationContext.ant + } + + @Override + BuildOptions getOptions() { + compilationContext.options + } + + @Override + BuildMessages getMessages() { + compilationContext.messages + } + + @Override + BuildPaths getPaths() { + compilationContext.paths + } + + @Override + JpsProject getProject() { + compilationContext.project + } + + @Override + JpsGantProjectBuilder getProjectBuilder() { + compilationContext.projectBuilder + } + @Override JpsModule findRequiredModule(String name) { - def module = findModule(name) - if (module == null) { - messages.error("Cannot find required module '$name' in the project") - } - return module + return compilationContext.findRequiredModule(name) } JpsModule findModule(String name) { - project.modules.find { it.name == name } + return compilationContext.findModule(name) } @Override @@ -284,9 +199,10 @@ class BuildContextImpl extends BuildContext { BuildContext forkForParallelTask(String taskName) { def ant = new AntBuilder(ant.project) def messages = messages.forkForParallelTask(taskName) - def child = new BuildContextImpl(ant, messages, paths.communityHome, paths.projectHome, paths.jdkHome, project, global, projectBuilder, productProperties, + def compilationContextCopy = compilationContext.createCopy(ant, messages, options, createBuildOutputRootEvaluator(compilationContext.paths.projectHome, productProperties)) + def child = new BuildContextImpl(compilationContextCopy, productProperties, windowsDistributionCustomizer, linuxDistributionCustomizer, macDistributionCustomizer, - proprietaryBuildTools, options) + proprietaryBuildTools) child.paths.artifacts = paths.artifacts child.bundledJreManager.baseDirectoryForJre = bundledJreManager.baseDirectoryForJre return child @@ -300,11 +216,12 @@ class BuildContextImpl extends BuildContext { def options = new BuildOptions() options.useCompiledClassesFromProjectOutput = true - def copy = new BuildContextImpl(ant, messages, paths.communityHome, paths.projectHome, paths.jdkHome, project, global, projectBuilder, productProperties, - windowsDistributionCustomizer, linuxDistributionCustomizer, macDistributionCustomizer, proprietaryBuildTools, options) + def compilationContextCopy = compilationContext.createCopy(ant, messages, options, createBuildOutputRootEvaluator(paths.projectHome, productProperties)) + def copy = new BuildContextImpl(compilationContextCopy, productProperties, + windowsDistributionCustomizer, linuxDistributionCustomizer, macDistributionCustomizer, proprietaryBuildTools) copy.paths.artifacts = paths.artifacts copy.bundledJreManager.baseDirectoryForJre = bundledJreManager.baseDirectoryForJre - copy.prepareForBuild() + copy.compilationContext.prepareForBuild() return copy } @@ -362,21 +279,4 @@ class BuildContextImpl extends BuildContext { } messages.artifactBuild(relativePath) } - - private static String toCanonicalPath(String communityHome) { - FileUtil.toSystemIndependentName(new File(communityHome).canonicalPath) - } -} - -class BuildPathsImpl extends BuildPaths { - BuildPathsImpl(String communityHome, String projectHome, String buildOutputRoot, String jdkHome) { - this.communityHome = communityHome - this.projectHome = projectHome - this.buildOutputRoot = buildOutputRoot - this.jdkHome = jdkHome - artifacts = "$buildOutputRoot/artifacts" - distAll = "$buildOutputRoot/dist.all" - temp = "$buildOutputRoot/temp" - } - } diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy index 6051f8cc7767..612c0f7a8128 100644 --- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy @@ -20,6 +20,7 @@ import com.intellij.openapi.util.text.StringUtil import org.jetbrains.intellij.build.BuildContext import org.jetbrains.intellij.build.BuildOptions import org.jetbrains.intellij.build.BuildTasks +import org.jetbrains.intellij.build.CompilationTasks import org.jetbrains.intellij.build.ProductModulesLayout import org.jetbrains.jps.model.java.JavaResourceRootType import org.jetbrains.jps.model.java.JavaSourceRootType @@ -182,7 +183,7 @@ idea.fatal.error.notification=disabled } File patchApplicationInfo() { - def sourceFile = buildContext.findApplicationInfoInSources() + def sourceFile = BuildContextImpl.findApplicationInfoInSources(buildContext.project, buildContext.productProperties, buildContext.messages) def targetFile = new File(buildContext.paths.temp, sourceFile.name) def date = ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern("uuuuMMddHHmm")) BuildUtils.copyAndPatchFile(sourceFile.path, targetFile.path, @@ -244,8 +245,14 @@ idea.fatal.error.notification=disabled checkProductProperties() def patchedApplicationInfo = patchApplicationInfo() def distributionJARsBuilder = new DistributionJARsBuilder(buildContext, patchedApplicationInfo) - compileModules(buildContext.productProperties.productLayout.includedPluginModules + distributionJARsBuilder.platformModules + - buildContext.productProperties.additionalModulesToCompile, buildContext.productProperties.modulesToCompileTests) + compileModulesForDistribution(distributionJARsBuilder) + } + + private compileModulesForDistribution(DistributionJARsBuilder distributionJARsBuilder) { + def moduleNames = buildContext.productProperties.productLayout.includedPluginModules + distributionJARsBuilder.platformModules + + buildContext.productProperties.additionalModulesToCompile + + (buildContext.proprietaryBuildTools.scrambleTool?.additionalModulesToCompile ?: []) + compileModules(moduleNames, buildContext.productProperties.modulesToCompileTests) } @Override @@ -254,8 +261,7 @@ idea.fatal.error.notification=disabled def patchedApplicationInfo = patchApplicationInfo() def distributionJARsBuilder = new DistributionJARsBuilder(buildContext, patchedApplicationInfo) - compileModules(buildContext.productProperties.productLayout.includedPluginModules + distributionJARsBuilder.platformModules + - buildContext.productProperties.additionalModulesToCompile, buildContext.productProperties.modulesToCompileTests) + compileModulesForDistribution(distributionJARsBuilder) buildContext.messages.block("Build platform and plugin JARs") { if (buildContext.shouldBuildDistributions()) { distributionJARsBuilder.buildJARs() @@ -410,56 +416,7 @@ idea.fatal.error.notification=disabled @Override void compileModules(List moduleNames, List includingTestsInModules = []) { - if (buildContext.options.useCompiledClassesFromProjectOutput) { - buildContext.messages.info("Compilation skipped, the compiled classes from the project output will be used") - return - } - if (buildContext.options.pathToCompiledClassesArchive != null) { - buildContext.messages.info("Compilation skipped, the compiled classes from '${buildContext.options.pathToCompiledClassesArchive}' will be used") - return - } - - ensureKotlinCompilerAddedToClassPath() - - buildContext.projectBuilder.cleanOutput() - try { - if (moduleNames == null) { - buildContext.projectBuilder.buildProduction() - } - else { - List modulesToBuild = ((moduleNames as Set) + - buildContext.proprietaryBuildTools.scrambleTool?.additionalModulesToCompile ?: []) as List - List invalidModules = modulesToBuild.findAll {buildContext.findModule(it) == null} - if (!invalidModules.empty) { - buildContext.messages.warning("The following modules won't be compiled: $invalidModules") - } - buildContext.projectBuilder.buildModules(modulesToBuild.collect {buildContext.findModule(it)}.findAll {it != null}) - } - for (String moduleName : includingTestsInModules) { - buildContext.projectBuilder.makeModuleTests(buildContext.findModule(moduleName)) - } - } - catch (Throwable e) { - buildContext.messages.error("Compilation failed with exception: $e", e) - } - } - - private void ensureKotlinCompilerAddedToClassPath() { - try { - Class.forName("org.jetbrains.kotlin.jps.build.KotlinBuilder") - return - } - catch (ClassNotFoundException ignored) {} - - def kotlinPluginLibPath = "$buildContext.paths.communityHome/build/kotlinc/plugin/Kotlin/lib" - if (new File(kotlinPluginLibPath).exists()) { - ["jps/kotlin-jps-plugin.jar", "kotlin-plugin.jar", "kotlin-runtime.jar", "kotlin-reflect.jar"].each { - BuildUtils.addToJpsClassPath("$kotlinPluginLibPath/$it", buildContext.ant) - } - } - else { - buildContext.messages.error("Could not find Kotlin JARs at $kotlinPluginLibPath: run download_kotlin.gant script to download them") - } + CompilationTasks.create(buildContext).compileModules(moduleNames, includingTestsInModules) } private List runInParallel(List> tasks) { diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CompilationContextImpl.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CompilationContextImpl.groovy new file mode 100644 index 000000000000..30f07f09f4af --- /dev/null +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CompilationContextImpl.groovy @@ -0,0 +1,218 @@ +/* + * Copyright 2000-2017 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.intellij.build.impl + +import com.intellij.openapi.util.io.FileUtil +import groovy.transform.CompileDynamic +import groovy.transform.CompileStatic +import org.jetbrains.intellij.build.BuildMessages +import org.jetbrains.intellij.build.BuildOptions +import org.jetbrains.intellij.build.BuildPaths +import org.jetbrains.intellij.build.CompilationContext +import org.jetbrains.jps.gant.JpsGantProjectBuilder +import org.jetbrains.jps.model.JpsGlobal +import org.jetbrains.jps.model.JpsProject +import org.jetbrains.jps.model.java.JpsJavaExtensionService +import org.jetbrains.jps.model.module.JpsModule +import org.jetbrains.jps.model.serialization.JpsModelSerializationDataService +import org.jetbrains.jps.model.serialization.JpsProjectLoader +import org.jetbrains.jps.util.JpsPathUtil + +import java.util.function.BiFunction +/** + * @author nik + */ +@CompileStatic +class CompilationContextImpl implements CompilationContext { + final AntBuilder ant + final BuildOptions options + final BuildMessages messages + final BuildPaths paths + final JpsProject project + final JpsGlobal global + final JpsGantProjectBuilder projectBuilder + + static CompilationContextImpl create(AntBuilder ant, JpsGantProjectBuilder projectBuilder, JpsProject project, JpsGlobal global, + String communityHome, String projectHome, + BiFunction buildOutputRootEvaluator, BuildOptions options) { + def messages = BuildMessagesImpl.create(projectBuilder, ant.project) + communityHome = toCanonicalPath(communityHome) + if (["platform/build-scripts", "bin/log.xml", "build.txt"].any { !new File(communityHome, it).exists() }) { + messages.error("communityHome ($communityHome) doesn't point to a directory containing IntelliJ Community sources") + } + + projectHome = toCanonicalPath(projectHome) + def jdk8Home = toCanonicalPath(JdkUtils.computeJdkHome(messages, "jdk8Home", "$projectHome/build/jdk/1.8", "JDK_18_x64")) + if (project.modules.isEmpty()) { + loadProject(communityHome, projectHome, jdk8Home, project, global, messages) + } + else { + //todo[nik] currently we need this to build IDEA CE from IDEA UI build scripts. It would be better to create a separate JpsProject instance instead + messages.info("Skipping loading project because it's already loaded") + } + + def context = new CompilationContextImpl(ant, projectBuilder, project, global, communityHome, projectHome, jdk8Home, messages, + buildOutputRootEvaluator, options) + context.prepareForBuild() + return context + } + + private CompilationContextImpl(AntBuilder ant, JpsGantProjectBuilder projectBuilder, JpsProject project, JpsGlobal global, + String communityHome, String projectHome, String jdk8Home, BuildMessages messages, + BiFunction buildOutputRootEvaluator, BuildOptions options) { + this.ant = ant + this.project = project + this.global = global + this.options = options + this.projectBuilder = projectBuilder + this.messages = messages + String buildOutputRoot = options.outputRootPath ?: buildOutputRootEvaluator.apply(project, messages) + this.paths = new BuildPathsImpl(communityHome, projectHome, buildOutputRoot, jdk8Home) + } + + CompilationContextImpl createCopy(AntBuilder ant, BuildMessages messages, BuildOptions options, + BiFunction buildOutputRootEvaluator) { + return new CompilationContextImpl(ant, projectBuilder, project, global, paths.communityHome, paths.projectHome, paths.jdkHome, + messages, buildOutputRootEvaluator, options) + } + + private static void loadProject(String communityHome, String projectHome, String jdkHome, JpsProject project, JpsGlobal global, + BuildMessages messages) { + def bundledKotlinPath = "$communityHome/build/kotlinc" + if (!new File(bundledKotlinPath, "lib/kotlin-runtime.jar").exists()) { + messages.error( + "Could not find Kotlin runtime at $bundledKotlinPath/lib/kotlin-runtime.jar: run download_kotlin.gant script to download Kotlin JARs") + } + JpsModelSerializationDataService.getOrCreatePathVariablesConfiguration(global).addPathVariable("KOTLIN_BUNDLED", bundledKotlinPath) + + JdkUtils.defineJdk(global, "IDEA jdk", JdkUtils.computeJdkHome(messages, "jdkHome", "$projectHome/build/jdk/1.6", "JDK_16_x64")) + JdkUtils.defineJdk(global, "1.8", jdkHome) + + def pathVariables = JpsModelSerializationDataService.computeAllPathVariables(global) + JpsProjectLoader.loadProject(project, pathVariables, projectHome) + messages.info("Loaded project $projectHome: ${project.modules.size()} modules, ${project.libraryCollection.libraries.size()} libraries") + } + + void prepareForBuild() { + checkCompilationOptions() + projectBuilder.buildIncrementally = options.incrementalCompilation + def dataDirName = options.incrementalCompilation ? ".jps-build-data-incremental" : ".jps-build-data" + projectBuilder.dataStorageRoot = new File(paths.buildOutputRoot, dataDirName) + def logDir = new File(paths.buildOutputRoot, "log") + FileUtil.delete(logDir) + projectBuilder.setupAdditionalLogging(new File("$logDir/compilation.log"), System.getProperty("intellij.build.debug.logging.categories", "")) + + def classesDirName = "classes" + def classesOutput = "$paths.buildOutputRoot/$classesDirName" + List outputDirectoriesToKeep = ["log"] + if (options.pathToCompiledClassesArchive != null) { + unpackCompiledClasses(messages, ant, classesOutput, options) + outputDirectoriesToKeep.add(classesDirName) + } + if (options.incrementalCompilation) { + outputDirectoriesToKeep.add(dataDirName) + outputDirectoriesToKeep.add(classesDirName) + } + if (!options.useCompiledClassesFromProjectOutput) { + projectBuilder.targetFolder = classesOutput + } + else { + def outputDir = JpsPathUtil.urlToFile(JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(project).outputUrl) + if (!outputDir.exists()) { + messages.error("$BuildOptions.USE_COMPILED_CLASSES_PROPERTY is enabled, but the project output directory $outputDir.absolutePath doesn't exist") + } + } + + suppressWarnings(project) + projectBuilder.exportModuleOutputProperties() + cleanOutput(outputDirectoriesToKeep) + } + + void cleanOutput(List outputDirectoriesToKeep) { + messages.block("Clean output") { + def outputPath = paths.buildOutputRoot + messages.progress("Cleaning output directory $outputPath") + new File(outputPath).listFiles()?.each { File file -> + if (outputDirectoriesToKeep.contains(file.name)) { + messages.info("Skipped cleaning for $file.absolutePath") + } + else { + FileUtil.delete(file) + } + } + } + } + + + @CompileDynamic + private static void unpackCompiledClasses(BuildMessages messages, AntBuilder ant, String classesOutput, BuildOptions options) { + messages.block("Unpack compiled classes archive") { + FileUtil.delete(new File(classesOutput)) + ant.unzip(src: options.pathToCompiledClassesArchive, dest: classesOutput) + } + } + + private void checkCompilationOptions() { + if (options.useCompiledClassesFromProjectOutput && options.incrementalCompilation) { + messages.warning("'${BuildOptions.USE_COMPILED_CLASSES_PROPERTY}' is specified, so 'incremental compilation' option will be ignored") + options.incrementalCompilation = false + } + if (options.pathToCompiledClassesArchive != null && options.incrementalCompilation) { + messages.warning("Paths to the compiled project output is specified, so 'incremental compilation' option will be ignored") + options.incrementalCompilation = false + } + if (options.pathToCompiledClassesArchive != null && options.useCompiledClassesFromProjectOutput) { + messages.warning("'${BuildOptions.USE_COMPILED_CLASSES_PROPERTY}' is specified, so the archive with compiled project output won't be used") + options.pathToCompiledClassesArchive = null + } + } + + private static void suppressWarnings(JpsProject project) { + def compilerOptions = JpsJavaExtensionService.instance.getOrCreateCompilerConfiguration(project).currentCompilerOptions + compilerOptions.GENERATE_NO_WARNINGS = true + compilerOptions.DEPRECATION = false + compilerOptions.ADDITIONAL_OPTIONS_STRING = compilerOptions.ADDITIONAL_OPTIONS_STRING.replace("-Xlint:unchecked", "") + } + + @Override + JpsModule findRequiredModule(String name) { + def module = findModule(name) + if (module == null) { + messages.error("Cannot find required module '$name' in the project") + } + return module + } + + JpsModule findModule(String name) { + project.modules.find { it.name == name } + } + + private static String toCanonicalPath(String communityHome) { + FileUtil.toSystemIndependentName(new File(communityHome).canonicalPath) + } +} + +class BuildPathsImpl extends BuildPaths { + BuildPathsImpl(String communityHome, String projectHome, String buildOutputRoot, String jdkHome) { + this.communityHome = communityHome + this.projectHome = projectHome + this.buildOutputRoot = buildOutputRoot + this.jdkHome = jdkHome + artifacts = "$buildOutputRoot/artifacts" + distAll = "$buildOutputRoot/dist.all" + temp = "$buildOutputRoot/temp" + } +} diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CompilationTasksImpl.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CompilationTasksImpl.groovy new file mode 100644 index 000000000000..f21cc2a798e3 --- /dev/null +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CompilationTasksImpl.groovy @@ -0,0 +1,97 @@ +/* + * Copyright 2000-2017 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.intellij.build.impl + +import groovy.transform.CompileStatic +import org.jetbrains.intellij.build.CompilationContext +import org.jetbrains.intellij.build.CompilationTasks +/** + * @author nik + */ +@CompileStatic +class CompilationTasksImpl extends CompilationTasks { + private final CompilationContext context + + CompilationTasksImpl(CompilationContext context) { + this.context = context + } + + @Override + void compileModules(List moduleNames, List includingTestsInModules) { + if (context.options.useCompiledClassesFromProjectOutput) { + context.messages.info("Compilation skipped, the compiled classes from the project output will be used") + return + } + if (context.options.pathToCompiledClassesArchive != null) { + context.messages.info("Compilation skipped, the compiled classes from '${context.options.pathToCompiledClassesArchive}' will be used") + return + } + + ensureKotlinCompilerAddedToClassPath() + + context.projectBuilder.cleanOutput() + try { + if (moduleNames == null) { + if (includingTestsInModules == null) { + context.projectBuilder.buildAll() + } + else { + context.projectBuilder.buildProduction() + } + } + else { + List invalidModules = moduleNames.findAll { context.findModule(it) == null } + if (!invalidModules.empty) { + context.messages.warning("The following modules won't be compiled: $invalidModules") + } + context.projectBuilder.buildModules(moduleNames.collect { context.findModule(it) }.findAll { it != null }) + } + + if (includingTestsInModules != null) { + for (String moduleName : includingTestsInModules) { + context.projectBuilder.makeModuleTests(context.findModule(moduleName)) + } + } + } + catch (Throwable e) { + context.messages.error("Compilation failed with exception: $e", e) + } + } + + @Override + void compileAllModulesAndTests() { + compileModules(null, null) + } + + private void ensureKotlinCompilerAddedToClassPath() { + try { + Class.forName("org.jetbrains.kotlin.jps.build.KotlinBuilder") + return + } + catch (ClassNotFoundException ignored) { + } + + def kotlinPluginLibPath = "$context.paths.communityHome/build/kotlinc/plugin/Kotlin/lib" + if (new File(kotlinPluginLibPath).exists()) { + ["jps/kotlin-jps-plugin.jar", "kotlin-plugin.jar", "kotlin-runtime.jar", "kotlin-reflect.jar"].each { + BuildUtils.addToJpsClassPath("$kotlinPluginLibPath/$it", context.ant) + } + } + else { + context.messages.error("Could not find Kotlin JARs at $kotlinPluginLibPath: run download_kotlin.gant script to download them") + } + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/ClipboardSynchronizer.java b/platform/platform-impl/src/com/intellij/ide/ClipboardSynchronizer.java index 51c9db04f256..927838ca6ae3 100644 --- a/platform/platform-impl/src/com/intellij/ide/ClipboardSynchronizer.java +++ b/platform/platform-impl/src/com/intellij/ide/ClipboardSynchronizer.java @@ -146,7 +146,8 @@ public class ClipboardSynchronizer implements ApplicationComponentAdapter, Dispo return ClipboardUtil.handleClipboardSafely(myClipboardHandler::getContents, () -> null); } - public Object getData(DataFlavor dataFlavor) { + @Nullable + public Object getData(@NotNull DataFlavor dataFlavor) { return ClipboardUtil.handleClipboardSafely(() -> { try { return myClipboardHandler.getData(dataFlavor); @@ -204,7 +205,8 @@ public class ClipboardSynchronizer implements ApplicationComponentAdapter, Dispo return clipboard == null ? null: clipboard.getContents(this); } - public Object getData(DataFlavor dataFlavor) throws IOException, UnsupportedFlavorException { + @Nullable + public Object getData(@NotNull DataFlavor dataFlavor) throws IOException, UnsupportedFlavorException { Clipboard clipboard = getClipboard(); return clipboard == null ? null : clipboard.getData(dataFlavor); } @@ -256,7 +258,8 @@ public class ClipboardSynchronizer implements ApplicationComponentAdapter, Dispo } @Override - public Object getData(DataFlavor dataFlavor) throws IOException, UnsupportedFlavorException { + @Nullable + public Object getData(@NotNull DataFlavor dataFlavor) throws IOException, UnsupportedFlavorException { if (myFullTransferable == null) return super.getData(dataFlavor); Transferable contents = getContents(); return contents == null ? null : contents.getTransferData(dataFlavor); @@ -371,22 +374,12 @@ public class ClipboardSynchronizer implements ApplicationComponentAdapter, Dispo return ClipboardSynchronizer.areDataFlavorsAvailable(currentContent, flavors); } - try { - Collection contents = checkContentsQuick(); - if (contents != null) { - return ClipboardSynchronizer.areDataFlavorsAvailable(contents, flavors); - } + Collection contents = checkContentsQuick(); + if (contents != null) { + return ClipboardSynchronizer.areDataFlavorsAvailable(contents, flavors); + } - return super.areDataFlavorsAvailable(flavors); - } - catch (NullPointerException e) { - LOG.warn("Java bug #6322854", e); - return false; - } - catch (IllegalArgumentException e) { - LOG.warn("Java bug #7173464", e); - return false; - } + return super.areDataFlavorsAvailable(flavors); } @Override @@ -396,47 +389,28 @@ public class ClipboardSynchronizer implements ApplicationComponentAdapter, Dispo return currentContent; } - try { - final Collection contents = checkContentsQuick(); - if (contents != null && contents.isEmpty()) { - return null; - } + Collection contents = checkContentsQuick(); + if (contents != null && contents.isEmpty()) { + return null; + } - return super.getContents(); - } - catch (NullPointerException e) { - LOG.warn("Java bug #6322854", e); - return null; - } - catch (IllegalArgumentException e) { - LOG.warn("Java bug #7173464", e); - return null; - } + return super.getContents(); } @Override - public Object getData(DataFlavor dataFlavor) throws IOException, UnsupportedFlavorException { + @Nullable + public Object getData(@NotNull DataFlavor dataFlavor) throws IOException, UnsupportedFlavorException { Transferable currentContent = myCurrentContent; if (currentContent != null) { return currentContent.getTransferData(dataFlavor); } - try { - final Collection contents = checkContentsQuick(); - if (contents != null && contents.isEmpty()) { - return null; - } + Collection contents = checkContentsQuick(); + if (contents != null && !contents.contains(dataFlavor)) { + return null; + } - return super.getData(dataFlavor); - } - catch (NullPointerException e) { - LOG.warn("Java bug #6322854", e); - return null; - } - catch (IllegalArgumentException e) { - LOG.warn("Java bug #7173464", e); - return null; - } + return super.getData(dataFlavor); } @Override @@ -508,7 +482,8 @@ public class ClipboardSynchronizer implements ApplicationComponentAdapter, Dispo } @Override - public Object getData(DataFlavor dataFlavor) throws IOException, UnsupportedFlavorException { + @Nullable + public Object getData(@NotNull DataFlavor dataFlavor) throws IOException, UnsupportedFlavorException { return myContent.getTransferData(dataFlavor); } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ex/ClipboardUtil.java b/platform/platform-impl/src/com/intellij/openapi/application/ex/ClipboardUtil.java index 827096ed655b..3b1bd3fbe21e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/ex/ClipboardUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/ex/ClipboardUtil.java @@ -38,8 +38,14 @@ public class ClipboardUtil { else { LOG.warn(e); } - return onFail.get(); } + catch (NullPointerException e) { + LOG.warn("Java bug #6322854", e); + } + catch (IllegalArgumentException e) { + LOG.warn("Java bug #7173464", e); + } + return onFail.get(); } private static final String USE_LEGACY_MERGE_SORT_PROPERTY_NAME = "java.util.Arrays.useLegacyMergeSort"; diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/core/EduNames.java b/python/educational-core/student/src/com/jetbrains/edu/learning/core/EduNames.java index b20719033090..29a0cc2c7470 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/core/EduNames.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/core/EduNames.java @@ -38,7 +38,6 @@ public class EduNames { public static final String TESTS_FILE = "tests.py"; public static final String TEST_HELPER = "test_helper.py"; - public static final String SANDBOX_DIR = "Sandbox"; public static final String COURSE_META_FILE = "course.json"; public static final String PYCHARM_ADDITIONAL = "PyCharm additional materials"; public static final String PYCHARM = "PyCharm"; diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java b/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java index 935bd3c5c3cb..58ae0c9c5774 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java @@ -109,7 +109,6 @@ public class StudyGenerator { lesson.setIndex(i); createLesson(lesson, baseDir, resourceRoot, project); } - baseDir.createChildDirectory(project, EduNames.SANDBOX_DIR); File[] files = resourceRoot.listFiles( (dir, name) -> !name.contains(EduNames.LESSON) && !name.equals(EduNames.COURSE_META_FILE) && !name.equals(EduNames.HINTS)); if (files != null) { diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/projectView/CourseDirectoryNode.java b/python/educational-core/student/src/com/jetbrains/edu/learning/projectView/CourseDirectoryNode.java index e990a00c525f..13f7d71dd651 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/projectView/CourseDirectoryNode.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/projectView/CourseDirectoryNode.java @@ -43,9 +43,6 @@ public class CourseDirectoryNode extends StudyDirectoryNode { Object value = childNode.getValue(); if (value instanceof PsiDirectory) { PsiDirectory directory = (PsiDirectory)value; - if (EduNames.SANDBOX_DIR.equals(directory.getName())) { - return new SandboxDirectoryNode(myProject, directory, myViewSettings); - } Lesson lesson = myCourse.getLesson(directory.getName()); return lesson != null ? createChildDirectoryNode(lesson, directory) : null; } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/projectView/SandboxDirectoryNode.java b/python/educational-core/student/src/com/jetbrains/edu/learning/projectView/SandboxDirectoryNode.java deleted file mode 100644 index bd340ed68658..000000000000 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/projectView/SandboxDirectoryNode.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.jetbrains.edu.learning.projectView; - -import com.intellij.ide.projectView.PresentationData; -import com.intellij.ide.projectView.ViewSettings; -import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode; -import com.intellij.ide.util.treeView.AbstractTreeNode; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiDirectory; -import com.jetbrains.edu.learning.core.EduNames; -import com.jetbrains.edu.learning.courseFormat.StudyItem; -import icons.InteractiveLearningIcons; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class SandboxDirectoryNode extends StudyDirectoryNode { - public SandboxDirectoryNode(@NotNull Project project, - PsiDirectory value, - ViewSettings viewSettings) { - super(project, value, viewSettings); - } - - @Nullable - @Override - public AbstractTreeNode modifyChildNode(AbstractTreeNode childNode) { - return childNode; - } - - @Override - public PsiDirectoryNode createChildDirectoryNode(StudyItem item, PsiDirectory value) { - return null; - } - - @Override - protected void updateImpl(PresentationData data) { - setPresentation(data, EduNames.SANDBOX_DIR, InteractiveLearningIcons.Sandbox); - } - - @Override - public int getWeight() { - return Integer.MAX_VALUE; - } -} diff --git a/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionContributor.java b/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionContributor.java index 29eea8c89d8c..3890229ee4c8 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionContributor.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionContributor.java @@ -58,7 +58,7 @@ public class HtmlCompletionContributor extends CompletionContributor { }); } - private static boolean hasHtmlAttributesCompletion(PsiElement position) { + public static boolean hasHtmlAttributesCompletion(PsiElement position) { if (PsiTreeUtil.getParentOfType(position, HtmlTag.class, false) != null) { return true; }