如何为自定义Java标记添加Eclipse快速修复? [英] How can I add an Eclipse Quick Fix for a custom Java marker?

查看:127
本文介绍了如何为自定义Java标记添加Eclipse快速修复?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想向Eclipse的问题视图报告Java文件的自定义问题,并为它们提供快速修复。

I'd like to report custom problems for Java files to the Problems View of Eclipse and provide Quick Fixes for them.

标准方法是使用扩展点 org.eclipse.core.resources.markers 声明自定义标记并通过调用 org.eclipse.core.resources.IResource添加标记.createMarker(String)。然后,可以使用扩展点 org.eclipse.ui.ide.markerResolution 为自定义标记提供快速修复。

The standard way to do is to use the extension point org.eclipse.core.resources.markers to declare a custom marker and add markers by calling org.eclipse.core.resources.IResource.createMarker(String). Then, one can use the extension point org.eclipse.ui.ide.markerResolution to provide a Quick Fix for the custom markers.

以上方法是创建和解析资源标记的独立于语言的方法。缺点是我必须编写一些样板代码来解决自定义Java问题。相反,我想重用 IQuickFixProcessor 。也就是说,我想使用扩展点 org.eclipse.jdt.ui.quickFixProcessors 来解析自定义Java标记。使用此扩展点,我不再需要解析在其中找到标记的Java文件,也不必构建绑定并找到覆盖标记的AST节点。如果我不重复使用 org.eclipse.jdt.internal.ui.text.correction.CorrectionMarkerResolutionGenerator 及其依赖项,我将最终复制大部分内容。

The above approach is a language-independent method of creating and resolving resource markers. The downside is that I have to write some boilerplate code to resolve my custom Java problems. Instead, I'd like to be reuse IQuickFixProcessor. That is, I'd like to resolve my custom Java markers using the extension point org.eclipse.jdt.ui.quickFixProcessors. Using this extension point, I no longer have to parse the Java file in which the marker is found, I don't have to build the bindings and find the AST node covering the marker. If I don't reuse org.eclipse.jdt.internal.ui.text.correction.CorrectionMarkerResolutionGenerator and its dependencies, I'll end up duplicating most of it.

如何使用JDT基础结构为自定义Java标记提供快速修复?

How can I provide Quick Fixes for my custom Java markers using the JDT infrastructure?

尝试1:

我将自定义标记定义如下:

I defined my custom marker as follows:

<extension
  id="custom.marker"
  name="Custom Java Problem"
  point="org.eclipse.core.resources.markers">
    <super type="org.eclipse.jdt.core.problem"/>
    <super type="org.eclipse.core.resources.problemmarker"/>
    <super type="org.eclipse.core.resources.textmarker"/>
    <persistent value="true"/>
</extension>

然后,我通过调用方法 IResource.createMarker添加了上述标记的实例( custom.marker)

Then, I added instances of the above marker by invoking method IResource.createMarker("custom.marker").

接下来,我定义了一个自定义快速修复处理器。

Next, I defined a custom Quick Fix processor.

<extension
  point="org.eclipse.jdt.ui.quickFixProcessors">
  <quickFixProcessor
    class="quickfixes.CustomQuickFixProcessor"
    id="quickfixes.quickFixProcessor">
  </quickFixProcessor>
</extension>

我的自定义标记显示在Eclipse的问题视图中,但是当我右键单击自定义标记时问题,快速修复菜单项被禁用。

My custom markers show up in the Problems View of Eclipse, but when I right-click on a custom problem, the Quick Fix menu item is disabled.

尝试2:

我用 IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);代替了 IMarker marker = resource.createMarker( custom.marker); 。更改的结果是,当我在问题视图中右键单击自定义问题时,快速修复菜单项变为可用,但是当我选择它时,会弹出一个对话框,指出没有针对所选问题的修复程序问题。但是,我验证了 CustomQuickFixProcessor.hasCorrections(ICompilationUnit,int)被调用并返回了 true ,但是, CustomQuickFixProcessor.getCorrections(IInvocationContext,IProblemLocation [])不会被调用。

I repalced IMarker marker = resource.createMarker("custom.marker"); by IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);. As a result of this change, when I right-click on a custom problem in the Problems View, the Quick Fix menu item becomes available, but, when I select it, a dialog pops up that says there is no fix available for the selected problem. However, I verified that CustomQuickFixProcessor.hasCorrections(ICompilationUnit, int) gets called and returns true, but, CustomQuickFixProcessor.getCorrections(IInvocationContext, IProblemLocation[]) doesn't get invoked.

尝试3:

尝试3是尝试2的延续。我按如下所示设置自定义标记的 IJavaModelMarker.ID

Attempt 3 is a continuation of Attempt 2. I set the IJavaModelMarker.ID of the custom marker as follows:

marker.setAttribute(IJavaModelMarker.ID, IProblem.ExternalProblemFixable);

因此, CustomQuickFixProcessor.getCorrections 在以下情况下被调用我将鼠标悬停在编辑器中的自定义标记上,或单击Java编辑器左边缘的light-build。但是,当我在问题视图中选择标记时,右键单击标记,然后选择快速修复菜单项, CustomQuickFixProcessor.getCorrections 不会被调用,并且

Consequently, CustomQuickFixProcessor.getCorrections gets called when I hover over my custom marker in the editor or click on the light-build on the left margin of the Java editor. However, when I select the marker in the Problems View, right-click on the marker, and select the Quick Fix menu item, CustomQuickFixProcessor.getCorrections doesn't get called and a dialog appears saying that no Quick Fixes are available.

