mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-14 18:05:27 +07:00
IJPL-149476 convert InspectopediaExtractor to language with modern API
GitOrigin-RevId: 9721f95f85456710dd49deb96d54f65e1da40e0e
This commit is contained in:
committed by
intellij-monorepo-bot
parent
7c5bb9bd3c
commit
3eaa41d59a
@@ -1,244 +1,247 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.inspectopedia.extractor;
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
@file:Suppress("ReplacePutWithAssignment")
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
import com.intellij.codeInspection.InspectionEP;
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
import com.intellij.codeInspection.ex.*;
|
||||
import com.intellij.codeInspection.options.*;
|
||||
import com.intellij.ide.plugins.PluginManager;
|
||||
import com.intellij.inspectopedia.extractor.data.Inspection;
|
||||
import com.intellij.inspectopedia.extractor.data.OptionsPanelInfo;
|
||||
import com.intellij.inspectopedia.extractor.data.Plugin;
|
||||
import com.intellij.inspectopedia.extractor.data.Plugins;
|
||||
import com.intellij.inspectopedia.extractor.utils.HtmlUtils;
|
||||
import com.intellij.openapi.application.ApplicationInfo;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ApplicationStarter;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.util.text.HtmlChunk;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
package com.intellij.inspectopedia.extractor
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException
|
||||
import com.fasterxml.jackson.databind.MapperFeature
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.fasterxml.jackson.databind.SerializationFeature
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper
|
||||
import com.intellij.codeInspection.ex.InspectionMetaInformationService
|
||||
import com.intellij.codeInspection.options.*
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor
|
||||
import com.intellij.ide.plugins.PluginManager
|
||||
import com.intellij.inspectopedia.extractor.InspectopediaExtractor.Companion.getMyText
|
||||
import com.intellij.inspectopedia.extractor.data.Inspection
|
||||
import com.intellij.inspectopedia.extractor.data.OptionsPanelInfo
|
||||
import com.intellij.inspectopedia.extractor.data.Plugin
|
||||
import com.intellij.inspectopedia.extractor.data.Plugins
|
||||
import com.intellij.inspectopedia.extractor.utils.HtmlUtils
|
||||
import com.intellij.openapi.application.ApplicationInfo
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ApplicationStarter
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import java.io.IOException
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.util.*
|
||||
import java.util.function.Function
|
||||
import java.util.stream.Collectors
|
||||
|
||||
final class InspectopediaExtractor implements ApplicationStarter {
|
||||
private static final Logger LOG = Logger.getInstance(InspectopediaExtractor.class);
|
||||
private static final Map<String, ObjectMapper> ASSETS = new HashMap<>();
|
||||
private class InspectopediaExtractor : ApplicationStarter {
|
||||
private val assets: MutableMap<String, ObjectMapper> = HashMap()
|
||||
|
||||
static {
|
||||
JsonMapper jsonMapper = JsonMapper.builder()
|
||||
init {
|
||||
val jsonMapper = JsonMapper.builder()
|
||||
.enable(SerializationFeature.INDENT_OUTPUT)
|
||||
.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)
|
||||
.build();
|
||||
ASSETS.put("json", jsonMapper);
|
||||
.build()
|
||||
assets.put("json", jsonMapper)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void main(@NotNull List<String> args) {
|
||||
final int size = args.size();
|
||||
override fun main(args: List<String>) {
|
||||
val size = args.size
|
||||
if (size != 2) {
|
||||
LOG.error("Usage: inspectopedia-generator <output directory>");
|
||||
System.exit(-1);
|
||||
LOG.error("Usage: inspectopedia-generator <output directory>")
|
||||
System.exit(-1)
|
||||
}
|
||||
|
||||
ApplicationInfo appInfo = ApplicationInfo.getInstance();
|
||||
String IDE_CODE = appInfo.getBuild().getProductCode().toLowerCase(Locale.getDefault());
|
||||
String IDE_NAME = appInfo.getVersionName();
|
||||
String IDE_VERSION = appInfo.getShortVersion();
|
||||
String ASSET_FILENAME = IDE_CODE + "-inspections.";
|
||||
val appInfo = ApplicationInfo.getInstance()
|
||||
val IDE_CODE = appInfo.build.productCode.lowercase(Locale.getDefault())
|
||||
val IDE_NAME = appInfo.versionName
|
||||
val IDE_VERSION = appInfo.shortVersion
|
||||
val ASSET_FILENAME = "$IDE_CODE-inspections."
|
||||
|
||||
final String outputDirectory = args.get(1);
|
||||
final Path rootOutputPath = Path.of(outputDirectory).toAbsolutePath();
|
||||
final Path outputPath = rootOutputPath.resolve(IDE_CODE);
|
||||
val outputDirectory = args[1]
|
||||
val rootOutputPath = Path.of(outputDirectory).toAbsolutePath()
|
||||
val outputPath = rootOutputPath.resolve(IDE_CODE)
|
||||
|
||||
try {
|
||||
Files.createDirectories(outputPath);
|
||||
Files.createDirectories(outputPath)
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error("Output directory does not exist and could not be created");
|
||||
System.exit(-1);
|
||||
catch (e: IOException) {
|
||||
LOG.error("Output directory does not exist and could not be created")
|
||||
System.exit(-1)
|
||||
}
|
||||
|
||||
if (!Files.exists(outputPath) || !Files.isDirectory(outputPath) || !Files.isWritable(outputPath)) {
|
||||
LOG.error("Output path is invalid");
|
||||
System.exit(-1);
|
||||
LOG.error("Output path is invalid")
|
||||
System.exit(-1)
|
||||
}
|
||||
|
||||
try {
|
||||
final Project project = ProjectManager.getInstance().getDefaultProject();
|
||||
val project = ProjectManager.getInstance().defaultProject
|
||||
|
||||
LOG.info("Using project " + project.getName() + ", default: " + project.isDefault());
|
||||
final InspectionProjectProfileManager inspectionManager = InspectionProjectProfileManager.getInstance(project);
|
||||
final List<ScopeToolState> scopeToolStates = inspectionManager.getCurrentProfile().getAllTools();
|
||||
LOG.info("Using project " + project.name + ", default: " + project.isDefault)
|
||||
val inspectionManager = InspectionProjectProfileManager.getInstance(project)
|
||||
val scopeToolStates = inspectionManager.currentProfile.allTools
|
||||
|
||||
final Map<String, Plugin> availablePlugins = Arrays.stream(PluginManager.getPlugins()).map(
|
||||
pluginDescriptor -> new Plugin(pluginDescriptor.getPluginId().getIdString(), pluginDescriptor.getName(),
|
||||
pluginDescriptor.getVersion())).distinct()
|
||||
.collect(Collectors.toMap(Plugin::getId, plugin -> plugin));
|
||||
val availablePlugins = Arrays.stream(
|
||||
PluginManager.getPlugins()).map { pluginDescriptor: IdeaPluginDescriptor ->
|
||||
Plugin(pluginDescriptor.pluginId.idString, pluginDescriptor.name,
|
||||
pluginDescriptor.version)
|
||||
}.distinct()
|
||||
.collect(Collectors.toMap(
|
||||
Function { obj: Plugin -> obj.getId() }, Function { plugin: Plugin -> plugin }))
|
||||
|
||||
availablePlugins.put(IDE_NAME, new Plugin(IDE_NAME, IDE_NAME, IDE_VERSION));
|
||||
availablePlugins[IDE_NAME] = Plugin(IDE_NAME, IDE_NAME, IDE_VERSION)
|
||||
|
||||
final InspectionMetaInformationService
|
||||
service = ApplicationManager.getApplication().getService(InspectionMetaInformationService.class);
|
||||
val service = ApplicationManager.getApplication().getService(
|
||||
InspectionMetaInformationService::class.java)
|
||||
|
||||
final MetaInformationState inspectionsExtraState = service == null ? null : (MetaInformationState)service.getState(null);
|
||||
val inspectionsExtraState = if (service == null) null else service.getState(null)
|
||||
|
||||
for (final ScopeToolState scopeToolState : scopeToolStates) {
|
||||
for (scopeToolState in scopeToolStates) {
|
||||
val wrapper = scopeToolState.tool
|
||||
val extension = wrapper.extension
|
||||
val pluginId = extension?.pluginDescriptor?.pluginId?.idString ?: IDE_NAME
|
||||
val originalDescription = wrapper.loadDescription()
|
||||
val description = originalDescription?.split("<!-- tooltip end -->".toRegex())?.dropLastWhile { it.isEmpty() }?.toTypedArray()
|
||||
?: arrayOf("")
|
||||
|
||||
final InspectionToolWrapper<?, ?> wrapper = scopeToolState.getTool();
|
||||
final InspectionEP extension = wrapper.getExtension();
|
||||
final String pluginId = extension == null ? IDE_NAME : extension.getPluginDescriptor().getPluginId().getIdString();
|
||||
final String originalDescription = wrapper.loadDescription();
|
||||
final String[] description = originalDescription == null ? new String[]{""} : originalDescription.split("<!-- tooltip end -->");
|
||||
|
||||
List<OptionsPanelInfo> panelInfo = null;
|
||||
var panelInfo: List<OptionsPanelInfo?>? = null
|
||||
try {
|
||||
InspectionProfileEntry tool = wrapper.getTool();
|
||||
final OptPane panel = tool.getOptionsPane();
|
||||
val tool = wrapper.tool
|
||||
val panel = tool.optionsPane
|
||||
|
||||
if (!panel.equals(OptPane.EMPTY)) {
|
||||
LOG.info("Saving options panel for " + wrapper.getShortName());
|
||||
panelInfo = retrievePanelStructure(panel, tool.getOptionController());
|
||||
if (panel != OptPane.EMPTY) {
|
||||
LOG.info("Saving options panel for " + wrapper.shortName)
|
||||
panelInfo = retrievePanelStructure(panel, tool.optionController)
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
LOG.info("Cannot create options panel " + wrapper.getShortName(), t);
|
||||
catch (t: Throwable) {
|
||||
LOG.info("Cannot create options panel " + wrapper.shortName, t)
|
||||
}
|
||||
final MetaInformation metaInformation = inspectionsExtraState == null ? null : inspectionsExtraState.getInspections().get(wrapper.getID());
|
||||
final List<Integer> cweIds = metaInformation == null ? null : metaInformation.getCweIds();
|
||||
val metaInformation = inspectionsExtraState?.inspections?.get(wrapper.id)
|
||||
val cweIds = metaInformation?.cweIds
|
||||
|
||||
final String language = wrapper.getLanguage();
|
||||
final String briefDescription = HtmlUtils.cleanupHtml(description[0], language);
|
||||
final String extendedDescription = description.length > 1 ? HtmlUtils.cleanupHtml(description[1], language) : null;
|
||||
final Inspection inspection = new Inspection(wrapper.getShortName(), wrapper.getDisplayName(), wrapper.getDefaultLevel().getName(),
|
||||
language, briefDescription,
|
||||
extendedDescription, Arrays.asList(wrapper.getGroupPath()), wrapper.applyToDialects(),
|
||||
wrapper.isCleanupTool(), wrapper.isEnabledByDefault(), panelInfo, cweIds);
|
||||
val language = wrapper.language
|
||||
val briefDescription = HtmlUtils.cleanupHtml(description[0], language)
|
||||
val extendedDescription = if (description.size > 1) HtmlUtils.cleanupHtml(
|
||||
description[1], language)
|
||||
else null
|
||||
val inspection = Inspection(wrapper.shortName, wrapper.displayName, wrapper.defaultLevel.name,
|
||||
language, briefDescription,
|
||||
extendedDescription, Arrays.asList(*wrapper.groupPath), wrapper.applyToDialects(),
|
||||
wrapper.isCleanupTool, wrapper.isEnabledByDefault, panelInfo, cweIds)
|
||||
|
||||
availablePlugins.get(pluginId).addInspection(inspection);
|
||||
availablePlugins[pluginId]!!.addInspection(inspection)
|
||||
}
|
||||
|
||||
var sortedPlugins = availablePlugins.values().stream()
|
||||
.sorted(Comparator.comparing(Plugin::getId))
|
||||
.peek(plugin -> {
|
||||
plugin.inspections.sort(null);
|
||||
}).toList();
|
||||
final Plugins pluginsData = new Plugins(sortedPlugins, IDE_CODE, IDE_NAME, IDE_VERSION);
|
||||
val sortedPlugins = availablePlugins.values.stream()
|
||||
.sorted(Comparator.comparing { obj: Plugin -> obj.getId() })
|
||||
.peek { plugin: Plugin ->
|
||||
plugin.inspections.sort(null)
|
||||
}.toList()
|
||||
val pluginsData = Plugins(sortedPlugins, IDE_CODE, IDE_NAME, IDE_VERSION)
|
||||
|
||||
for (final String ext : ASSETS.keySet()) {
|
||||
String data = "";
|
||||
for (ext in assets.keys) {
|
||||
var data: String? = ""
|
||||
try {
|
||||
data = ASSETS.get(ext).writeValueAsString(pluginsData);
|
||||
data = assets[ext]!!.writeValueAsString(pluginsData)
|
||||
}
|
||||
catch (JsonProcessingException e) {
|
||||
LOG.error("Cannot serialize " + ext.toUpperCase(Locale.getDefault()), e);
|
||||
System.exit(-1);
|
||||
catch (e: JsonProcessingException) {
|
||||
LOG.error("Cannot serialize " + ext.uppercase(Locale.getDefault()), e)
|
||||
System.exit(-1)
|
||||
}
|
||||
|
||||
final Path outPath = outputPath.resolve(ASSET_FILENAME + ext);
|
||||
val outPath = outputPath.resolve(ASSET_FILENAME + ext)
|
||||
|
||||
try {
|
||||
Files.writeString(outPath, data);
|
||||
Files.writeString(outPath, data)
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error("Cannot write " + outPath, e);
|
||||
System.exit(-1);
|
||||
catch (e: IOException) {
|
||||
LOG.error("Cannot write $outPath", e)
|
||||
System.exit(-1)
|
||||
}
|
||||
LOG.info("Inspections info saved in " + outPath);
|
||||
LOG.info("Inspections info saved in $outPath")
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
System.exit(-1);
|
||||
catch (e: Exception) {
|
||||
LOG.error(e.message, e)
|
||||
System.exit(-1)
|
||||
}
|
||||
System.exit(0);
|
||||
System.exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
private static @Nullable LocMessage getMyText(final @NotNull OptComponent cmp) {
|
||||
if (cmp instanceof OptCheckbox checkbox) {
|
||||
return checkbox.label();
|
||||
}
|
||||
else if (cmp instanceof OptString string) {
|
||||
return string.splitLabel();
|
||||
}
|
||||
else if (cmp instanceof OptNumber number) {
|
||||
return number.splitLabel();
|
||||
}
|
||||
else if (cmp instanceof OptExpandableString expandableString) {
|
||||
return expandableString.label();
|
||||
}
|
||||
else if (cmp instanceof OptStringList list) {
|
||||
return list.label();
|
||||
}
|
||||
else if (cmp instanceof OptTable table) {
|
||||
return table.label();
|
||||
}
|
||||
else if (cmp instanceof OptTableColumn column) {
|
||||
return column.name();
|
||||
}
|
||||
else if (cmp instanceof OptTab tab) {
|
||||
return tab.label();
|
||||
}
|
||||
else if (cmp instanceof OptDropdown dropdown) {
|
||||
return dropdown.splitLabel();
|
||||
}
|
||||
else if (cmp instanceof OptGroup group) {
|
||||
return group.label();
|
||||
}
|
||||
else if (cmp instanceof OptSettingLink link) {
|
||||
return link.displayName();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private val LOG = logger<InspectopediaExtractor>()
|
||||
|
||||
private static @NotNull List<@NotNull OptionsPanelInfo> retrievePanelStructure(@NotNull OptPane pane,
|
||||
@NotNull OptionController controller) {
|
||||
List<OptionsPanelInfo> children = new ArrayList<>();
|
||||
for (OptRegularComponent component : pane.components()) {
|
||||
children.add(retrievePanelStructure(component, controller));
|
||||
}
|
||||
return children;
|
||||
private fun getMyText(cmp: OptComponent): LocMessage? {
|
||||
return if (cmp is OptCheckbox) {
|
||||
cmp.label
|
||||
}
|
||||
else if (cmp is OptString) {
|
||||
cmp.splitLabel
|
||||
}
|
||||
else if (cmp is OptNumber) {
|
||||
cmp.splitLabel
|
||||
}
|
||||
else if (cmp is OptExpandableString) {
|
||||
cmp.label
|
||||
}
|
||||
else if (cmp is OptStringList) {
|
||||
cmp.label
|
||||
}
|
||||
else if (cmp is OptTable) {
|
||||
cmp.label
|
||||
}
|
||||
else if (cmp is OptTableColumn) {
|
||||
cmp.name
|
||||
}
|
||||
else if (cmp is OptTab) {
|
||||
cmp.label
|
||||
}
|
||||
else if (cmp is OptDropdown) {
|
||||
cmp.splitLabel
|
||||
}
|
||||
else if (cmp is OptGroup) {
|
||||
cmp.label
|
||||
}
|
||||
else if (cmp is OptSettingLink) {
|
||||
cmp.displayName
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private static @NotNull OptionsPanelInfo retrievePanelStructure(@NotNull OptComponent component, @NotNull OptionController controller) {
|
||||
final OptionsPanelInfo result = new OptionsPanelInfo();
|
||||
result.type = component.getClass().getSimpleName();
|
||||
result.value = component instanceof OptControl control ? controller.getOption(control.bindId()) : null;
|
||||
if (component instanceof OptDropdown dropdown) {
|
||||
if (result.value != null) {
|
||||
OptDropdown.Option option = dropdown.findOption(result.value);
|
||||
result.value = option == null ? null : option.label().label();
|
||||
}
|
||||
result.content = ContainerUtil.map(dropdown.options(), opt -> opt.label().label());
|
||||
}
|
||||
LocMessage text = getMyText(component);
|
||||
result.text = text == null ? null : text.label();
|
||||
if (component instanceof OptDescribedComponent describedComponent) {
|
||||
HtmlChunk description = describedComponent.description();
|
||||
result.description = description == null ? null : description.toString();
|
||||
}
|
||||
List<OptionsPanelInfo> children = new ArrayList<>();
|
||||
for (OptComponent child : component.children()) {
|
||||
children.add(retrievePanelStructure(child, controller));
|
||||
}
|
||||
if (!children.isEmpty()) {
|
||||
result.children = children;
|
||||
}
|
||||
return result;
|
||||
private fun retrievePanelStructure(pane: OptPane,
|
||||
controller: OptionController): List<OptionsPanelInfo?> {
|
||||
val children: MutableList<OptionsPanelInfo?> = ArrayList()
|
||||
for (component in pane.components) {
|
||||
children.add(retrievePanelStructure(component, controller))
|
||||
}
|
||||
return children
|
||||
}
|
||||
|
||||
private fun retrievePanelStructure(component: OptComponent, controller: OptionController): OptionsPanelInfo {
|
||||
val result = OptionsPanelInfo()
|
||||
result.type = component.javaClass.simpleName
|
||||
result.value = if (component is OptControl) controller.getOption(component.bindId()) else null
|
||||
if (component is OptDropdown) {
|
||||
if (result.value != null) {
|
||||
val option = component.findOption(result.value)
|
||||
result.value = option?.label?.label()
|
||||
}
|
||||
result.content = ContainerUtil.map(component.options) { opt: OptDropdown.Option -> opt.label.label() }
|
||||
}
|
||||
val text = getMyText(component)
|
||||
result.text = text?.label()
|
||||
if (component is OptDescribedComponent) {
|
||||
val description = component.description()
|
||||
result.description = description?.toString()
|
||||
}
|
||||
val children: MutableList<OptionsPanelInfo> = ArrayList()
|
||||
for (child in component.children()) {
|
||||
children.add(retrievePanelStructure(child, controller))
|
||||
}
|
||||
if (!children.isEmpty()) {
|
||||
result.children = children
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user