繁体   English   中英

如何为自定义Java标记添加Eclipse Quick Fix?

[英]How can I add an Eclipse Quick Fix for a custom Java marker?

我想将Eclipse文件的自定义问题报告给Eclipse的Problems View,并为它们提供快速修复。

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

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

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

尝试1:

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

<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")添加了上述标记的实例。

接下来,我定义了一个自定义Quick Fix处理器。

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

我的自定义标记出现在Eclipse的Problems View中,但是当我右键单击自定义问题时,Quick Fix菜单项被禁用。

尝试2:

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

尝试3:

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

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

因此,当我将鼠标悬停在编辑器中的自定义标记上或单击Java编辑器左边缘的灯光构建时,将调用CustomQuickFixProcessor.getCorrections 但是,当我在“问题视图”中选择标记时,右键单击标记,然后选择“快速修复”菜单项,不会调用CustomQuickFixProcessor.getCorrections并出现一个对话框,指出没有可用的快速修复。

我在调试模式下运行JDT以查看当我从Problems视图调用Quick Fix时它不调用CustomQuickFixProcessor.getCorrections原因。 事实证明, CorrectionMarkerResolutionGenerator.internalGetResolutions(IMarker)找不到任何分辨率,因为CorrectionMarkerResolutionGenerator.hasProblem (context.getASTRoot().getProblems(), location)在编译单元的AST中找不到自定义问题。 我不确定如何将自定义标记与编译单元的AST相关联。

在这篇文章和调试器的帮助下,我得到了这个工作。 这是你要做的:

创建标记

plugin.xml中

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

<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字段非常重要,我认为此处列出的所有其他字段也是如此。

// 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声明正确的id

<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的

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

如果您创建自己的标记类型(如上所述),我认为您可以硬编码hasCorrections以返回true。 但要保存并遵循约定检查它是否与您的jdt问题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。

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);
}

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

您的尝试1将无效,原因:

JDT UI定义了以下扩展。

   <extension
         point="org.eclipse.ui.ide.markerResolution">
      <markerResolutionGenerator
            markerType="org.eclipse.jdt.core.problem"
            class="org.eclipse.jdt.internal.ui.text.correction.CorrectionMarkerResolutionGenerator">
      </markerResolutionGenerator>

即来自JDT的快速修复仅适用于markerType =“org.eclipse.jdt.core.problem”。

尝试2 :即使在JDT UI实现中,也有一些情况,当QuickFixProcessor#hasCorrections(...)返回true但QuickFixProcessor#getCorrections(...)可能不会返回修复。 这是因为我们总是为特定标记返回true或false。 但是,特定标记的所有实例可能都不是“可修复的”。 也许你碰到类似的东西?

尝试3 :您在标记上设置的所有属性是什么? 由于CorrectionMarkerResolutionGenerator.hasProblem(...)检查它,您需要至少设置IMarker.CHAR_START属性。 看看org.eclipse.jdt.internal.core.eval.RequestorWrapper.acceptProblem(CategorizedProblem, char[], int) ,这是创建JDT Core中的标记的地方。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM