Unify extension point and extension registration in plugin and cli

This commit is contained in:
Zalim Bashorov
2014-11-19 01:01:26 +03:00
parent 14d663bcab
commit 912727e5d2
12 changed files with 206 additions and 47 deletions
@@ -0,0 +1,60 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ide.plugins;
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.ExtensionsArea;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.List;
import java.util.Set;
// TODO drop this temporary hack to access to PluginManagerCore methods when CoreApplicationEnvironment got similar features.
public class PluginManagerCoreProxy {
private PluginManagerCoreProxy() {}
@Nullable
public static IdeaPluginDescriptorImpl loadDescriptorFromDir(@NotNull File file, @NotNull String fileName) {
return PluginManagerCore.loadDescriptorFromDir(file, fileName);
}
@Nullable
public static IdeaPluginDescriptorImpl loadDescriptorFromJar(@NotNull File file, @NotNull String fileName) {
return PluginManagerCore.loadDescriptorFromJar(file, fileName);
}
// copied as is from PluginManagerCore#registerExtensionPointsAndExtensions
public static void registerExtensionPointsAndExtensions(ExtensionsArea area, List<IdeaPluginDescriptorImpl> loadedPlugins) {
for (IdeaPluginDescriptorImpl descriptor : loadedPlugins) {
descriptor.registerExtensionPoints(area);
}
Set<String> epNames = ContainerUtil.newHashSet();
for (ExtensionPoint point : area.getExtensionPoints()) {
epNames.add(point.getName());
}
for (IdeaPluginDescriptorImpl descriptor : loadedPlugins) {
for (String epName : epNames) {
descriptor.registerExtensions(area, epName);
}
}
}
}
@@ -19,8 +19,6 @@ package org.jetbrains.jet.cli.js;
import com.google.common.base.Joiner;
import com.google.common.base.Predicates;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.extensions.ExtensionsArea;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -45,13 +43,11 @@ import org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity;
import org.jetbrains.jet.cli.common.messages.MessageCollector;
import org.jetbrains.jet.cli.common.output.outputUtils.OutputUtilsPackage;
import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentUtil;
import org.jetbrains.jet.cli.jvm.compiler.EnvironmentConfigFiles;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.config.CompilerConfiguration;
import org.jetbrains.jet.config.Services;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.DiagnosticsWithSuppression;
import org.jetbrains.k2js.analyze.SuppressUnusedParameterForJsNative;
import org.jetbrains.k2js.analyze.SuppressWarningsFromExternalModules;
import org.jetbrains.jet.utils.PathUtil;
import org.jetbrains.k2js.analyze.TopDownAnalyzerFacadeForJS;
import org.jetbrains.k2js.config.*;
@@ -95,14 +91,8 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector);
CompileEnvironmentUtil.addSourceFilesCheckingForDuplicates(configuration, arguments.freeArgs);
JetCoreEnvironment environmentForJS = JetCoreEnvironment.createForProduction(rootDisposable, configuration);
ExtensionsArea rootArea = Extensions.getRootArea();
rootArea.getExtensionPoint(DiagnosticsWithSuppression.SuppressStringProvider.EP_NAME)
.registerExtension(new SuppressUnusedParameterForJsNative());
rootArea.getExtensionPoint(DiagnosticsWithSuppression.DiagnosticSuppressor.EP_NAME)
.registerExtension(new SuppressWarningsFromExternalModules());
JetCoreEnvironment environmentForJS =
JetCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JS_CONFIG_FILES);
Project project = environmentForJS.getProject();
List<JetFile> sourcesFiles = environmentForJS.getSourceFiles();
@@ -0,0 +1,35 @@
/*
* Copyright 2010-2014 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.jet.cli.jvm.compiler;
import java.io.File;
import java.util.Arrays;
import java.util.List;
public class EnvironmentConfigFiles {
private static final String EXTENSIONS_DIR = "extensions";
private static final String COMMON_CONFIG_FILE = EXTENSIONS_DIR + File.separator + "common.xml";
private static final String JVM_CONFIG_FILE = EXTENSIONS_DIR + File.separator + "kotlin2jvm.xml";
private static final String JS_CONFIG_FILE = EXTENSIONS_DIR + File.separator + "kotlin2js.xml";
public static final List<String> JVM_CONFIG_FILES = Arrays.asList(COMMON_CONFIG_FILE, JVM_CONFIG_FILE);
public static final List<String> JS_CONFIG_FILES = Arrays.asList(COMMON_CONFIG_FILE, JS_CONFIG_FILE);
private EnvironmentConfigFiles() {}
}
@@ -21,6 +21,8 @@ import com.intellij.core.CoreApplicationEnvironment;
import com.intellij.core.CoreJavaFileManager;
import com.intellij.core.JavaCoreApplicationEnvironment;
import com.intellij.core.JavaCoreProjectEnvironment;
import com.intellij.ide.plugins.IdeaPluginDescriptorImpl;
import com.intellij.ide.plugins.PluginManagerCoreProxy;
import com.intellij.lang.java.JavaParserDefinition;
import com.intellij.mock.MockApplication;
import com.intellij.mock.MockProject;
@@ -54,7 +56,6 @@ import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import org.jetbrains.jet.lang.parsing.JetScriptDefinitionProvider;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.CodeAnalyzerInitializer;
import org.jetbrains.jet.lang.resolve.DiagnosticsWithSuppression;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinBinaryClassCache;
import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileFinderFactory;
import org.jetbrains.jet.lang.resolve.lazy.declarations.CliDeclarationProviderFactoryService;
@@ -64,9 +65,9 @@ import org.jetbrains.jet.utils.PathUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.intellij.core.CoreApplicationEnvironment.registerApplicationExtensionPoint;
import static org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity.ERROR;
import static org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity.WARNING;
@@ -81,6 +82,15 @@ public class JetCoreEnvironment {
public static JetCoreEnvironment createForProduction(
@NotNull Disposable parentDisposable,
@NotNull CompilerConfiguration configuration
) {
return createForProduction(parentDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
}
@NotNull
public static JetCoreEnvironment createForProduction(
@NotNull Disposable parentDisposable,
@NotNull CompilerConfiguration configuration,
@NotNull List<String> configFilePaths
) {
// JPS may run many instances of the compiler in parallel (there's an option for compiling independent modules in parallel in IntelliJ)
// All projects share the same ApplicationEnvironment, and when the last project is disposed, the ApplicationEnvironment is disposed as well
@@ -95,7 +105,8 @@ public class JetCoreEnvironment {
}
});
JetCoreEnvironment environment =
new JetCoreEnvironment(parentDisposable, getOrCreateApplicationEnvironmentForProduction(), configuration);
new JetCoreEnvironment(parentDisposable, getOrCreateApplicationEnvironmentForProduction(configFilePaths), configuration);
synchronized (APPLICATION_LOCK) {
ourProjectCount++;
}
@@ -104,18 +115,31 @@ public class JetCoreEnvironment {
@TestOnly
@NotNull
public static JetCoreEnvironment createForTests(@NotNull Disposable parentDisposable, @NotNull CompilerConfiguration configuration) {
public static JetCoreEnvironment createForTests(
@NotNull Disposable parentDisposable,
@NotNull CompilerConfiguration configuration
) {
return createForTests(parentDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
}
@TestOnly
@NotNull
public static JetCoreEnvironment createForTests(
@NotNull Disposable parentDisposable,
@NotNull CompilerConfiguration configuration,
@NotNull List<String> extensionConfigs
) {
// Tests are supposed to create a single project and dispose it right after use
return new JetCoreEnvironment(parentDisposable, createApplicationEnvironment(parentDisposable), configuration);
return new JetCoreEnvironment(parentDisposable, createApplicationEnvironment(parentDisposable, extensionConfigs), configuration);
}
@NotNull
private static JavaCoreApplicationEnvironment getOrCreateApplicationEnvironmentForProduction() {
private static JavaCoreApplicationEnvironment getOrCreateApplicationEnvironmentForProduction(@NotNull List<String> configFilePaths) {
synchronized (APPLICATION_LOCK) {
if (ourApplicationEnvironment != null) return ourApplicationEnvironment;
Disposable parentDisposable = Disposer.newDisposable();
ourApplicationEnvironment = createApplicationEnvironment(parentDisposable);
ourApplicationEnvironment = createApplicationEnvironment(parentDisposable, configFilePaths);
ourProjectCount = 0;
Disposer.register(parentDisposable, new Disposable() {
@Override
@@ -139,10 +163,15 @@ public class JetCoreEnvironment {
}
@NotNull
private static JavaCoreApplicationEnvironment createApplicationEnvironment(@NotNull Disposable parentDisposable) {
private static JavaCoreApplicationEnvironment createApplicationEnvironment(
@NotNull Disposable parentDisposable,
@NotNull List<String> configFilePaths
) {
JavaCoreApplicationEnvironment applicationEnvironment = new JavaCoreApplicationEnvironment(parentDisposable);
registerApplicationExtensionPointsForCLI();
for (String config : configFilePaths) {
registerApplicationExtensionPointsAndExtensionsFrom(config);
}
registerApplicationServicesForCLI(applicationEnvironment);
registerApplicationServices(applicationEnvironment);
@@ -150,12 +179,22 @@ public class JetCoreEnvironment {
return applicationEnvironment;
}
private static void registerApplicationExtensionPointsForCLI() {
registerApplicationExtensionPoint(DiagnosticsWithSuppression.SuppressStringProvider.EP_NAME,
DiagnosticsWithSuppression.SuppressStringProvider.class);
private static void registerApplicationExtensionPointsAndExtensionsFrom(String configFilePath) {
IdeaPluginDescriptorImpl descriptor;
File jar = PathUtil.getPathUtilJar();
if (jar.isFile()) {
descriptor = PluginManagerCoreProxy.loadDescriptorFromJar(jar, configFilePath);
}
else {
// hack for load extensions when compiler run directly from out directory(e.g. in tests)
File srcDir = jar.getParentFile().getParentFile().getParentFile();
File pluginDir = new File(srcDir, "idea/src");
descriptor = PluginManagerCoreProxy.loadDescriptorFromDir(pluginDir, configFilePath);
}
registerApplicationExtensionPoint(DiagnosticsWithSuppression.DiagnosticSuppressor.EP_NAME,
DiagnosticsWithSuppression.DiagnosticSuppressor.class);
assert descriptor != null : "Can not load descriptor from " + configFilePath + " relative to " + jar;
PluginManagerCoreProxy.registerExtensionPointsAndExtensions(Extensions.getRootArea(), Collections.singletonList(descriptor));
}
private static void registerApplicationServicesForCLI(@NotNull JavaCoreApplicationEnvironment applicationEnvironment) {