Przeglądaj źródła

Headless error handling (#1825)

* #1157 : ensure error handler in scope provider is reseted

* to original

* pro#1157 : add error handler for headless mode

* pro#1157 : resolve model elements related to the given generator model
entry

* pro#1157 : ensure errors are thrown out of stext scope provider

* pro#1157 : cleanup

* pro#1157 : resolve eObjects instead of complete resources

* the resource might be null
(org.yakindu.sct.generator.java.util.AbstractJavaGeneratorTest.createGeneratorEntry(String,
String))

* pro#1157 : add license header
Johannes Dicks 8 lat temu
rodzic
commit
eea5ce3213

+ 40 - 0
plugins/org.yakindu.sct.domain.generic.resource/src/org/yakindu/sct/domain/generic/resource/HeadlessErrorHandler.java

@@ -0,0 +1,40 @@
+/** 
+ * Copyright (c) 2017 committers of YAKINDU and others. 
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution, and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ * Contributors:
+ * committers of YAKINDU - initial API and implementation
+ *
+*/
+package org.yakindu.sct.domain.generic.resource;
+
+import org.yakindu.sct.model.stext.scoping.STextScopeProvider.ErrorHandlerDelegate;
+
+/**
+ * 
+ * @author johannes dicks - Initial contribution and API
+ * 
+ */
+public class HeadlessErrorHandler<T> extends ErrorHandlerDelegate<T> {
+	@Override
+	public T handle(Object[] params, Throwable throwable) {
+		/// XXX: has to be an instance of Error because of
+		/// org.eclipse.xtext.util.PolymorphicDispatcher.invoke(Object...)
+		throw new HeadlessError(throwable);
+		// return delegate.handle(params, throwable);
+
+	}
+
+	public static class HeadlessError extends Error {
+
+		private static final long serialVersionUID = -670534113540254487L;
+
+		public HeadlessError(Throwable throwable) {
+			super(throwable);
+		}
+
+	}
+
+}

+ 8 - 1
plugins/org.yakindu.sct.domain.generic.resource/src/org/yakindu/sct/domain/generic/resource/ResourceModuleProvider.java

@@ -16,6 +16,7 @@ import org.yakindu.sct.domain.extension.IDomain;
 import org.yakindu.sct.domain.extension.IModuleProvider;
 import org.yakindu.sct.model.stext.STextRuntimeModule;
 import org.yakindu.sct.model.stext.resource.StextResource;
+import org.yakindu.sct.model.stext.scoping.STextScopeProvider.ErrorHandlerDelegate;
 import org.yakindu.sct.model.stext.ui.STextUiModule;
 import org.yakindu.sct.model.stext.ui.internal.STextActivator;
 
@@ -33,7 +34,13 @@ public class ResourceModuleProvider implements IModuleProvider {
 	@Override
 	public Module getModule(String... options) {
 		if (options.length == 1 && IDomain.OPTION_HEADLESS.equals(options[0])) {
-			return getLanguageRuntimeModule();
+			return Modules.combine(getLanguageRuntimeModule(), new Module() {
+
+				@Override
+				public void configure(Binder binder) {
+					binder.bind(ErrorHandlerDelegate.class).to(HeadlessErrorHandler.class);
+				}
+			});
 		}
 		Module module = Modules.override(getLanguageRuntimeModule())
 				.with(new STextUiModule(STextActivator.getInstance()));

+ 6 - 1
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/execution/GeneratorExecutorLookup.java

@@ -67,7 +67,12 @@ public class GeneratorExecutorLookup {
 		if (typeSystem instanceof AbstractTypeSystem) {
 			ResourceSet set = entry.getElementRef().eResource().getResourceSet();
 			set.getResources().add(((AbstractTypeSystem) typeSystem).getResource());
-			EcoreUtil.resolveAll(set);
+
+			// XXX: avoid resolving the whole resource set, because there might
+			// be models with different domains, we have to ensure that just the models related to the current entry are resolved.
+			EcoreUtil.resolveAll(entry);
+			EcoreUtil.resolveAll(entry.getElementRef());
+			EcoreUtil.resolveAll(((AbstractTypeSystem) typeSystem).getResource());
 		}
 
 		return executor;

+ 16 - 11
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/scoping/STextScopeProvider.java

@@ -55,6 +55,7 @@ import org.yakindu.sct.model.stext.stext.InternalScope;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Lists;
 import com.google.inject.Inject;
+import com.google.inject.Injector;
 
 /**
  * 
@@ -73,17 +74,15 @@ public class STextScopeProvider extends ExpressionsScopeProvider {
 	private IQualifiedNameProvider nameProvider;
 	@Inject
 	private ContextPredicateProvider predicateProvider;
+	@Inject
+	private Injector injector;
 	
-	private static class ErrorHandlerDelegate<T> implements ErrorHandler<T> {
+	public static class ErrorHandlerDelegate<T> implements ErrorHandler<T> {
 
-		private ErrorHandler<T> delegate;
+		protected ErrorHandler<T> delegate;
 
 		public static final Log LOG = LogFactory.getLog(STextScopeProvider.class);
 
-		public ErrorHandlerDelegate(ErrorHandler<T> delegate) {
-			this.delegate = delegate;
-		}
-
 		public T handle(Object[] params, Throwable throwable) {
 			if (throwable instanceof NoSuchMethodException) {
 				LOG.debug("Error in scope method, using fallback", throwable);
@@ -93,19 +92,25 @@ public class STextScopeProvider extends ExpressionsScopeProvider {
 			return delegate.handle(params, throwable);
 		}
 
+		public void setDelegate(ErrorHandler<T> delegate) {
+			this.delegate = delegate;
+		}
+
 	}
 	
 	@Override
 	public IScope getScope(EObject context, EReference reference) {
+		ErrorHandler<IScope> originalHandler = getErrorHandler();
 		try {
-			ErrorHandler<IScope> originalHandler = getErrorHandler();
-			setErrorHandler(new ErrorHandlerDelegate<IScope>(originalHandler));
+			ErrorHandlerDelegate instance = injector.getInstance(ErrorHandlerDelegate.class);
+			instance.setDelegate(originalHandler);
+			setErrorHandler(instance);
 			IScope scope = super.getScope(context, reference);
-			setErrorHandler(originalHandler);
 			return scope;
 		} catch (Throwable t) {
-			t.printStackTrace();
-			return null;
+				throw t;
+		} finally {
+			setErrorHandler(originalHandler);
 		}
 	}