如何为自定义Java标记添加Eclipse快速修复? [英] How can I add an Eclipse Quick Fix for a custom Java marker?
问题描述
我想向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屋!