Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Content Assist problem
Content Assist problem [message #1778788] Thu, 21 December 2017 13:05 Go to next message
Romain Bernard is currently offline Romain BernardFriend
Messages: 18
Registered: July 2009
Junior Member
Hi Xtext team,

I have a strange content assist problem for a language that extends xbase. In some very specific and strange circumstances (see tests below), the content assist does not work anymore, and seems to depend on other elements defined before the place where the problem occurs.
As far as I understand, the computation of followElements by the parser does not produce the right elements in the test with errors...

I also attach a complete example...

In advance, thank you for your help !
Kind regards,
Romain

grammar :
grammar org.xtext.example.buggy.MyDsl with org.eclipse.xtext.xbase.annotations.XbaseWithAnnotations

generate myDsl "http://www.xtext.org/example/buggy/MyDsl"
import 'http://www.eclipse.org/xtext/xbase/Xbase' as xbase

Model:
	package=PackageDeclaration;

PackageDeclaration:
	'package' name=QualifiedName ';'?
	importSection=XImportSection?
	rootElement=RootElement;
	
RootElement:
	'class' name=ID body=XBlockExpression;
	
AbstractElement returns xbase::XExpression:
	InstructionA | InstructionB
;

InstructionA returns xbase::XExpression:
	{InstructionA} 'A' "intProperty:" intProperty=XExpression body=XBlockExpression
;

InstructionB returns xbase::XExpression:
	{InstructionB}
	'B' "enumProperty:" enumProperty=EnumType body=XBlockExpression;

enum EnumType:
	literal1 = "literal1" | literal2 = "literal2"
;

@ Override XExpression returns xbase::XExpression:
	XAssignment | AbstractElement;


JvmModelInferrer:
package org.xtext.example.buggy.jvmmodel

import com.google.inject.Inject
import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
import org.xtext.example.buggy.myDsl.Model

class MyDslJvmModelInferrer extends AbstractModelInferrer {

	@Inject extension JvmTypesBuilder

	def dispatch void infer(Model element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
		val pkg = element.package
		val rootElement = pkg?.rootElement

 		acceptor.accept(element.toClass(pkg.name + "." + rootElement.name)) [
			
 			members += element.toMethod("main", typeRef("void")) [
 				body = rootElement.body
 			]

		]
	}
}


Compiler:
package org.xtext.example.buggy.jvmmodel

import org.eclipse.xtext.xbase.XExpression
import org.eclipse.xtext.xbase.compiler.XbaseCompiler
import org.eclipse.xtext.xbase.compiler.output.ITreeAppendable
import org.xtext.example.buggy.myDsl.InstructionA
import org.xtext.example.buggy.myDsl.InstructionB

class MyDslCompiler extends XbaseCompiler {

	override protected doInternalToJavaStatement(XExpression expr, ITreeAppendable it, boolean isReferenced) {
		switch expr {
			InstructionA: {
				newLine
				append('''// code comes here for InstructionA''')
				expr.body.internalToJavaStatement(it, false)
			}
			InstructionB: {
				newLine
				append('''// code comes here for InstructionA''')
				expr.body.internalToJavaStatement(it, false)
			}
			default: {
				super.doInternalToJavaStatement(expr, it, isReferenced)
			}
		}
	}

	override protected internalToConvertedExpression(XExpression obj, ITreeAppendable it) {
		if (hasName(obj)) {
			append(getName(obj))
		} else
			super.internalToConvertedExpression(obj, it)
	}

}


TypesComputer:
package org.xtext.example.buggy.jvmmodel

import org.eclipse.xtext.xbase.XExpression
import org.eclipse.xtext.xbase.annotations.typesystem.XbaseWithAnnotationsTypeComputer
import org.eclipse.xtext.xbase.typesystem.computation.ITypeComputationState
import org.xtext.example.buggy.myDsl.InstructionA
import org.xtext.example.buggy.myDsl.InstructionB
import org.xtext.example.buggy.myDsl.RootElement

class MyDslTypeComputer extends XbaseWithAnnotationsTypeComputer {

	override computeTypes(XExpression expression, ITypeComputationState state) {
		if (expression instanceof InstructionA) {
			_computeTypes(expression, state);
		} else if (expression instanceof InstructionB) {
			_computeTypes(expression, state);
		} else if (expression instanceof RootElement) {
			_computeTypes(expression, state);
		} else {
			super.computeTypes(expression, state)
		}
	}

	protected def _computeTypes(RootElement expression, ITypeComputationState state) {
		state.acceptActualType(getTypeForName(Void.TYPE, state));
		if (expression.body !== null) {
			computeTypes(expression.body, state)
		}
	}

	protected def _computeTypes(InstructionA expression, ITypeComputationState state) {
		state.acceptActualType(getTypeForName(Void.TYPE, state));
		if (expression.intProperty !== null) {
			computeTypes(expression.intProperty, state)
		}
		if (expression.body !== null) {
			computeTypes(expression.body, state)
		}
	}

	protected def _computeTypes(InstructionB expression, ITypeComputationState state) {
		state.acceptActualType(getTypeForName(Void.TYPE, state));
		if (expression.body !== null) {
			computeTypes(expression.body, state)
		}
	}

}


Validator:
package org.xtext.example.buggy.validation

import org.eclipse.xtext.xbase.XExpression

class MyDslValidator extends AbstractMyDslValidator {

	def override checkInnerExpressions(XExpression expr) {
	}

}


I wrote tests to reproduce the problem :
package org.xtext.example.buggy.ui.tests

import org.eclipse.xtext.testing.InjectWith
import org.eclipse.xtext.testing.XtextRunner
import org.eclipse.xtext.xbase.junit.ui.AbstractContentAssistTest
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(XtextRunner)
@InjectWith(MyDslUiInjectorProvider)
class ContentAssistTest extends AbstractContentAssistTest {
	
	/**
	 * Always work outside of a for() {} instruction
	 */
	@Test
	def void testWithSuccess1() {
		newBuilder.append('''package aaa
		
		class Test { 
			  
			A intProperty:10 {	}
			B enumProperty: ''').assertText("literal1", "literal2")
	}
	
	/**
	 * Works inside a for instruction, if not preceded by A
	 */
	@Test
	def void testWithSuccess2() {
		newBuilder.append('''
		package aaa
		
		class Test { 
			  
			for (var i = 1; i < 10; i++) { 
				B enumProperty: ''').assertText("literal1", "literal2")
	}
	
	/**
	 * FIXME
	 * Does not work if preceded by A, and if A's intProperty uses a XNumberLiteral
	 */
	@Test
	def void testWithError1() {
		newBuilder.append('''
		package aaa
		
		class Test { 
			  
			for (var i = 1; i < 10; i++) { 
				A intProperty:10 {	}
				B enumProperty: ''').assertText("literal1", "literal2")
	}
	
	/**
	 * But works if preceded by a A instruction with a XFeatureCall integer expression (here a simple reference to a variable) !
	 */
	@Test
	def void testWithSuccess3() {
		newBuilder.append('''
		package aaa
		
		class Test { 
			
			var intValue = 10
			for (var i = 1; i < 10; i++) { 
				A intProperty:intValue {	}
				B enumProperty: ''').assertText("literal1", "literal2")
	}
	
	/**
	 * Works inside while
	 */
	@Test
	def void testWithSuccess4() {
		newBuilder.append('''
		package aaa
		
		class Test { 
			
			var intValue = 10
			while (intValue < 70) {
					A intProperty:10 {	}
					B enumProperty: ''').assertText("literal1", "literal2")
	}
	
	
	/**
	 * Works inside if
	 */
	 @Test
	def void testWithSuccess5() {
		newBuilder.append('''
		package aaa
		
		class Test { 
			
			var intValue = 10
			if (intValue>80) {
					A intProperty:10 {	}
					B enumProperty: ''').assertText("literal1", "literal2")
	}
	
}

Re: Content Assist problem [message #1778789 is a reply to message #1778788] Thu, 21 December 2017 13:08 Go to previous message
Romain Bernard is currently offline Romain BernardFriend
Messages: 18
Registered: July 2009
Junior Member
It seems that the attchment was not really attached. Second try...
Previous Topic:Content Assist problem
Next Topic:Code generator testing strategies
Goto Forum:
  


Current Time: Wed Jan 17 05:43:14 GMT 2018

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

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