Я пишу плагин для IntelliJ IDE, который работает с деревом файлов; В частности, разваливающиеся и гнездящиеся узлы. Пока он отлично работает, но иногда, если я внесу изменения в файлы во время его работы, я получу эту странную ошибку в выводе отладчика, к которой я не могу найти источник.
2019-06-13 22:47:39,914 [ 257001] WARN - com.intellij.util.xmlb.Binding - no accessors for class org.jetbrains.kotlin.idea.highlighter.KotlinDefaultHighlightingSettingsProvider
2019-06-13 22:47:51,772 [ 268859] WARN - ntellij.ui.tree.AsyncTreeModel - ignore duplicated child at 1: module
2019-06-13 22:47:52,195 [ 269282] WARN - ntellij.ui.tree.AsyncTreeModel - ignore duplicated child at 1: module
2019-06-13 22:48:37,693 [ 314780] WARN - ntellij.ui.tree.AsyncTreeModel - ignore duplicated child at 1: module
2019-06-13 22:48:37,908 [ 314995] WARN - ntellij.ui.tree.AsyncTreeModel - ignore duplicated child at 1: module
2019-06-13 22:48:38,183 [ 315270] WARN - ntellij.ui.tree.AsyncTreeModel - ignore duplicated child at 1: module
2019-06-13 22:49:48,007 [ 385094] WARN - ntellij.ui.tree.AsyncTreeModel - ignore duplicated child at 1: module
2019-06-13 22:49:48,214 [ 385301] WARN - ntellij.ui.tree.AsyncTreeModel - ignore duplicated child at 1: module
2019-06-13 22:49:49,111 [ 386198] WARN - ntellij.ui.tree.AsyncTreeModel - ignore duplicated child at 1: module
2019-06-13 22:49:49,348 [ 386435] WARN - ntellij.ui.tree.AsyncTreeModel - ignore duplicated child at 1: module
Как говорится в сообщении об ошибке, похоже, что происходит сбой, когда он встречает два файла с одинаковыми именами на каком-то этапе процесса рендеринга или сортировки. Кажется, я не могу найти подходящее место, чтобы на самом деле поймать и решить эту проблему.
Я пишу плагин в Kotlin
. Это первый раз, когда я использовал Kotlin, так что я немного новичок в этом - и я плохо разбираюсь в Java, так что это мало поможет.
В моем файле plugin.xml
я настраиваю treeStructureProvider
следующим образом;
<extensions defaultExtensionNs="com.intellij">
<treeStructureProvider implementation="FoldingTreeStructureProvider" />
</extensions>
Я разместил класс FoldingTreeStructureProvider
ниже, но держу его в нижней части вопроса для удобства чтения.
Ошибка обычно возникает, когда я переименовываю уже вложенный файл, поэтому я предполагаю, что запущен другой тип провайдера дерева, и он сталкивается с проблемой там. Я просто не уверен, где именно обращаться с этой логикой или что именно искать.
Это базовый FoldingTreeStructureProvider
класс.
class FoldingTreeStructureProvider :
com.intellij.ide.projectView.TreeStructureProvider {
private lateinit var PATTERN_PREFIX: Pattern
private lateinit var PATTERN_EXTENSION: Pattern
/**
* enable or disable grouping completely.
*/
private val MatchPrefix: Boolean
get() = PropertiesComponent.getInstance().getBoolean(
FoldingConfiguration.ENABLE_PREFIX_MATCHING, true
)
/**
* Mask the matched prefix when drawing nodes.
*/
private val MaskPrefix: Boolean
get() = PropertiesComponent.getInstance().getBoolean(
FoldingConfiguration.MASK_PREFIX, true
)
private val MatchExtensions: Boolean
get() = PropertiesComponent.getInstance().getBoolean(
FoldingConfiguration.ENABLE_EXTENSIONS_MATCHING, true
)
override fun modify(
parent: AbstractTreeNode<*>,
children: Collection<AbstractTreeNode<*>>,
viewSettings: ViewSettings
): Collection<AbstractTreeNode<*>> {
/*
by default, the files inside of a directory are the
children for any node.
*/
if (parent !is PsiDirectoryNode || !MatchPrefix)
return children
val project = parent.project
val groups = HashMap<String, FoldableFileNodes>()
val nodes = ArrayList<AbstractTreeNode<*>>()
if (project == null)
return emptyList()
PATTERN_PREFIX = Pattern.compile(
PropertiesComponent.getInstance().getValue(
FoldingConfiguration.PATTERN_PREFIX,
FoldingConfiguration.DEFAULT_PREFIX_PATTERN
),
Pattern.CASE_INSENSITIVE
)
PATTERN_EXTENSION = Pattern.compile(
PropertiesComponent.getInstance().getValue(
FoldingConfiguration.PATTERN_EXTENSIONS,
FoldingConfiguration.DEFAULT_EXTENSIONS_PATTERN
),
Pattern.CASE_INSENSITIVE
)
/**
* iterate each file and see if it is even a file
*/
for (child in children) {
if (child.value !is PsiFile) {
nodes.add(child)
continue
}
// get the filename
// get the filename of the given node
val filename = nameFromNode(child)
val extensionMatcher = PATTERN_EXTENSION.matcher(filename)
/**
* if we have selected to limit matching only to certain extensions,
* then we will check for that here.
*/
if (!extensionMatcher.find() && MatchExtensions) {
nodes.add(child)
continue
}
// parse the filename with the regex PATTERN_PREFIX
val groupMatcher = PATTERN_PREFIX.matcher(filename)
// if no match was found, then we just add this
// file to the tree as normal; Since we're going on
// and building the rest of the tree uninterrupted.
if (!groupMatcher.find()) {
nodes.add(child)
continue
}
// if there were matches found, we can proceed to
// try and determine what group - if any, the file
// should belong to.
val prefix = groupMatcher.group(1)
val type = groupMatcher.group(2)
val extension = groupMatcher.group(3)
// obtain the group key for this node
val groupKey = String.format("%s", prefix)
/**
* obtain the group of nodes related to this collection
*/
var group = groups[groupKey]
/**
* if a group is not found, then it needs to be created
*/
if (group == null) {
/**
* construct a new folding node section
*/
group = FoldableFileNodes(
project,
viewSettings,
prefix,
if (type.isNotBlank()) type else ""
)
/**
* ensure that the new group is assigned to the
* appropriate key for the next iteration
*/
groups[groupKey] = group
nodes.add(group)
}
group.add(
project,
child,
MaskPrefix,
type,
extension,
prefix
)
}
// undo grouping that only has children and no parent
// elements.
var i = 0
while (i < nodes.size) {
val added = nodes[i]
if (added is FoldableFileNodes) {
if (added.children.size <= 1) {
nodes[i] = added.root!!
}
}
i++
}
return nodes
}
/**
* retrieve the filename of any given node.
*/
private fun nameFromNode(node: AbstractTreeNode<*>): String? {
return (node.value as? PsiFile)?.name
}
}