/* * $Id$ * * SARL is an general-purpose agent programming language. * More details on http://www.sarl.io * * Copyright (C) 2014-2017 the original authors or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.sarl.maven.docs.testing; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.inject.Inject; import com.google.common.io.Files; import com.google.inject.Injector; import org.apache.log4j.Level; import org.arakhne.afc.vmutil.FileSystem; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.xtext.diagnostics.Severity; import org.eclipse.xtext.util.Strings; import org.eclipse.xtext.xbase.XExpression; import org.eclipse.xtext.xbase.interpreter.IEvaluationResult; import org.eclipse.xtext.xbase.interpreter.IExpressionInterpreter; import org.junit.ComparisonFailure; import io.sarl.lang.compiler.batch.ICompilatedResourceReceiver; import io.sarl.lang.compiler.batch.SarlBatchCompiler; import io.sarl.lang.sarl.SarlClass; import io.sarl.lang.sarl.SarlField; import io.sarl.lang.sarl.SarlScript; /** Sarl script executor. * * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ * @since 0.6 */ public class SarlScriptExecutor implements ScriptExecutor { private File tmpFolder = null; private String classpath = Strings.emptyIfNull(null); private String bootClasspath = Strings.emptyIfNull(null); private String sourceVersion = Strings.emptyIfNull(null); private SarlBatchCompiler compiler; private IExpressionInterpreter interpreter; /** Change the injector. * * @param injector the new injector. */ @Inject public void setInjector(Injector injector) { if (injector != null) { this.compiler = injector.getInstance(SarlBatchCompiler.class); this.interpreter = injector.getInstance(IExpressionInterpreter.class); } } @Override public void setTempFolder(File dirname) { this.tmpFolder = dirname; } @Override public void setClassPath(String classpath) { this.classpath = Strings.emptyIfNull(classpath); } @Override public void setBootClassPath(String classpath) { this.bootClasspath = Strings.emptyIfNull(classpath); } @Override public void setJavaSourceVersion(String version) { this.sourceVersion = Strings.emptyIfNull(version); } private File createRootFolder() throws IOException { return FileSystem.createTempDirectory("sarldocs", null, this.tmpFolder); //$NON-NLS-1$ } private static File createSourceFolder(File root) { return new File(root, "src"); //$NON-NLS-1$ } private static File createGenFolder(File root) { return new File(root, "src-gen"); //$NON-NLS-1$ } private static File createBinFolder(File root) { return new File(root, "bin"); //$NON-NLS-1$ } private static File createFile(File sourceFolder, String content) throws IOException { File file = new File(sourceFolder, "test.sarl"); //$NON-NLS-1$ file.getParentFile().mkdirs(); Files.write(content.getBytes(), file); return file; } @Override public List<String> compile(int lineno, String code) throws Exception { List<String> issues = new ArrayList<>(); compile(lineno, code, issues, null); return issues; } @Override public File compile(int lineno, String code, List<String> issues, ICompilatedResourceReceiver receiver) throws Exception { File rootFolder = createRootFolder(); File sourceFolder = createSourceFolder(rootFolder); File genFolder = createGenFolder(rootFolder); File binFolder = createBinFolder(rootFolder); this.compiler.setBasePath(rootFolder.getAbsolutePath()); this.compiler.addSourcePath(sourceFolder); this.compiler.setClassOutputPath(binFolder); this.compiler.setOutputPath(genFolder); this.compiler.setGenerateGeneratedAnnotation(false); this.compiler.setGenerateInlineAnnotation(false); this.compiler.setGenerateSyntheticSuppressWarnings(true); this.compiler.setDeleteTempDirectory(false); this.compiler.setClassPath(this.classpath); this.compiler.setBootClassPath(this.bootClasspath); this.compiler.setJavaSourceVersion(this.sourceVersion); this.compiler.setAllWarningSeverities(Severity.IGNORE); this.compiler.setJavaCompilerVerbose(false); this.compiler.getLogger().setLevel(Level.OFF); this.compiler.addIssueMessageListener((issue, uri, message) -> { if (issue.isSyntaxError() || issue.getSeverity().compareTo(Severity.ERROR) >= 0) { final Integer line = issue.getLineNumber(); final int issueLine = (line == null ? 0 : line.intValue()) + lineno; issues.add(message + "(line " + issueLine + ")"); //$NON-NLS-1$ //$NON-NLS-2$ } }); if (receiver != null) { this.compiler.addCompiledResourceReceiver(receiver); } File file = createFile(sourceFolder, code); if (this.compiler.compile()) { issues.clear(); } return file; } @Override public Object execute(int lineno, String code) throws Exception { final List<String> issues = new ArrayList<>(); final Collection<Resource> resources = new ArrayList<>(); compile(lineno, "package x.x.x; class ____Fake_Class____ { var __fake_attr__ : Object = { " + code + " }; }", //$NON-NLS-1$ //$NON-NLS-2$ issues, (it) -> { resources.add(it); }); assertNoIssue(lineno, issues); for (Resource resource : resources) { SarlScript script = (SarlScript) resource.getContents().get(0); SarlClass clazz = (SarlClass) script.getXtendTypes().get(0); SarlField field = (SarlField) clazz.getMembers().get(0); XExpression xexpression = field.getInitialValue(); IEvaluationResult result = this.interpreter.evaluate(xexpression); if (result.getException() == null) { return result.getResult(); } return result.getException(); } return null; } private static void assertNoIssue(int lineno, List<String> issues) { if (issues != null && !issues.isEmpty()) { StringBuilder msg = new StringBuilder(); for (String message : issues) { msg.append(message).append("\n"); //$NON-NLS-1$ } throw new ComparisonFailure("Expecting no issue but find one [line:" + lineno + "]", "", msg.toString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } } }