I am using Xtend to write custom QuickFixes for the Eclipse UI plugin of my Xtext language. The idea is to extend org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider
and use call the accept
method of an org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor
.
accept
has several overloaded signatures, including:
void accept(Issue issue, String label, String description, String image, IModification modification)
void accept(Issue issue, String label, String description, String image, ISemanticModification semanticModification)
Using the first of those signatures is easy using Xtend's lambda expression syntax:
@Fix(MyDSLValidator::INVALID_TYPE_NAME)
def removeInitialUnderscore(Issue issue, IssueResolutionAcceptor acceptor) {
acceptor.accept(issue,
"Remove initial underscore",
"Remove initial underscore",
'upcase.png')
[
context |
context.xtextDocument.replace(issue.offset, 1, "")
]
}
The Xtend compiler produces the following Java code:
public void removeInitialUnderscore(final Issue issue, final IssueResolutionAcceptor acceptor) {
final IModification _function = new IModification() {
public void apply(final IModificationContext context) throws Exception {
IXtextDocument _xtextDocument = context.getXtextDocument();
Integer _offset = issue.getOffset();
_xtextDocument.replace((_offset).intValue(), 1, "");
}
};
acceptor.accept(issue,
"Remove initial underscore",
"Remove initial underscore",
"upcase.png", _function);
}
Now I want to write a second QuickFix that uses ISemanticModification
instead of IModification
so that I can get access to the underlying EMF model, not just the strings. However, I'm struggling to tell the Xtend compiler which overloading of the method I'd like to use:
@Fix(MyDSLValidator::MISSING_USAGE)
def addMissingUseStatement(Issue issue, IssueResolutionAcceptor acceptor) {
acceptor.accept(issue,
"Add missing use statement",
"Add missing use statement",
"upcase.png",
[
EObject element |
(element.eContainer as MyContainer).usages.add(
(element as MyElement).myattr.eContainer as MyOtherContainer
)
])
}
Xtend always thinks I want to pass an IModification
instead of an ISemanticModification
and produces an error in the compiled java code because the two apply
methods have different signatures, IModification
takes an IModificationContext
while ISemanticModification
takes an EObject
.
@Fix(MyDSLValidator.MISSING_USAGE)
public void addMissingUseStatement(final Issue issue, final IssueResolutionAcceptor acceptor) {
final IModification _function = new IModification() {
public void apply(final IModificationContext element) throws Exception {
EObject _eContainer = element.eContainer(); // COMPILE ERROR
EList<Circuit> _usages = ((MyContainer) _eContainer).getUsages();
MyAttr _myattr = ((MyAttr ) element).getMyattr();
EObject _eContainer_1 = _myattr.eContainer();
_usages.add(
((MyOtherContainer) _eContainer_1));
}
};
acceptor.accept(issue,
"Add missing use statement",
"Add missing use statement",
"upcase.png", _function);
}
How do I tell Xtend which overloading to use? As far as I know, it's not possible to create an anonymous object in Xtend, so there needs to be another way to call IssueResolutionAcceptor.accept
passing an ISemanticModification
.