私は、異なる XML ファイル間、および XML ソースと Java ソース間のナビゲーションを提供する IDEA プラグインに取り組んでいます。これは、Spring サポートに少し似ています。
サポートされる予定の XML タグには <name> 子があり (Spring の id 属性とは対照的に)、参照は spring と同じです: ref="..." Java ソースへのナビゲーションは後のステップになります。新しいプラグインをサポートする xml ファイルの命名規則もあります: *-definitions.xml
現時点では、最初のステップの 1 つである LineMarkerProvider と ReferenceContributor で行き詰まっています。
「カスタム言語サポート」の例を出発点として使用しました。しかし、私はカスタム言語を持っていませんが、代わりに xml 機能を拡張したいので、レクサー、パーサー、ファイル ファクトリなどを削除し、LineMarkerProvider と ReferenceContributor のみを含めました。
だから私が今まで持っているのは:
- クラス DefinitionsReference は PsiReferenceBase を拡張します
- クラス DefinitionsUtil (SimplePsiImplUtil に類似)
- クラス DefinitionsLineMarkerProvider は RelatedItemLineMarkerProvider を拡張します
- クラス DefinitionsReferenceContributor は PsiReferenceContributor を拡張します
LineMarkerProvider (language=XML) と ReferenceContributor を plugin.xml に登録し、ログ出力を追加して、それらが呼び出されたかどうか、および結果が空かどうかを確認しました。
ReferenceContributor.PsiReferenceProvider.getReferencesByElement() と DefinitionsReference.multiResolve() および reslove() は実際に空でない結果を返し、LineMarkerProvider.collectNavigationMarkers() はマークする場所をいくつか見つけますが、ナビゲーションガターアイコンを取得することもできませんref= から対応するタグに移動します。「行く宣言が見つかりません」と表示されます。
重要な詳細を見逃していたようです。
最初に何を探すべきですか?
それとも完全に間違ったアプローチですか?
編集:
これは、サポートされる XML ファイルの 1 つです。
<?xml version="1.0" ?>
<event-definitions>
<data-source-definition>
<name>event.eventDataSource</name>
<class>...</class>
</data-source-definition>
<plugin-definition>
<name>event.taskPlugin</name>
<class>...</class>
<title>...</title>
<data-source ref="event.eventDataSource">
<property>eventDataSource</property>
</data-source>
<data-source ref="personDataSource"/> <!-- defined in other XML file -->
... more data-sources ...
</plugin-definition>
<editor-definition>
<name>event.admin.Editor</name>
<editor>...</editor>
<title>...</title>
<editor-view>...</editor-view>
<data-source ref="event.eventDataSource"/>
<data-source ref="personDataSource"/> <!-- defined in other XML file -->
... more data-sources ...
<plugin ref="event.taskPlugin">
...
</plugin>
<plugin ref="assignment.ratingPlugin"> <!-- defined in other XML file -->
...
</plugin>
... more plugins ...
</editor-definition>
</event-definitions>
これは私の ReferenceContributor です:
public class DefinitionsReferenceContributor extends PsiReferenceContributor {
@Override
public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
registrar.registerReferenceProvider(PlatformPatterns.psiElement(XmlTag.class),
new PsiReferenceProvider() {
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
XmlTag tag = (XmlTag) element;
final String localName = tag.getLocalName();
if ("name".equals(localName)) {
final PsiReference[] psiReferences = DefinitionsUtil.matchTag((XmlTag) element);
return psiReferences;
} else {
return new PsiReference[0];
}
}
});
}
}
私の LineMarkerProvider:
public class DefinitionsLineMarkerProvider extends RelatedItemLineMarkerProvider {
@Override
protected void collectNavigationMarkers(@NotNull PsiElement element, Collection<? super RelatedItemLineMarkerInfo> result) {
if (element instanceof XmlTag) {
XmlTag tag = (XmlTag) element;
final String localName = tag.getLocalName();
if ("name".equals(localName)) {
final Project project = element.getProject();
final String tagName = DefinitionsUtil.getTagName(tag);
if (tagName != null) {
final List<XmlTag> matchingTags = DefinitionsUtil.findMatchingReferences(project, tagName);
if (matchingTags.size() > 0) {
NavigationGutterIconBuilder<PsiElement> builder =
NavigationGutterIconBuilder.create(SmotiveDefinitionsIcons.FILE).
setTargets(matchingTags).
setTooltipText("Navigate to a sMOTIVE Definition");
result.add(builder.createLineMarkerInfo(element));
}
}
} else {
final String ref = DefinitionsUtil.getRefValue(tag);
if (ref != null) {
final Project project = element.getProject();
final List<XmlTag> matchingTags = DefinitionsUtil.findMatchingTags(project, ref);
if (matchingTags.size() > 0) {
NavigationGutterIconBuilder<PsiElement> builder =
NavigationGutterIconBuilder.create(SmotiveDefinitionsIcons.FILE).
setTargets(matchingTags).
setTooltipText("Navigate to a sMOTIVE Definition");
result.add(builder.createLineMarkerInfo(element));
}
}
}
}
}
}
そして最後に、私の plugin.xml の拡張セクション:
<extensions defaultExtensionNs="com.intellij">
<codeInsight.lineMarkerProvider language="XML" implementationClass="de.smotive.tools.navigation.definitions.DefinitionsLineMarkerProvider"/>
<psi.referenceContributor implementation="de.smotive.tools.navigation.definitions.DefinitionsReferenceContributor"/>
</extensions>
サイズが大きいため、 DefinitionsUtil を省略しました。解決策を見つけるために必要であることが判明した場合は、後で追加します。