Bug 440280 - NPE when JvmIdentifiableElement in Xbase expression does not reside in resource
Summary: NPE when JvmIdentifiableElement in Xbase expression does not reside in resource
Status: CLOSED INVALID
Alias: None
Product: TMF
Classification: Modeling
Component: Xtext (show other bugs)
Version: 2.6.1   Edit
Hardware: Macintosh Mac OS X
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords: needinfo
Depends on:
Blocks:
 
Reported: 2014-07-23 18:41 EDT by Denes Harmath CLA
Modified: 2014-07-25 03:39 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Denes Harmath CLA 2014-07-23 18:41:57 EDT
The following test:

import static org.junit.Assert.assertEquals;

import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.common.types.access.IJvmTypeProvider;
import org.eclipse.xtext.common.types.util.TypeReferences;
import org.eclipse.xtext.naming.IQualifiedNameConverter;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.util.CancelIndicator;
import org.eclipse.xtext.xbase.XFeatureCall;
import org.eclipse.xtext.xbase.XVariableDeclaration;
import org.eclipse.xtext.xbase.XbaseFactory;
import org.eclipse.xtext.xbase.XbaseStandaloneSetup;
import org.eclipse.xtext.xbase.interpreter.IEvaluationContext;
import org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter;
import org.junit.Test;

import com.google.inject.Injector;
import com.google.inject.Provider;

@SuppressWarnings("restriction")
public class TestBug {

	@Test
	public void testName() {
		XVariableDeclaration variable = XbaseFactory.eINSTANCE.createXVariableDeclaration();
		String variableName = "foo";
		variable.setName(variableName);
		Injector injector = new XbaseStandaloneSetup().createInjectorAndDoEMFRegistration();
		IJvmTypeProvider typeProvider = injector.getInstance(IJvmTypeProvider.Factory.class).createTypeProvider();
		JvmType type = typeProvider.findTypeByName(String.class.getName());
		TypeReferences typeReferences = injector.getInstance(TypeReferences.class);
		JvmTypeReference typeReference = typeReferences.createTypeRef(type);
		variable.setType(typeReference);
//		new ResourceImpl().getContents().add(variable); // XXX
		XFeatureCall expression = XbaseFactory.eINSTANCE.createXFeatureCall();
		expression.setFeature(variable);

		XbaseInterpreter interpreter = injector.getInstance(XbaseInterpreter.class);

		interpreter.setClassLoader(getClass().getClassLoader());

		Provider<IEvaluationContext> contextProvider = injector.getProvider(IEvaluationContext.class);

		IQualifiedNameConverter nameConverter = injector.getInstance(IQualifiedNameConverter.class);

		IEvaluationContext evaluationContext = contextProvider.get();
		QualifiedName qualifiedName = nameConverter.toQualifiedName(variableName);
		String expectedValue = "Hello World";
		evaluationContext.newValue(qualifiedName, expectedValue);

		assertEquals(expectedValue, interpreter.evaluate(expression, evaluationContext, CancelIndicator.NullImpl).getResult());
	}

}

Fails with the following exception:

java.lang.NullPointerException
	at org.eclipse.xtext.util.OnChangeEvictingCache.getOrCreate(OnChangeEvictingCache.java:110)
	at org.eclipse.xtext.util.OnChangeEvictingCache.execWithoutCacheClear(OnChangeEvictingCache.java:124)
	at org.eclipse.xtext.xbase.typesystem.internal.CachingBatchTypeResolver.doResolveTypes(CachingBatchTypeResolver.java:51)
	at org.eclipse.xtext.xbase.typesystem.internal.AbstractBatchTypeResolver.resolveTypes(AbstractBatchTypeResolver.java:44)
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203)
	at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:188)
	at com.tttech.rteverify.safetyruleinstancecollector.placeholdercalculator.TestBug.testName(TestBug.java:54)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

If I uncomment the line marked with XXX, it passes.
Comment 1 Sebastian Zarnekow CLA 2014-07-24 03:14:20 EDT
Hi Denes,

EMF Objects that are not contained in a resource cannot work correctly. Basically the resource and its containing resource set belong to the invariant of EObjects. I'm inclined to close this as invalid, but could you please elaborate on your use case before I do that? Maybe I'm missing something.
Comment 2 Denes Harmath CLA 2014-07-24 19:39:00 EDT
Thanks for the reply!
My use case is very similar to this minimal test case: programmatically building and interpreting an Xbase expression that references a JvmIdentifiableElement (an EMF-IncQuery pattern variable, precisely). Is there a more suitable way to achieve this than the code above?
It would be great if this "invariant" was documented somewhere, or maybe Xtext failed earlier when it does not hold.
Comment 3 Sebastian Zarnekow CLA 2014-07-25 02:41:06 EDT
(In reply to Dénes Harmath from comment #2)
> Thanks for the reply!
> My use case is very similar to this minimal test case: programmatically
> building and interpreting an Xbase expression that references a
> JvmIdentifiableElement (an EMF-IncQuery pattern variable, precisely). Is
> there a more suitable way to achieve this than the code above?
> It would be great if this "invariant" was documented somewhere, or maybe
> Xtext failed earlier when it does not hold.

The easiest way would be to parse your expression from text. Otherwise I've serious doubts that it will be straight forward to produce a proper AST for a reasonable complex expression.

Besides that, this invariant is more or less imposed by EMF. The resource sets describes the context of all its contained resources and EObjects. They are pretty much useless without that.
Comment 4 Denes Harmath CLA 2014-07-25 03:39:44 EDT
Okay, thanks for the information! I'll ask on some forum about the way to parse textual Xbase expressions so that my custom JvmIdentifiableElements (in my case, EMF-IncQuery Variables) are resolved properly.