我在调试模式下运行JDT以查看为什么不调用 CustomQuickFixProcessor.getCorrections 当我从问题视图调用快速修复时。原来 CorrectionMarkerResolutionGenerator.internalGetResolutions(IMarker)没有找到解决方法,因为 CorrectionMarkerResolutionGenerator.hasProblem(context.getASTRoot()。getProblems(),位置)在编译单元的AST中找不到自定义问题。我不确定如何将自定义标记与编译单元的AST相关联。

I ran JDT in debug mode to see why it doesn't call CustomQuickFixProcessor.getCorrections when I invoke the Quick Fix from the Problems View. It turned out CorrectionMarkerResolutionGenerator.internalGetResolutions(IMarker) finds no resolutions because CorrectionMarkerResolutionGenerator.hasProblem (context.getASTRoot().getProblems(), location) doesn't find the custom problem in the AST of the compilation unit. I'm not sure how to associate my custom markers with the AST of the compilation unit.

推荐答案

这篇文章和调试器提供了很大的帮助。这是您要做的事情:

I got this working, with great help from this post and the debugger. Here is what you have to do:

plugin.xml >

声明标记,以便扩展这三个现有标记(我认为这都是必要的)

Declare the marker so it extends these three existing markers (I think all are necessary)

<extension
       id="mymarker"
       name="My Problem"
       point="org.eclipse.core.resources.markers">
    <super
          type="org.eclipse.jdt.core.problem">
    </super>
    <super
          type="org.eclipse.core.resources.problemmarker">
    </super>
    <super
          type="org.eclipse.core.resources.textmarker">
    </super>
    <persistent
          value="true">
    </persistent>
 </extension>

Java

创建标记时,重要的是设置 IJavaModelMarker.ID 字段,我想这里也列出了所有其他字段。

When you create the marker it is important that you set the IJavaModelMarker.ID field, and I think all the other fields listed here as well.

// Must match the "id" attribute from plugin.xml
String MY_MARKER_ID = "com.example.my.plugin.mymarker"
// Must not be -1 or any of the values in org.eclipse.jdt.core.compiler.IProblem
int MY_JDT_PROBLEM_ID = 1234

// ....
IMarker marker = resource.createMarker(MY_MARKER_ID);
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING);
marker.setAttribute(IMarker.MESSAGE, msg);
marker.setAttribute(IMarker.CHAR_START, start);
marker.setAttribute(IMarker.CHAR_END, end);
marker.setAttribute(IJavaModelMarker.ID, MY_JDT_PROBLEM_ID);



创建QuickFixProcessor



plugin.xml

首先在 plugin.xml 中声明它。确保在 handledMarkerTypes

First declare it in plugin.xml. Be sure your declare the right id in handledMarkerTypes

<extension
      point="org.eclipse.jdt.ui.quickFixProcessors">
   <quickFixProcessor
         class="com.example.my.plugin.ui.MyQuickFixProcessor"
         id="org.eclipse.jdt.ui.text.correction.QuickFixProcessor"
         name="My Quick Fix Processor">
      <handledMarkerTypes>
         <markerType
               id="com.example.my.plugin.mymarker">
         </markerType>
      </handledMarkerTypes>
   </quickFixProcessor>
</extension>

Java

这是快速修复处理器的基本框架。请注意,重要的是要检查位置实际是否包含内容。

Here is the basic skeleton for the quick fix processor. Note that it is important to check that locations actually has contents.

如果您创建自己的标记类型(如如上所述),我认为,您只需对 hasCorrections 进行硬编码即可返回true。但是要保存并遵循约定,请检查它是否与您的jdt问题ID匹配。

If you make your own marker type (as described above) I think you can just hard-code hasCorrections to return true. But to be save and to follow the convention check that it matches your jdt problem id.

public class MyQuickFixProcessor implements IQuickFixProcessor {

  @Override
  public IJavaCompletionProposal[] getCorrections(IInvocationContext context, IProblemLocation[] locations) throws CoreException {
    if (locations == null || locations.length == 0) {
      // https://bugs.eclipse.org/444120 Eclipse can call this method without
      // any locations, if a quick fix is requested without any problems.
      return null;
    }

    IJavaCompletionProposal[] proposals = ...
    //...
    return proposals;
  }

  @Override
  public boolean hasCorrections(ICompilationUnit unit, int problemId) {
    return problemId == MY_JDT_PROBLEM_ID;
  }
}



找到一个好的JDT ID



您需要一个唯一的 MY_JDT_PROBLEM_ID !运行以下代码,以打印 IProblem 中定义的所有当前ID。在这些数字中选择一个相当大的范围,然后选择该范围内的ID。

Finding a good JDT ID

You need a MY_JDT_PROBLEM_ID that is unique! Run the code below, to print all the current ID's defined in IProblem. Pick a sizeable range in these numbers, and select you ID in that range.

Field[] fields = org.eclipse.jdt.core.compiler.IProblem.class.getFields();
List<Integer> ints = new ArrayList<>();
for (Field field : fields) {
  ints.add(field.getInt(null));
}
sort(ints);
for (Integer integer : ints) {
  System.out.printf("%16d %16o %16x%n", integer, integer, integer);
}






我希望我记得一切。祝你好运。


I hope I have remembered everything. Good Luck.

这篇关于如何为自定义Java标记添加Eclipse快速修复?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