2

私は、異なる 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 を省略しました。解決策を見つけるために必要であることが判明した場合は、後で追加します。

4

0 に答える 0