Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Quick Fix - Access Specific Token(How to reference specific elements in a Quick Fix. )
Quick Fix - Access Specific Token [message #696090] Wed, 13 July 2011 08:54 Go to next message
Daniel Missing name is currently offline Daniel Missing nameFriend
Messages: 101
Registered: July 2011
Senior Member
Hi everybody.

As always: A small szenario that I want to achieve.

I want to provide some Quick Fixes to fix some errors. As an example I want to prevent cycles within type hierarchies using this grammar:
// Eine Strukturdefinition
Type:
    'type' name = ID 
        ('extends' superType = [Type|QualifiedName])? '{'
    '}'
;


I have written a validator which detects cycles within types:
  public static final String  INHERITANCE_LOOP = "inheritance-loop";
  @Check
  public void checkTypeInheritance(Type type) {
    Type hierarchyLoopElement = getHierarchyLoop(type);
    if (hierarchyLoopElement != null) {
      error('Cycle detected ...',
            MyDslPackage.Literals.TYPE__SUPER_TYPE, INHERITANCE_LOOP, hierarchyLoopElement.getName());
    }
  }


The strange thing is: MyDslPackage.Literals.TYPE__SUPER_TYPE marks the full type definition as an error, not only the superType part. I want to provide a quick fix to remove the 'extends SuperType' part from the source code:
  @Fix(MyDslJavaValidator.INHERITANCE_LOOP)
  public void breakInheritenceLoop(...) {
    acceptor.accept(issue, 
        "..", "..", "..", 
        new IModification() {          
          @Override
          public void apply(IModificationContext context) throws Exception {
            IXtextDocument xtextDocument = context.getXtextDocument();
            xtextDocument.replace(issue.getOffset(), issue.getLength(), "");
          }
        });
  }


But this Quick Fix removes the complete type definition. How can I access the ranges of specific subtoken? Even if the TYPE__SUPER_TYPE reference would only mark the superType reference, how can I ensure the "extends" before the type reference will also get removed?

-Daniel
Re: Quick Fix - Access Specific Token [message #696142 is a reply to message #696090] Wed, 13 July 2011 11:02 Go to previous messageGo to next message
Alexander Nittka is currently offline Alexander NittkaFriend
Messages: 1193
Registered: July 2009
Senior Member
Hi,

try using an ISemanticModification instead of an IModification. In this case you should get the object with the error. Then you simply set the extend feature to null. If your serialiser and formatter is functioning properly, you are done. If this (semantic modification) does not work, you would still have to calculate the correct region for the replace. In short: apply an readOnlyUnitOfWork on the xtextDocument. You then use NodeModelUtil to get at the EObject at the offset, search the node model of your type for the beginning of the extends-keyword and the end of the superType-Feature and use these to calculate offset and length of the replace region.

Alex


Need training, onsite consulting or any other kind of help for Xtext?
Go visit http://xtext.itemis.com or send a mail to xtext@itemis.de
Re: Quick Fix - Access Specific Token [message #696208 is a reply to message #696142] Wed, 13 July 2011 13:59 Go to previous messageGo to next message
Daniel Missing name is currently offline Daniel Missing nameFriend
Messages: 101
Registered: July 2011
Senior Member
Hi.

I just started developing with Xtext and my knowledge about the architecture is quite limited yet. I don't have written any serializer and formatter yet because I am currently focusing on the basic language rules and Quick Fixes to auto-correct them.

Using the second approach I got a working code. But this piece is very complex. Can this code be written easier?
final IXtextDocument xtextDocument = context.getXtextDocument();
xtextDocument.readOnly(new IUnitOfWork.Void<XtextResource>() {
  public void process(XtextResource state) throws Exception {

    logger.debug("Trying to remove inheritance");
    
    EObject affectedObject = state.getEObject(issue
        .getUriToProblem().fragment());
    
    if (affectedObject != null) {
      
      int extendsStart = -1;
      int extendsEnd = -1;
      
      logger.debug("Searching for range to be removed");
      
      Iterable<INode> children = NodeModelUtils.getNode(
          affectedObject).getAsTreeIterable();
      
      for (INode child : children) {
        
        if (child instanceof AbstractNode) {
          AbstractNode node = (AbstractNode) child;
          boolean isKeyword = (node.getGrammarElement() instanceof Keyword);
          boolean isCrossReference = (node.getGrammarElement() instanceof CrossReference);

          // first try to find the extends keyword, then the following crossreference
          if (isKeyword
              && "extends".equals( ((Keyword)node.getGrammarElement()).getValue())) {
            extendsStart = node.getTotalOffset();
            logger.debug("Found 'extends' at position: " + extendsStart + ", now searching for crossreference");
          }
          else if (extendsStart > 0 && isCrossReference) {
            extendsEnd = node.getTotalEndOffset();
            logger.debug("Found CrossReference at position: " + node.getTotalOffset());
          }

          // as we have found them we can replace the code and finish
          if (extendsStart > 0 && extendsEnd > 0) {
            logger.debug("extends and crossreference found, remove from " + extendsStart + " to " + extendsEnd);
            xtextDocument.replace(extendsStart, extendsEnd - extendsStart, "");
            return;
          }
        }
      }
    }
    else
    {
      logger.debug("No object found to remove inheritance");
    }
  };
});

Re: Quick Fix - Access Specific Token [message #696223 is a reply to message #696208] Wed, 13 July 2011 14:24 Go to previous messageGo to next message
Alexander Nittka is currently offline Alexander NittkaFriend
Messages: 1193
Registered: July 2009
Senior Member
Hi,

a) have you tried the first approach without modifying the serialiser/formatter. If you do no complicated stuff in your grammar, you should not have to do anything but implementing the ISemanticModification ( something like object.setSupertype(null)).
b) the idea of the code is about right. You may get some "simplifications" and more robust code if you use the grammar access of your language and existing helper methods in NodeModelUtil. E.g. obtaining the node for the super type feature directly. As a side node: a read-Only-Unit of work should only be used to obtain information (i.e. calculate offset and length). No modification must be done within it. In your case this may not be so problematic as the IModification already allows for a modification to be done.

Alex

Alex


Need training, onsite consulting or any other kind of help for Xtext?
Go visit http://xtext.itemis.com or send a mail to xtext@itemis.de
Re: Quick Fix - Access Specific Token [message #696233 is a reply to message #696223] Wed, 13 July 2011 14:40 Go to previous messageGo to next message
Daniel Missing name is currently offline Daniel Missing nameFriend
Messages: 101
Registered: July 2011
Senior Member
Okay, I will implement the serializer and formatter as next. I will write some feedback here afterwards.
Re: Quick Fix - Access Specific Token [message #696267 is a reply to message #696233] Wed, 13 July 2011 15:35 Go to previous messageGo to next message
Alexander Nittka is currently offline Alexander NittkaFriend
Messages: 1193
Registered: July 2009
Senior Member
Hi,

maybe I was not clear. Do not work on the serialiser or formatter before you have tried to use the ISemanticModification-version for the quickfix. It may well be that it works out of the box.

Alex
Re: Quick Fix - Access Specific Token [message #696520 is a reply to message #696267] Thu, 14 July 2011 07:47 Go to previous messageGo to next message
Daniel Missing name is currently offline Daniel Missing nameFriend
Messages: 101
Registered: July 2011
Senior Member
I already tried the semantic modification but it only throws an exception as I set the superType to null. It seems the generated serializer cannot take care of this modification. I also tried to add a new sub-rule for the complete inheritance block and set this new feature to null afterwards, no success.

Therefore I thought I need to modify the Serializer for writing correct code after modifications. (Like removing the extends keyword too if the subtype is null).

org.eclipse.emf.common.util.WrappedException: java.lang.RuntimeException: The context 'Model' is not valid for type 'Struct'
Recommended contexts for type 'Struct': Declaration, TypeDeclaration, Struct, StructElement, UnionElement
The context 'Model' is valid for types: ModelDeclaration

Semantic Object: ModelDeclaration'INHERITANCE'.declarations[4]->Struct'ERR1_A'
	at org.eclipse.xtext.ui.editor.quickfix.IssueResolution.apply(IssueResolution.java:50)
	at org.eclipse.xtext.ui.editor.quickfix.QuickAssistCompletionProposal.apply(QuickAssistCompletionProposal.java:32)
	at org.eclipse.jface.text.contentassist.CompletionProposalPopup.insertProposal(CompletionProposalPopup.java:935)
...
Caused by: java.lang.RuntimeException: The context 'Model' is not valid for type 'Struct'
Recommended contexts for type 'Struct': Declaration, TypeDeclaration, Struct, StructElement, UnionElement
The context 'Model' is valid for types: ModelDeclaration

Semantic Object: ModelDeclaration'INHERITANCE'.declarations[4]->Struct'ERR1_A'
	at org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic$ExceptionThrowingAcceptor.accept(ISerializationDiagnostic.java:66)
	at at.mydsl.serializer.AbstractMyDslSemanticSequencer.createSequence(AbstractMyDslSemanticSequencer.java:623)
	at org.eclipse.xtext.serializer.impl.Serializer.serialize(Serializer.java:68)
Re: Quick Fix - Access Specific Token [message #696530 is a reply to message #696520] Thu, 14 July 2011 08:21 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian ZarnekowFriend
Messages: 3118
Registered: July 2009
Senior Member
Hi Daniel,

I take you created a new project with Xtext 2.0 with the "Experimental
features" configuration. The new serializer as of June 23rd could not
handle partial serialization. I'd recommend to enable the
ParseTreeConstructorFragment instead of the SerializerFragment in your
workflow.

Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com

On 14.07.11 09:47, Daniel wrote:
> I already tried the semantic modification but it only throws an
> exception as I set the superType to null. It seems the generated
> serializer cannot take care of this modification. I also tried to add a
> new sub-rule for the complete inheritance block and set this new feature
> to null afterwards, no success.
> Therefore I thought I need to modify the Serializer for writing correct
> code after modifications. (Like removing the extends keyword too if the
> subtype is null).
>
> org.eclipse.emf.common.util.WrappedException:
> java.lang.RuntimeException: The context 'Model' is not valid for type
> 'Struct'
> Recommended contexts for type 'Struct': Declaration, TypeDeclaration,
> Struct, StructElement, UnionElement
> The context 'Model' is valid for types: ModelDeclaration
>
> Semantic Object:
> ModelDeclaration'INHERITANCE'.declarations[4]->Struct'ERR1_A'
> at
> org.eclipse.xtext.ui.editor.quickfix.IssueResolution.apply(IssueResolution.java:50)
>
> at
> org.eclipse.xtext.ui.editor.quickfix.QuickAssistCompletionProposal.apply(QuickAssistCompletionProposal.java:32)
>
> at
> org.eclipse.jface.text.contentassist.CompletionProposalPopup.insertProposal(CompletionProposalPopup.java:935)
>
> ..
> Caused by: java.lang.RuntimeException: The context 'Model' is not valid
> for type 'Struct'
> Recommended contexts for type 'Struct': Declaration, TypeDeclaration,
> Struct, StructElement, UnionElement
> The context 'Model' is valid for types: ModelDeclaration
>
> Semantic Object:
> ModelDeclaration'INHERITANCE'.declarations[4]->Struct'ERR1_A'
> at
> org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic$ExceptionThrowingAcceptor.accept(ISerializationDiagnostic.java:66)
>
> at
> at.mydsl.serializer.AbstractMyDslSemanticSequencer.createSequence(AbstractMyDslSemanticSequencer.java:623)
>
> at
> org.eclipse.xtext.serializer.impl.Serializer.serialize(Serializer.java:68)
>
Re: Quick Fix - Access Specific Token [message #696562 is a reply to message #696530] Thu, 14 July 2011 09:58 Go to previous messageGo to next message
Daniel Missing name is currently offline Daniel Missing nameFriend
Messages: 101
Registered: July 2011
Senior Member
Awesome, it worked! Will the new serializer support this "partial serialization" in the future too?
Re: Quick Fix - Access Specific Token [message #696661 is a reply to message #696562] Thu, 14 July 2011 14:03 Go to previous message
Sebastian Zarnekow is currently offline Sebastian ZarnekowFriend
Messages: 3118
Registered: July 2009
Senior Member
Yes, it will for sure!

Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com

On 14.07.11 11:58, Daniel wrote:
> Awesome, it worked! Will the new serializer support this "partial
> serialization" in the future too?
Previous Topic:Webinar on Xtext 2.0
Next Topic:[Xtend2] Code Reference
Goto Forum:
  


Current Time: Wed Apr 24 21:10:40 GMT 2024

Powered by FUDForum. Page generated in 0.04031 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top