mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
platform: make lang substitutor dynamic IDEA-226264
GitOrigin-RevId: 53f525ee77d1391b04a32632e36c258f71c98ba4
This commit is contained in:
committed by
intellij-monorepo-bot
parent
0ebc97022c
commit
d3759e6942
@@ -0,0 +1,43 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.lang
|
||||
|
||||
import com.intellij.ide.plugins.loadExtensionWithText
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.fileTypes.PlainTextLanguage
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.LanguageSubstitutor
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
|
||||
|
||||
class LanguageSubstitutorLoadUnloadTest : LightJavaCodeInsightFixtureTestCase() {
|
||||
|
||||
fun testBefore() {
|
||||
myFixture.configureByText("dummy.txt", "package hello;")
|
||||
}
|
||||
|
||||
fun testLoadUnload() {
|
||||
val beforeLoading = myFixture.configureByText("dummy.txt", "package hello;")
|
||||
UsefulTestCase.assertInstanceOf(beforeLoading.language, PlainTextLanguage::class.java)
|
||||
|
||||
val virtualFile = beforeLoading.virtualFile
|
||||
val text = "<lang.substitutor language=\"TEXT\" implementationClass=\"${TextToJavaSubstitutor::class.java.name}\"/>"
|
||||
val disposable = loadExtensionWithText(text, javaClass.classLoader)
|
||||
val psiManager = PsiManager.getInstance(myFixture.project)
|
||||
val afterLoading = psiManager.findFile(virtualFile)
|
||||
UsefulTestCase.assertInstanceOf(afterLoading!!.language, JavaLanguage::class.java)
|
||||
|
||||
Disposer.dispose(disposable)
|
||||
val afterUnloading = psiManager.findFile(virtualFile)
|
||||
UsefulTestCase.assertInstanceOf(afterUnloading!!.language, PlainTextLanguage::class.java)
|
||||
}
|
||||
|
||||
private class TextToJavaSubstitutor : LanguageSubstitutor() {
|
||||
override fun getLanguage(file: VirtualFile,
|
||||
project: Project): Language? {
|
||||
return if (file.name.startsWith("dummy")) JavaLanguage.INSTANCE else null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,9 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.Service;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.extensions.ExtensionPoint;
|
||||
import com.intellij.openapi.extensions.ExtensionPointListener;
|
||||
import com.intellij.openapi.extensions.PluginDescriptor;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManagerListener;
|
||||
import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl;
|
||||
@@ -34,6 +37,7 @@ import com.intellij.psi.impl.DebugUtil;
|
||||
import com.intellij.psi.impl.PsiManagerImpl;
|
||||
import com.intellij.psi.impl.PsiTreeChangeEventImpl;
|
||||
import com.intellij.util.FileContentUtilCore;
|
||||
import com.intellij.util.KeyedLazyInstance;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -66,6 +70,31 @@ public final class PsiVFSListener implements BulkFileListener {
|
||||
@Override
|
||||
public void runActivity(@NotNull Project project) {
|
||||
MessageBusConnection connection = project.getMessageBus().connect();
|
||||
|
||||
ExtensionPoint<KeyedLazyInstance<LanguageSubstitutor>> point = LanguageSubstitutors.getInstance().getPoint();
|
||||
if (point != null) {
|
||||
point.addExtensionPointListener(
|
||||
new ExtensionPointListener<KeyedLazyInstance<LanguageSubstitutor>>() {
|
||||
|
||||
@Override
|
||||
public void extensionRemoved(@NotNull KeyedLazyInstance<LanguageSubstitutor> extension,
|
||||
@NotNull PluginDescriptor pluginDescriptor) {
|
||||
if (project.isDisposed()) return;
|
||||
|
||||
PsiManagerImpl psiManager = (PsiManagerImpl)PsiManager.getInstance(project);
|
||||
((FileManagerImpl)(psiManager.getFileManager())).processFileTypesChanged(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void extensionAdded(@NotNull KeyedLazyInstance<LanguageSubstitutor> extension,
|
||||
@NotNull PluginDescriptor pluginDescriptor) {
|
||||
if (project.isDisposed()) return;
|
||||
PsiManagerImpl psiManager = (PsiManagerImpl)PsiManager.getInstance(project);
|
||||
((FileManagerImpl)(psiManager.getFileManager())).processFileTypesChanged(true);
|
||||
}
|
||||
}, false, project);
|
||||
}
|
||||
|
||||
connection.subscribe(ProjectTopics.PROJECT_ROOTS, new MyModuleRootListener(project));
|
||||
connection.subscribe(FileTypeManager.TOPIC, new FileTypeListener() {
|
||||
@Override
|
||||
|
||||
@@ -32,14 +32,16 @@ public class FileBasedIndexSwitcher {
|
||||
FileBasedIndexImpl.LOG.assertTrue(mySemaphore.isUp());
|
||||
mySemaphore.down();
|
||||
|
||||
for (Project project : ProjectManager.getInstance().getOpenProjects()) {
|
||||
DumbService.getInstance(project).queueTask(new DumbModeTask() {
|
||||
@Override
|
||||
public void performInDumbMode(@NotNull ProgressIndicator indicator) {
|
||||
indicator.setText(IdeBundle.message("progress.indexing.reload"));
|
||||
mySemaphore.waitFor();
|
||||
}
|
||||
});
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
for (Project project : ProjectManager.getInstance().getOpenProjects()) {
|
||||
DumbService.getInstance(project).queueTask(new DumbModeTask() {
|
||||
@Override
|
||||
public void performInDumbMode(@NotNull ProgressIndicator indicator) {
|
||||
indicator.setText(IdeBundle.message("progress.indexing.reload"));
|
||||
mySemaphore.waitFor();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
myFileBasedIndex.performShutdown(true);
|
||||
|
||||
@@ -411,7 +411,7 @@
|
||||
|
||||
<extensionPoint name="codeInsight.surroundWithRangeAdjuster" interface="com.intellij.codeInsight.generation.surroundWith.SurroundWithRangeAdjuster" dynamic="true"/>
|
||||
|
||||
<extensionPoint name="lang.substitutor" beanClass="com.intellij.lang.LanguageExtensionPoint">
|
||||
<extensionPoint dynamic="true" name="lang.substitutor" beanClass="com.intellij.lang.LanguageExtensionPoint">
|
||||
<with attribute="implementationClass" implements="com.intellij.psi.LanguageSubstitutor"/>
|
||||
</extensionPoint>
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.ide.plugins
|
||||
|
||||
import com.intellij.ide.plugins.DynamicPlugins.loadPlugin
|
||||
import com.intellij.ide.plugins.DynamicPlugins.unloadPlugin
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.testFramework.assertions.Assertions
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import kotlin.math.abs
|
||||
|
||||
fun loadDescriptorInTest(dir: Path): IdeaPluginDescriptorImpl {
|
||||
Assertions.assertThat(dir).exists()
|
||||
PluginManagerCore.ourPluginError = null
|
||||
val parentContext = DescriptorListLoadingContext.createSingleDescriptorContext(emptySet())
|
||||
val result = DescriptorLoadingContext(parentContext, /* isBundled = */ false, /* isEssential = */ true,
|
||||
PathBasedJdomXIncluder.DEFAULT_PATH_RESOLVER).use { context ->
|
||||
PluginManagerCore.loadDescriptorFromFileOrDir(dir, PluginManagerCore.PLUGIN_XML, context, Files.isDirectory(dir))
|
||||
}
|
||||
if (result == null) {
|
||||
@Suppress("USELESS_CAST")
|
||||
Assertions.assertThat(PluginManagerCore.ourPluginError as String?).isNotNull
|
||||
PluginManagerCore.ourPluginError = null
|
||||
}
|
||||
return result!!
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun loadExtensionWithText(extensionTag: String, loader: ClassLoader, ns: String = "com.intellij"): Disposable {
|
||||
val name = "test" + abs(extensionTag.hashCode())
|
||||
val text = """<idea-plugin>
|
||||
<name>$name</name>
|
||||
<extensions defaultExtensionNs="$ns">
|
||||
$extensionTag
|
||||
</extensions>
|
||||
</idea-plugin>"""
|
||||
|
||||
return loadPluginWithText(text, loader)
|
||||
}
|
||||
|
||||
fun loadPluginWithText(pluginXml: String, loader: ClassLoader): Disposable {
|
||||
val directory = FileUtil.createTempDirectory("test", "test", true)
|
||||
val plugin = File(directory, "/plugin/META-INF/plugin.xml")
|
||||
FileUtil.createParentDirs(plugin)
|
||||
FileUtil.writeToFile(plugin, pluginXml)
|
||||
var descriptor = loadDescriptorInTest(plugin.toPath().parent.parent)
|
||||
descriptor.setLoader(loader)
|
||||
loadPlugin(descriptor, false)
|
||||
|
||||
return Disposable {
|
||||
descriptor = loadDescriptorInTest(plugin.toPath().parent.parent)
|
||||
unloadPlugin(descriptor, false)
|
||||
}
|
||||
}
|
||||
@@ -379,19 +379,4 @@ private val testDataPath: String
|
||||
|
||||
private fun loadDescriptorInTest(dirName: String): IdeaPluginDescriptorImpl {
|
||||
return loadDescriptorInTest(Paths.get(testDataPath, dirName))
|
||||
}
|
||||
|
||||
internal fun loadDescriptorInTest(dir: Path): IdeaPluginDescriptorImpl {
|
||||
assertThat(dir).exists()
|
||||
PluginManagerCore.ourPluginError = null
|
||||
val parentContext = DescriptorListLoadingContext.createSingleDescriptorContext(emptySet())
|
||||
val result = DescriptorLoadingContext(parentContext, /* isBundled = */ false, /* isEssential = */ true, PathBasedJdomXIncluder.DEFAULT_PATH_RESOLVER).use { context ->
|
||||
PluginManagerCore.loadDescriptorFromFileOrDir(dir, PluginManagerCore.PLUGIN_XML, context, Files.isDirectory(dir))
|
||||
}
|
||||
if (result == null) {
|
||||
@Suppress("USELESS_CAST")
|
||||
assertThat(PluginManagerCore.ourPluginError as String?).isNotNull()
|
||||
PluginManagerCore.ourPluginError = null
|
||||
}
|
||||
return result!!
|
||||
}
|
||||
Reference in New Issue
Block a user