diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 01a427261..000000000 --- a/.gitignore +++ /dev/null @@ -1,58 +0,0 @@ -# Compiled source # -################### -*.jar -*.class -*.rs -*.log -*.orig -*.sh -*.w3x -*.w3m -*.settings -*.classpath -*.im -*.db -*.zip - -#bin folders -*/bin/* -*/target/* -*/dist/* -*/src-gen/* -*/logs/* -*/temp/* -*/WurstSetup/* -WSetup/* -Wurstpack/wurstscript/lib/MapStuff/* -Wurstpack/wurstscript/lib/EBR/* -*/backupsdata.txt - -Wurstpack/war3map.j - -de.peeeq.wurstscript/logs/* -de.peeeq.wurstscript/test-output/* -de.peeeq.wurstscript/junitTestResults/ -de.peeeq.wurstscript/version2.properties - -WurstWeb/gwt-unitCache/* -WurstWeb/war/WEB-INF/classes/* -WurstWeb/war/WEB-INF/deploy/* -WurstWeb/war/wurstweb/* - -*~ -/WurstSetup/WurstSetup/nbproject/private/ -/WurstSetup/WurstSetup/build/ -/bin -Wurstpack/vexorianjasshelper/Blizzard.j -Wurstpack/vexorianjasshelper/common.j -Wurstpack/wurstscript/Blizzard.j -Wurstpack/wurstscript/common.j -Wurstpack/winmpq/temp/* -Wurstpack/wurstscript/logs/* -Wurstpack/tesh/TESH.ini -Checksums/testmd5.txt -/.idea -*.iml -downloads/ -WurstSetup/proguard.map -de.peeeq.wurstscript/output.txt diff --git a/de.peeeq.wurstscript/build.gradle b/de.peeeq.wurstscript/build.gradle index ba1633526..32a6325a0 100644 --- a/de.peeeq.wurstscript/build.gradle +++ b/de.peeeq.wurstscript/build.gradle @@ -5,6 +5,7 @@ buildscript { dependencies { classpath 'de.undercouch:gradle-download-task:3.2.0' classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:1.0.2' + classpath 'org.eclipse.jgit:org.eclipse.jgit:5.7.+' } } @@ -19,6 +20,10 @@ plugins { } import de.undercouch.gradle.tasks.download.Download +import org.eclipse.jgit.api.Git +import org.eclipse.jgit.internal.storage.file.FileRepository +import org.eclipse.jgit.lib.Constants +import org.eclipse.jgit.lib.ObjectId import java.util.regex.Matcher import java.util.regex.Pattern @@ -27,8 +32,10 @@ import java.util.regex.Pattern mainClassName = "de.peeeq.wurstio.Main" version = "1.8.1.0" -sourceCompatibility = '1.8' -targetCompatibility = '1.8' +allprojects { + sourceCompatibility = '1.8' + targetCompatibility = '1.8' +} jacoco { toolVersion = "0.8.5" @@ -105,7 +112,7 @@ dependencies { compile 'com.github.inwc3:jmpq3:1.7.14' // Water's wc3 libs - compile 'com.github.inwc3:wc3libs:257fcbd610' + compile 'com.github.inwc3:wc3libs:fd4b2fd5aa' // The setup tool for wurst.build handling compile 'com.github.wurstscript:wurstsetup:e038293d07' @@ -156,23 +163,11 @@ task versionInfoFile { String gitRevision = "unknown-version" String gitRevisionlong = "unknown-version" - new ByteArrayOutputStream().withStream { os -> - def result = exec { - executable = 'git' - args = ['describe', '--tags', '--always'] - standardOutput = os - } - gitRevision = os.toString().trim() - } + Git git = Git.open(new File(rootProject.projectDir, '..')) + ObjectId head = git.getRepository().resolve(Constants.HEAD) - new ByteArrayOutputStream().withStream { os -> - def result = exec { - executable = 'git' - args = ['describe', '--tags', '--always', '--abbrev=0'] - standardOutput = os - } - gitRevisionlong = os.toString().trim() - } + gitRevision = head.abbreviate(8).name() + gitRevisionlong = head.getName() String wurstVersion = "${version}-${gitRevision}" inputs.property("wurstVersion", wurstVersion) @@ -225,11 +220,6 @@ clean.doFirst { delete genDir } -//task wrapper(type: Wrapper) { -// gradleVersion = '2.12' -//} - - apply plugin: 'de.undercouch.download' @@ -244,6 +234,3 @@ task downloadAndUnzipFile(dependsOn: downloadZipFile, type: Copy) { } apply from: 'deploy.gradle' - - - diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/CompilationProcess.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/CompilationProcess.java index 01e7ae2dc..13e8f1d59 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/CompilationProcess.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/CompilationProcess.java @@ -18,6 +18,7 @@ import java.io.File; import java.io.IOException; import java.io.PrintStream; +import java.util.Optional; /** * @@ -77,8 +78,6 @@ public CompilationProcess(WurstGui gui, RunArgs runArgs) { return null; } - File mapFile = compiler.getMapFile(); - if (runArgs.isRunTests()) { timeTaker.measure("Run tests", () -> runTests(compiler.getImTranslator(), compiler)); @@ -142,7 +141,6 @@ private File writeMapscript(CharSequence mapScript) { if (runArgs.getOutFile() != null) { outputMapscript = new File(runArgs.getOutFile()); } else { - //outputMapscript = File.createTempFile("outputMapscript", ".j"); outputMapscript = new File("./temp/output.j"); } outputMapscript.getParentFile().mkdirs(); @@ -159,13 +157,13 @@ private void runTests(ImTranslator translator, WurstCompilerJassImpl compiler) { // tests gui.sendProgress("Running tests"); System.out.println("Running tests"); - RunTests runTests = new RunTests(null, 0, 0, null) { + RunTests runTests = new RunTests(Optional.empty(), 0, 0, Optional.empty()) { @Override protected void print(String message) { out.print(message); } }; - runTests.runTests(translator, compiler.getImProg(), null, null); + runTests.runTests(translator, compiler.getImProg(), Optional.empty(), Optional.empty()); for (RunTests.TestFailure e : runTests.getFailTests()) { gui.sendError(new CompileError(e.getFunction(), e.getMessage())); @@ -179,6 +177,4 @@ protected void print(String message) { System.out.println("Finished running tests"); } - - } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/CompiletimeFunctionRunner.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/CompiletimeFunctionRunner.java index 2680e6f62..41351d384 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/CompiletimeFunctionRunner.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/CompiletimeFunctionRunner.java @@ -77,7 +77,9 @@ public boolean matches(ImFunction f) { } - public CompiletimeFunctionRunner(ImTranslator tr, ImProg imProg, File mapFile, MpqEditor mpqEditor, WurstGui gui, FunctionFlagToRun flag) { + public CompiletimeFunctionRunner( + ImTranslator tr, ImProg imProg, Optional mapFile, MpqEditor mpqEditor, WurstGui gui, + FunctionFlagToRun flag) { Preconditions.checkNotNull(imProg); this.translator = tr; this.imProg = imProg; @@ -92,8 +94,6 @@ public CompiletimeFunctionRunner(ImTranslator tr, ImProg imProg, File mapFile, M public void run() { -// interpreter.executeFunction("main"); -// interpreter.executeFunction("initGlobals"); try { List> toExecute = new ArrayList<>(); collectCompiletimeExpressions(toExecute); diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/Main.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/Main.java index 99c85cff9..f9435879e 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/Main.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/Main.java @@ -14,6 +14,7 @@ import de.peeeq.wurstio.map.importer.ImportFile; import de.peeeq.wurstio.mpq.MpqEditor; import de.peeeq.wurstio.mpq.MpqEditorFactory; +import de.peeeq.wurstio.utils.W3InstallationData; import de.peeeq.wurstscript.*; import de.peeeq.wurstscript.attributes.CompileError; import de.peeeq.wurstscript.gui.WurstGui; @@ -30,6 +31,7 @@ import java.nio.file.StandardCopyOption; import java.util.LinkedList; import java.util.List; +import java.util.Optional; import static de.peeeq.wurstio.languageserver.ProjectConfigBuilder.FILE_NAME; import static de.peeeq.wurstio.languageserver.WurstCommands.getCompileArgs; @@ -108,7 +110,7 @@ public static void main(String[] args) { try { WurstProjectConfigData projectConfig = null; Path buildDir = null; - Path target = null; + Optional target = Optional.empty(); String workspaceroot = runArgs.getWorkspaceroot(); if (runArgs.isBuild() && runArgs.getInputmap() != null && workspaceroot != null) { Path root = Paths.get(workspaceroot); @@ -118,9 +120,9 @@ public static void main(String[] args) { if (java.nio.file.Files.exists(inputMap) && projectConfig != null) { buildDir = root.resolve("_build"); java.nio.file.Files.createDirectories(buildDir); - target = buildDir.resolve(projectConfig.getBuildMapData().getFileName() + ".w3x"); - java.nio.file.Files.copy(inputMap, target, StandardCopyOption.REPLACE_EXISTING); - runArgs.setMapFile(target.toAbsolutePath().toString()); + target = Optional.of(buildDir.resolve(projectConfig.getBuildMapData().getFileName() + ".w3x")); + java.nio.file.Files.copy(inputMap, target.get(), StandardCopyOption.REPLACE_EXISTING); + runArgs.setMapFile(target.get().toAbsolutePath().toString()); } } @@ -139,7 +141,7 @@ public static void main(String[] args) { @Nullable CharSequence compiledScript; if (mapFilePath != null && workspaceroot != null) { - try (MpqEditor mpqEditor = MpqEditorFactory.getEditor(new File(mapFilePath))) { + try (MpqEditor mpqEditor = MpqEditorFactory.getEditor(Optional.of(new File(mapFilePath)))) { File projectFolder = Paths.get(workspaceroot).toFile(); compiledScript = compilationProcess.doCompilation(mpqEditor, projectFolder); if (compiledScript != null) { @@ -158,11 +160,12 @@ public static void main(String[] args) { File scriptFile = new File("compiled.j.txt"); Files.write(compiledScript.toString().getBytes(Charsets.UTF_8), scriptFile); - if (projectConfig != null && target != null) { - ProjectConfigBuilder.apply(projectConfig, target.toFile(), scriptFile, buildDir.toFile(), runArgs); + if (projectConfig != null && target.isPresent()) { + ProjectConfigBuilder.apply(projectConfig, target.get().toFile(), scriptFile, buildDir.toFile(), + runArgs, new W3InstallationData()); WLogger.info("map build success"); - System.out.println("Build succeeded. Output file: <" + target.toAbsolutePath() + ">"); + System.out.println("Build succeeded. Output file: <" + target.get().toAbsolutePath() + ">"); } } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/WurstCompilerJassImpl.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/WurstCompilerJassImpl.java index b1d8a14a3..397bc45b4 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/WurstCompilerJassImpl.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/WurstCompilerJassImpl.java @@ -49,7 +49,7 @@ public class WurstCompilerJassImpl implements WurstCompiler { private WurstGui gui; private boolean hasCommonJ; private RunArgs runArgs; - private @Nullable File mapFile; + private Optional mapFile = Optional.empty(); private @Nullable File projectFolder; private ErrorHandler errorHandler; private @Nullable Map libCache = null; @@ -141,7 +141,7 @@ public void loadWurstFilesInDir(File dir) { loadFile(f); } else if (f.getName().equals("wurst.dependencies")) { addDependencyFile(f); - } else if ((mapFile == null || runArgs.isNoExtractMapScript()) && f.getName().equals("war3map.j")) { + } else if ((!mapFile.isPresent() || runArgs.isNoExtractMapScript()) && f.getName().equals("war3map.j")) { loadFile(f); } } @@ -178,7 +178,7 @@ private void addDependencyFolder(File f, String folderName) { // search mapFile for (File file : files) { if (file.getName().endsWith(".w3x") || file.getName().endsWith(".w3m")) { - mapFile = file; + mapFile = Optional.ofNullable(file); } else if (file.isDirectory()) { if (projectFolder != null && !file.getParent().equals(projectFolder.getAbsolutePath())) { throw new RuntimeException("Cannot set projectFolder to " + file + " because it is already set to non parent " + projectFolder); @@ -190,10 +190,10 @@ private void addDependencyFolder(File f, String folderName) { // import wurst folder if it exists - File l_mapFile = mapFile; - if (l_mapFile != null) { + Optional l_mapFile = mapFile; + if (l_mapFile.isPresent()) { if (projectFolder == null) { - projectFolder = l_mapFile.getParentFile(); + projectFolder = l_mapFile.get().getParentFile(); } File relativeWurstDir = new File(projectFolder, "wurst"); if (relativeWurstDir.exists()) { @@ -626,7 +626,7 @@ private WurstModel mergeCompilationUnits(List compilationUnits) private CompilationUnit processMap(File file) { gui.sendProgress("Processing Map " + file.getName()); - if (!file.equals(mapFile)) { + if (!mapFile.isPresent() || !file.equals(mapFile.get())) { // TODO check if file != mapFile is possible, would be strange // so this should definitely be done differently throw new Error("file: " + file + " is not the mapfile: " + mapFile); @@ -747,7 +747,7 @@ public ImProg getImProg() { } } - public @Nullable File getMapFile() { + public Optional getMapFile() { return mapFile; } @@ -792,7 +792,7 @@ public void setRunArgs(RunArgs runArgs) { this.runArgs = runArgs; } - public void setMapFile(File mapFile) { + public void setMapFile(Optional mapFile) { this.mapFile = mapFile; } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/intermediateLang/interpreter/ProgramStateIO.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/intermediateLang/interpreter/ProgramStateIO.java index d1e272f58..6cfff8dac 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/intermediateLang/interpreter/ProgramStateIO.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/intermediateLang/interpreter/ProgramStateIO.java @@ -18,6 +18,7 @@ import java.io.PrintStream; import java.util.Iterator; import java.util.Map; +import java.util.Optional; public class ProgramStateIO extends ProgramState { @@ -29,9 +30,9 @@ public class ProgramStateIO extends ProgramState { private final Map objDefinitions = Maps.newLinkedHashMap(); private PrintStream outStream = System.err; private @Nullable WTS trigStrings = null; - private final @Nullable File mapFile; + private final Optional mapFile; - public ProgramStateIO(@Nullable File mapFile, @Nullable MpqEditor mpqEditor, WurstGui gui, ImProg prog, boolean isCompiletime) { + public ProgramStateIO(Optional mapFile, @Nullable MpqEditor mpqEditor, WurstGui gui, ImProg prog, boolean isCompiletime) { super(gui, prog, isCompiletime); this.mapFile = mapFile; this.mpqEditor = mpqEditor; @@ -191,8 +192,8 @@ public void writeBack(boolean inject) { } private void writeW3oFile() { - File objFile = new File(getObjectEditingOutputFolder(), "wurstCreatedObjects.w3o"); - try (BinaryDataOutputStream objFileStream = new BinaryDataOutputStream(objFile, true)) { + Optional objFile = getObjectEditingOutputFolder().map(fo -> new File(fo, "wurstCreatedObjects.w3o")); + try (BinaryDataOutputStream objFileStream = new BinaryDataOutputStream(objFile.get(), true)) { objFileStream.writeInt(1); // version for (ObjectFileType fileType : ObjectFileType.values()) { ObjectFile dataStore = getDataStore(fileType); @@ -210,12 +211,14 @@ private void writeW3oFile() { private void writebackObjectFile(ObjectFile dataStore, ObjectFileType fileType, boolean inject) throws Error { try { - File folder = getObjectEditingOutputFolder(); + Optional folder = getObjectEditingOutputFolder(); byte[] w3u = dataStore.writeToByteArray(); // wurst exported objects - FileUtils.write(dataStore.exportToWurst(fileType), new File(folder, "WurstExportedObjects_" + fileType.getExt() + ".wurst.txt")); + FileUtils.write( + dataStore.exportToWurst(fileType), + new File(folder.get(), "WurstExportedObjects_" + fileType.getExt() + ".wurst.txt")); if (inject) { if (mpqEditor == null) { @@ -232,16 +235,16 @@ private void writebackObjectFile(ObjectFile dataStore, ObjectFileType fileType, } - private @Nullable File getObjectEditingOutputFolder() { - if (mapFile == null) { + private Optional getObjectEditingOutputFolder() { + if (!mapFile.isPresent()) { File folder = new File("_build", "objectEditingOutput"); folder.mkdirs(); - return folder; + return Optional.of(folder); } - File folder = new File(mapFile.getParent(), "objectEditingOutput"); - if (!folder.exists() && !folder.mkdirs()) { - WLogger.info("Could not create folder " + folder.getAbsoluteFile()); - return null; + Optional folder = mapFile.map(fi -> new File(fi.getParent(), "objectEditingOutput")); + if (!folder.isPresent() || (!folder.get().exists() && !folder.get().mkdirs())) { + WLogger.info("Could not create folder " + folder.map(fo -> fo.getAbsoluteFile())); + return Optional.empty(); } return folder; } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ConfigProvider.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ConfigProvider.java index ec51baf6a..6c3682e89 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ConfigProvider.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ConfigProvider.java @@ -12,6 +12,7 @@ import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -54,16 +55,15 @@ public String getConfig(String key, String defaultValue) { public String getJhcrExe() { return getConfig("jhcrExe", "jhcr.exe"); } - - public String getWc3RunArgs() { - return getConfig("wc3RunArgs", null); + + public Optional getWc3RunArgs() { + return Optional.ofNullable(getConfig("wc3RunArgs", null)); } /** * The path where to put maps before running them */ - public String getMapDocumentPath() { - return getConfig("mapDocumentPath", null); + public Optional getMapDocumentPath() { + return Optional.ofNullable(getConfig("mapDocumentPath", null)); } } - diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/LanguageWorker.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/LanguageWorker.java index 89939d548..48872083e 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/LanguageWorker.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/LanguageWorker.java @@ -6,7 +6,6 @@ import org.eclipse.lsp4j.*; import org.eclipse.lsp4j.services.LanguageClient; -import java.io.FileNotFoundException; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicLong; @@ -49,7 +48,6 @@ public void setRootPath(WFile rootPath) { private WFile rootPath; private final Object lock = new Object(); - private int initRequestSequenceNr = -1; private BufferManager bufferManager = new BufferManager(); private LanguageClient languageClient; @@ -72,15 +70,6 @@ public void stop() { thread.interrupt(); } - -// public void handleRuntests(int sequenceNr, String filename, int line, int column) { -// synchronized (lock) { -// userRequests.add(new RunTests(sequenceNr, server, filename, line, column)); -// lock.notifyAll(); -// } -// -// } - abstract class PendingChange { private long time; private WFile filename; @@ -213,8 +202,6 @@ private void doInit(WFile rootPath) { modelManager.buildProject(); log("Finished building " + rootPath); - // TODO -// server.reply(initRequestSequenceNr, "done"); } catch (Exception e) { WLogger.severe(e); } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ModelManager.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ModelManager.java index 7d31adcc7..314d56883 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ModelManager.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ModelManager.java @@ -2,14 +2,12 @@ import de.peeeq.wurstscript.ast.CompilationUnit; import de.peeeq.wurstscript.ast.ModuleInstanciations; -import de.peeeq.wurstscript.ast.NoExpr; import de.peeeq.wurstscript.ast.WurstModel; import de.peeeq.wurstscript.attributes.CompileError; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.lsp4j.PublishDiagnosticsParams; import java.io.File; -import java.io.IOException; import java.util.List; import java.util.Set; import java.util.function.Consumer; diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ModelManagerImpl.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ModelManagerImpl.java index 153a57b86..be605b5ac 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ModelManagerImpl.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ModelManagerImpl.java @@ -640,13 +640,6 @@ private Set addPackageDependencies(List toChec return result; } - private Collection providedPackages(Collection result) { - return result.stream() - .flatMap(cu -> cu.getPackages().stream()) - .map(WPackage::getName) - .collect(Collectors.toSet()); - } - private void addImportingPackages(Collection providedPackages, WurstModel model2, Set result) { nextCu: for (CompilationUnit compilationUnit : model2) { diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ProjectConfigBuilder.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ProjectConfigBuilder.java index fd210e610..954722a6b 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ProjectConfigBuilder.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/ProjectConfigBuilder.java @@ -6,11 +6,13 @@ import de.peeeq.wurstio.languageserver.requests.RequestFailedException; import de.peeeq.wurstio.mpq.MpqEditor; import de.peeeq.wurstio.mpq.MpqEditorFactory; -import de.peeeq.wurstio.utils.W3Utils; +import de.peeeq.wurstio.utils.W3InstallationData; import de.peeeq.wurstscript.RunArgs; import net.moonlightflower.wc3libs.bin.app.MapFlag; import net.moonlightflower.wc3libs.bin.app.MapHeader; import net.moonlightflower.wc3libs.bin.app.W3I; +import net.moonlightflower.wc3libs.bin.app.W3I.Force; +import net.moonlightflower.wc3libs.bin.app.W3I.Player; import net.moonlightflower.wc3libs.dataTypes.app.Controller; import net.moonlightflower.wc3libs.port.GameVersion; import org.apache.commons.lang.StringUtils; @@ -28,13 +30,14 @@ public class ProjectConfigBuilder { public static final String FILE_NAME = "wurst.build"; - public static void apply(WurstProjectConfigData projectConfig, File targetMap, File compiledScript, File buildDir, RunArgs runArgs) throws IOException { + public static void apply(WurstProjectConfigData projectConfig, File targetMap, File compiledScript, File buildDir, + RunArgs runArgs, W3InstallationData w3data) throws IOException { if (projectConfig.getProjectName().isEmpty()) { throw new RequestFailedException(MessageType.Error, "wurst.build is missing projectName."); } - try (MpqEditor mpq = MpqEditorFactory.getEditor((targetMap))) { + try (MpqEditor mpq = MpqEditorFactory.getEditor(Optional.of(targetMap))) { File file = new File(buildDir, "wc3libs_injected.j"); byte[] scriptBytes; if (!projectConfig.getBuildMapData().getName().isEmpty()) { @@ -48,8 +51,8 @@ public static void apply(WurstProjectConfigData projectConfig, File targetMap, F // TODO apply config for hot start before JHCR transformation scriptBytes = java.nio.file.Files.readAllBytes(compiledScript.toPath()); } else { - if (W3Utils.getWc3PatchVersion() != null) { - w3I.injectConfigsInJassScript(inputStream, sw, W3Utils.getWc3PatchVersion()); + if (w3data.getWc3PatchVersion().isPresent()) { + w3I.injectConfigsInJassScript(inputStream, sw, w3data.getWc3PatchVersion().get()); } else { w3I.injectConfigsInJassScript(inputStream, sw, GameVersion.VERSION_1_32); } @@ -95,7 +98,7 @@ public static void apply(WurstProjectConfigData projectConfig, File targetMap, F } private static W3I prepareW3I(WurstProjectConfigData projectConfig, File targetMap) throws Exception { - try (MpqEditor mpq = MpqEditorFactory.getEditor((targetMap))) { + try (MpqEditor mpq = MpqEditorFactory.getEditor(Optional.of(targetMap))) { W3I w3I = new W3I(mpq.extractFile("war3map.w3i")); WurstProjectBuildMapData buildMapData = projectConfig.getBuildMapData(); if (StringUtils.isNotBlank(buildMapData.getName())) { @@ -151,7 +154,7 @@ private static void applyForces(WurstProjectConfigData projectConfig, W3I w3I) { w3I.clearForces(); ArrayList forces = projectConfig.getBuildMapData().getForces(); for (WurstProjectBuildForce wforce : forces) { - W3I.Force force = w3I.addForce(); + W3I.Force force = new Force(); force.setName(wforce.getName()); force.setFlag(W3I.Force.Flags.Flag.ALLIED, wforce.getFlags().getAllied()); force.setFlag(W3I.Force.Flags.Flag.ALLIED_VICTORY, wforce.getFlags().getAlliedVictory()); @@ -159,6 +162,7 @@ private static void applyForces(WurstProjectConfigData projectConfig, W3I w3I) { force.setFlag(W3I.Force.Flags.Flag.SHARED_UNIT_CONTROL, wforce.getFlags().getSharedControl()); force.setFlag(W3I.Force.Flags.Flag.SHARED_UNIT_CONTROL_ADVANCED, wforce.getFlags().getSharedControlAdvanced()); force.addPlayerNums(wforce.getPlayerIds()); + w3I.addForce(force); } w3I.setFlag(MapFlag.USE_CUSTOM_FORCES, true); } @@ -169,8 +173,9 @@ private static void applyPlayers(WurstProjectConfigData projectConfig, W3I w3I) ArrayList players = projectConfig.getBuildMapData().getPlayers(); for (WurstProjectBuildPlayer wplayer : players) { Optional old = existing.stream().filter(player -> player.getNum() == wplayer.getId()).findFirst(); - W3I.Player player = w3I.addPlayer(); + W3I.Player player = new Player(); player.setNum(wplayer.getId()); + w3I.addPlayer(player); old.ifPresent(player1 -> applyExistingPlayerConfig(player1, player)); diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/WurstCommands.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/WurstCommands.java index d2ee158a7..dad629353 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/WurstCommands.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/WurstCommands.java @@ -2,7 +2,6 @@ import com.google.common.base.Charsets; import com.google.common.collect.ImmutableList; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import de.peeeq.wurstio.languageserver.requests.*; import de.peeeq.wurstscript.WLogger; @@ -15,6 +14,7 @@ import java.nio.file.Paths; import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -66,10 +66,10 @@ public static CompletableFuture execute(WurstLanguageServer server, Exec private static CompletableFuture testMap(WurstLanguageServer server, ExecuteCommandParams params) { JsonObject options = (JsonObject) params.getArguments().get(0); - String filename = getString(options, "filename"); + Optional filename = getString(options, "filename"); int line = options.has("line") ? options.get("line").getAsInt() : -1; int column = options.has("column") ? options.get("column").getAsInt() : -1; - String testName = getString(options, "testName"); + Optional testName = getString(options, "testName"); return server.worker().handle(new RunTests(filename, line, column, testName)); } @@ -79,13 +79,13 @@ private static CompletableFuture buildmap(WurstLanguageServer server, Ex throw new RuntimeException("Missing arguments"); } JsonObject options = (JsonObject) params.getArguments().get(0); - String mapPath = getString(options, "mappath"); - String wc3Path = getString(options, "wc3path"); - if (mapPath == null) { + Optional mapPath = getString(options, "mappath"); + Optional wc3Path = getString(options, "wc3path"); + if (!mapPath.isPresent()) { throw new RuntimeException("No mappath given"); } - File map = new File(mapPath); + Optional map = mapPath.map(path -> new File(path)); List compileArgs = getCompileArgs(workspaceRoot); return server.worker().handle(new BuildMap(server.getConfigProvider(), workspaceRoot, wc3Path, map, compileArgs)).thenApply(x -> x); } @@ -97,20 +97,21 @@ private static CompletableFuture startmap(WurstLanguageServer server, Ex } JsonObject options = (JsonObject) params.getArguments().get(0); String key = "mappath"; - String mapPath = getString(options, key); - String wc3Path = getString(options, "wc3path"); + Optional mapPath = getString(options, key); + Optional wc3Path = getString(options, "wc3path"); - File map = mapPath == null ? null : new File(mapPath); + Optional map = mapPath.map(mp -> new File(mp)); List compileArgs = getCompileArgs(workspaceRoot, additionalArgs); return server.worker().handle(new RunMap(server.getConfigProvider(), workspaceRoot, wc3Path, map, compileArgs)).thenApply(x -> x); } - private static String getString(JsonObject options, String key) { - JsonElement jsonElement = options.get(key); - if (jsonElement == null) { - return null; + private static Optional getString(JsonObject options, String key) { + try { + return Optional.ofNullable(options.get(key)).map(jsonElement -> jsonElement.getAsString()); + } catch (ClassCastException | IllegalStateException e) { + WLogger.warning("Invalid configuration", e); + return Optional.empty(); } - return jsonElement.getAsString(); } private static final List defaultArgs = ImmutableList.of("-runcompiletimefunctions", "-injectobjects", "-stacktraces"); diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/BuildMap.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/BuildMap.java index 6e7c19da7..09b20c625 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/BuildMap.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/BuildMap.java @@ -11,13 +11,13 @@ import de.peeeq.wurstscript.attributes.CompileError; import de.peeeq.wurstscript.gui.WurstGui; import org.eclipse.lsp4j.MessageType; -import org.jetbrains.annotations.Nullable; import systems.crigges.jmpq3.JMpqEditor; import systems.crigges.jmpq3.MPQOpenOption; import java.io.File; import java.io.IOException; import java.util.List; +import java.util.Optional; import static de.peeeq.wurstio.languageserver.ProjectConfigBuilder.FILE_NAME; @@ -26,7 +26,8 @@ */ public class BuildMap extends MapRequest { - public BuildMap(ConfigProvider configProvider, WFile workspaceRoot, @Nullable String wc3Path, File map, List compileArgs) { + public BuildMap(ConfigProvider configProvider, WFile workspaceRoot, Optional wc3Path, Optional map, + List compileArgs) { super(configProvider, map, compileArgs, workspaceRoot, wc3Path); } @@ -46,11 +47,11 @@ public Object execute(ModelManager modelManager) throws IOException { WLogger.info("buildMap " + map + " " + compileArgs); WurstGui gui = new WurstGuiImpl(workspaceRoot.getFile().getAbsolutePath()); try { - if (map == null) { + if (!map.isPresent()) { throw new RequestFailedException(MessageType.Error, "Map is null"); } - if (!map.exists()) { - throw new RequestFailedException(MessageType.Error, map.getAbsolutePath() + " does not exist."); + if (!map.get().exists()) { + throw new RequestFailedException(MessageType.Error, map.get().getAbsolutePath() + " does not exist."); } gui.sendProgress("Copying map"); @@ -58,13 +59,14 @@ public Object execute(ModelManager modelManager) throws IOException { // first we copy in same location to ensure validity File buildDir = getBuildDir(); String fileName = projectConfig.getBuildMapData().getFileName(); - File targetMap = new File(buildDir, fileName.isEmpty() ? projectConfig.getProjectName() + ".w3x" : fileName + ".w3x"); + Optional targetMap = Optional.of( + new File(buildDir, fileName.isEmpty() ? projectConfig.getProjectName() + ".w3x" : fileName + ".w3x")); File compiledScript = compileScript(modelManager, gui, targetMap); gui.sendProgress("Applying Map Config..."); - ProjectConfigBuilder.apply(projectConfig, targetMap, compiledScript, buildDir, runArgs); + ProjectConfigBuilder.apply(projectConfig, targetMap.get(), compiledScript, buildDir, runArgs, w3data); - JMpqEditor finalizer = new JMpqEditor(targetMap, MPQOpenOption.FORCE_V0); + JMpqEditor finalizer = new JMpqEditor(targetMap.get(), MPQOpenOption.FORCE_V0); finalizer.close(); gui.sendProgress("Done."); @@ -81,6 +83,4 @@ public Object execute(ModelManager modelManager) throws IOException { } return "ok"; // TODO } - - } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/CodeActionRequest.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/CodeActionRequest.java index 45ccd1d1d..84d818d8d 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/CodeActionRequest.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/CodeActionRequest.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import static de.peeeq.wurstio.languageserver.WurstCommands.WURST_PERFORM_CODE_ACTION; @@ -61,32 +62,38 @@ public List> execute(ModelManager modelManager) { return Collections.emptyList(); } // get element under cursor - Element e = Utils.getAstElementAtPos(cu, line, column, false); + Optional e = Utils.getAstElementAtPos(cu, line, column, false); WLogger.info("Code action on element " + Utils.printElementWithSource(e)); - if (e instanceof ExprNewObject) { - ExprNewObject enew = (ExprNewObject) e; + if (!e.isPresent()) { + // TODO non simple TypeRef + + return Collections.emptyList(); + } + + if (e.get() instanceof ExprNewObject) { + ExprNewObject enew = (ExprNewObject) e.get(); ConstructorDef constructorDef = enew.attrConstructorDef(); if (constructorDef == null) { return handleMissingClass(modelManager, enew.getTypeName()); } - } else if (e instanceof FuncRef) { - FuncRef fr = (FuncRef) e; + } else if (e.get() instanceof FuncRef) { + FuncRef fr = (FuncRef) e.get(); FuncLink fd = fr.attrFuncLink(); if (fd == null) { return handleMissingFunction(modelManager, fr); } - } else if (e instanceof NameRef) { - NameRef nr = (NameRef) e; + } else if (e.get() instanceof NameRef) { + NameRef nr = (NameRef) e.get(); NameLink nd = nr.attrNameLink(); if (nd == null) { return handleMissingName(modelManager, nr); } - } else if (e instanceof TypeExprSimple) { - TypeExprSimple nr = (TypeExprSimple) e; + } else if (e.get() instanceof TypeExprSimple) { + TypeExprSimple nr = (TypeExprSimple) e.get(); TypeDef nd = nr.attrTypeDef(); if (nd == null) { return handleMissingType(modelManager, nr.getTypeName()); diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/Colors.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/Colors.java index decbdf9eb..b199fa982 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/Colors.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/Colors.java @@ -4,7 +4,6 @@ import de.peeeq.wurstio.languageserver.ModelManager; import de.peeeq.wurstio.languageserver.WFile; import de.peeeq.wurstscript.ast.*; -import de.peeeq.wurstscript.jassIm.ImIntVal; import de.peeeq.wurstscript.utils.Utils; import org.eclipse.lsp4j.*; @@ -12,6 +11,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -34,13 +34,14 @@ public DocumentColorRequest(DocumentColorParams params) { @Override public List execute(ModelManager modelManager) throws IOException { - CompilationUnit cu = modelManager.getCompilationUnit(WFile.create(textDocument)); - if (cu == null) { + Optional cu = Optional.ofNullable( + modelManager.getCompilationUnit(WFile.create(textDocument))); + if (!cu.isPresent()) { return Collections.emptyList(); } List result = new ArrayList<>(); - cu.accept(new Element.DefaultVisitor() { + cu.get().accept(new Element.DefaultVisitor() { @Override public void visit(ExprFunctionCall call) { Arguments args = call.getArgs(); @@ -100,18 +101,24 @@ public ColorPresentationRequest(ColorPresentationParams params) { @Override public List execute(ModelManager modelManager) { - CompilationUnit cu = modelManager.getCompilationUnit(WFile.create(textDocument)); - if (cu == null) { + Optional cu = Optional.ofNullable( + modelManager.getCompilationUnit(WFile.create(textDocument))); + if (!cu.isPresent()) { return Collections.emptyList(); } - Element elem = Utils.getAstElementAtPos(cu, range.getStart().getLine() + 1, range.getStart().getCharacter() + 2, false); + Optional elemAtPos = Utils.getAstElementAtPos(cu.get(), range.getStart().getLine() + 1, + range.getStart().getCharacter() + 2, false); + if (!elemAtPos.isPresent()) { + return Collections.emptyList(); + } + Element elem = elemAtPos.get(); if (elem instanceof ExprIntVal - && elem.getParent() != null) { + && Optional.ofNullable(elem.getParent()).isPresent()) { elem = elem.getParent(); } if (elem instanceof Arguments - && elem.getParent() != null) { + && Optional.ofNullable(elem.getParent()).isPresent()) { elem = elem.getParent(); } @@ -153,7 +160,7 @@ public static void collectStringColors(String s, List result, s = Utils.escapeStringWithoutQuotes(s); Matcher matcher = colorPattern.matcher(s); - for (int i = 0; matcher.find(); i++) { + for ( ; matcher.find(); ) { double red = Integer.parseInt(matcher.group(2), 16) / 255.; double green = Integer.parseInt(matcher.group(3), 16) / 255.; double blue = Integer.parseInt(matcher.group(4), 16) / 255.; diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/GetCompletions.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/GetCompletions.java index 7d9971df8..bc2b1bec6 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/GetCompletions.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/GetCompletions.java @@ -109,7 +109,7 @@ public List computeCompletionProposals(CompilationUnit cu) { searchMode = mode; List completions = Lists.newArrayList(); - elem = Utils.getAstElementAtPos(cu, line, column + 1, false); + elem = Utils.getAstElementAtPos(cu, line, column + 1, false).get(); WLogger.info("get completions at " + Utils.printElement(elem)); expectedType = null; if (elem instanceof Expr) { @@ -123,8 +123,6 @@ public List computeCompletionProposals(CompilationUnit cu) { dropBadCompletions(completions); removeDuplicates(completions); - // Collections.sort(completions, c) - if (completions.size() > 0) { return completions; } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/GetDefinition.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/GetDefinition.java index ab1272764..17608b62a 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/GetDefinition.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/GetDefinition.java @@ -45,7 +45,7 @@ private List execute2(ModelManager modelManager) { if (cu == null) { return Collections.emptyList(); } - Element e = Utils.getAstElementAtPos(cu, line, column, false); + Element e = Utils.getAstElementAtPos(cu, line, column, false).get(); WLogger.info("get definition at: " + e.getClass().getSimpleName()); if (e instanceof FuncRef) { FuncRef funcRef = (FuncRef) e; diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/GetUsages.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/GetUsages.java index aa75507e1..5ef088ea8 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/GetUsages.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/GetUsages.java @@ -37,14 +37,15 @@ public List execute(ModelManager modelManager) { if (cu == null) { return Collections.emptyList(); } - Element astElem = Utils.getAstElementAtPos(cu, line, column, false); - NameDef nameDef = astElem.tryGetNameDef(); + Optional astElem = Utils.getAstElementAtPos(cu, line, column, false); + Optional nameDef = astElem.flatMap(elem -> Optional.ofNullable(elem.tryGetNameDef())); List usages = new ArrayList<>(); - if (nameDef != null) { + if (nameDef.isPresent()) { - if (global || nameDef.getSource().getFile().equals(wFile.toString())) { + if (global || nameDef.get().getSource().getFile().equals(wFile.toString())) { // add declaration - usages.add(new UsagesData(Convert.posToLocation(nameDef.attrErrorPos()), DocumentHighlightKind.Write)); + usages.add( + new UsagesData(Convert.posToLocation(nameDef.get().attrErrorPos()), DocumentHighlightKind.Write)); } Deque todo = new ArrayDeque<>(); if (global) { @@ -59,7 +60,7 @@ public List execute(ModelManager modelManager) { todo.push(e.get(i)); } NameDef e_def = e.tryGetNameDef(); - if (e_def == nameDef) { + if (e_def == nameDef.get()) { UsagesData usagesData = new UsagesData(Convert.posToLocation(e.attrErrorPos()), DocumentHighlightKind.Read); usages.add(usagesData); } @@ -69,14 +70,8 @@ public List execute(ModelManager modelManager) { return usages; } -// static enum DocumentHighlightKind { -// Text, Read, Write -// } - public static class UsagesData { private Location location; -// private String wFile; -// private Range range; private DocumentHighlightKind kind; diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/HoverInfo.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/HoverInfo.java index 67fb6b941..913f11bce 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/HoverInfo.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/HoverInfo.java @@ -44,7 +44,7 @@ public Hover execute(ModelManager modelManager) { if (cu == null) { return new Hover(Collections.singletonList(Either.forLeft("File " + filename + " is not part of the project. Move it to the wurst folder."))); } - Element e = Utils.getAstElementAtPos(cu, line, column, false); + Element e = Utils.getAstElementAtPos(cu, line, column, false).get(); WLogger.info("hovering over " + Utils.printElement(e)); List> desription = e.match(new Description()); desription = addArgumentHint(e, desription); diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/MapRequest.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/MapRequest.java index 13c718de5..3949eb574 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/MapRequest.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/MapRequest.java @@ -10,7 +10,7 @@ import de.peeeq.wurstio.languageserver.WFile; import de.peeeq.wurstio.mpq.MpqEditor; import de.peeeq.wurstio.mpq.MpqEditorFactory; -import de.peeeq.wurstio.utils.W3Utils; +import de.peeeq.wurstio.utils.W3InstallationData; import de.peeeq.wurstscript.RunArgs; import de.peeeq.wurstscript.WLogger; import de.peeeq.wurstscript.ast.CompilationUnit; @@ -40,6 +40,7 @@ import java.time.Duration; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; @@ -47,11 +48,12 @@ public abstract class MapRequest extends UserRequest { protected final ConfigProvider configProvider; protected final @Nullable - File map; + Optional map; protected final List compileArgs; protected final WFile workspaceRoot; protected final RunArgs runArgs; - @Nullable protected final String wc3Path; + protected final Optional wc3Path; + protected final W3InstallationData w3data; /** * makes the compilation slower, but more safe by discarding results from the editor and working on a copy of the model @@ -62,13 +64,15 @@ enum SafetyLevel { QuickAndDirty, KindOfSafe } - public MapRequest(ConfigProvider configProvider, @Nullable File map, List compileArgs, WFile workspaceRoot, String wc3Path) { + public MapRequest(ConfigProvider configProvider, Optional map, List compileArgs, WFile workspaceRoot, + Optional wc3Path) { this.configProvider = configProvider; this.map = map; this.compileArgs = compileArgs; this.workspaceRoot = workspaceRoot; this.runArgs = new RunArgs(compileArgs); this.wc3Path = wc3Path; + this.w3data = getBestW3InstallationData(); } @Override @@ -82,11 +86,12 @@ public void handleException(LanguageClient languageClient, Throwable err, Comple } } - protected void processMapScript(RunArgs runArgs, WurstGui gui, ModelManager modelManager, File mapCopy) throws Exception { + protected void processMapScript( + RunArgs runArgs, WurstGui gui, ModelManager modelManager, Optional mapCopy) throws Exception { File existingScript = new File(new File(workspaceRoot.getFile(), "wurst"), "war3map.j"); // If runargs are no extract, either use existing or throw error // Otherwise try loading from map, if map was saved with wurst, try existing script, otherwise error - if (mapCopy == null || runArgs.isNoExtractMapScript()) { + if (!mapCopy.isPresent() || runArgs.isNoExtractMapScript()) { if (existingScript.exists()) { modelManager.syncCompilationUnit(WFile.create(existingScript)); return; @@ -97,7 +102,7 @@ protected void processMapScript(RunArgs runArgs, WurstGui gui, ModelManager mode } WLogger.info("extracting mapscript"); byte[] extractedScript = null; - try (MpqEditor mpqEditor = MpqEditorFactory.getEditor(mapCopy)) { + try (@Nullable MpqEditor mpqEditor = MpqEditorFactory.getEditor(mapCopy)) { if (mpqEditor.hasFile("war3map.j")) { extractedScript = mpqEditor.extractFile("war3map.j"); } @@ -135,9 +140,8 @@ protected void processMapScript(RunArgs runArgs, WurstGui gui, ModelManager mode modelManager.syncCompilationUnit(WFile.create(existingScript)); } - protected File compileMap(File projectFolder, WurstGui gui, File mapCopy, RunArgs runArgs, WurstModel model) { + protected File compileMap(File projectFolder, WurstGui gui, Optional mapCopy, RunArgs runArgs, WurstModel model) { try (@Nullable MpqEditor mpqEditor = MpqEditorFactory.getEditor(mapCopy)) { - //WurstGui gui = new WurstGuiLogger(); if (mpqEditor != null && !mpqEditor.canWrite()) { WLogger.severe("The supplied map is invalid/corrupted/protected and Wurst cannot write to it.\n" + "Please supply a valid .w3x input map that can be opened in the world editor."); @@ -166,15 +170,15 @@ protected File compileMap(File projectFolder, WurstGui gui, File mapCopy, RunArg if (runArgs.isLua()) { print("translating program to Lua ... "); - LuaCompilationUnit luaCode = compiler.transformProgToLua(); + Optional luaCode = Optional.ofNullable(compiler.transformProgToLua()); - if (luaCode == null) { + if (!luaCode.isPresent()) { print("Could not compile project\n"); throw new RuntimeException("Could not compile project (error in LUA translation)"); } StringBuilder sb = new StringBuilder(); - luaCode.print(sb, 0); + luaCode.get().print(sb, 0); String compiledMapScript = sb.toString(); File buildDir = getBuildDir(); @@ -186,14 +190,14 @@ protected File compileMap(File projectFolder, WurstGui gui, File mapCopy, RunArg print("translating program to jass ... "); compiler.transformProgToJass(); - JassProg jassProg = compiler.getProg(); - if (jassProg == null) { + Optional jassProg = Optional.ofNullable(compiler.getProg()); + if (!jassProg.isPresent()) { print("Could not compile project\n"); throw new RuntimeException("Could not compile project (error in JASS translation)"); } gui.sendProgress("Printing program"); - JassPrinter printer = new JassPrinter(!runArgs.isOptimize(), jassProg); + JassPrinter printer = new JassPrinter(!runArgs.isOptimize(), jassProg.get()); String compiledMapScript = printer.printProg(); File buildDir = getBuildDir(); File outFile = new File(buildDir, "compiled.j.txt"); @@ -240,7 +244,7 @@ private File runJassHotCodeReload(File mapScript) throws IOException, Interrupte ProcessBuilder pb = new ProcessBuilder(configProvider.getJhcrExe(), "init", commonJ.getName(), blizzardJ.getName(), mapScript.getName()); pb.directory(buildDir); - Utils.ExecResult result = Utils.exec(pb, Duration.ofSeconds(30), System.err::println); + Utils.exec(pb, Duration.ofSeconds(30), System.err::println); return new File(buildDir, "jhcr_war3map.j"); } @@ -310,7 +314,7 @@ protected void println(String s) { } - protected File compileScript(WurstGui gui, ModelManager modelManager, List compileArgs, @Nullable File mapCopy) throws Exception { + protected File compileScript(WurstGui gui, ModelManager modelManager, List compileArgs, Optional mapCopy) throws Exception { RunArgs runArgs = new RunArgs(compileArgs); print("Compile Script : "); for (File dep : modelManager.getDependencyWurstFiles()) { @@ -344,24 +348,26 @@ protected File compileScript(WurstGui gui, ModelManager modelManager, List testMap) throws Exception { + if (testMap.isPresent() && testMap.get().exists()) { + boolean deleteOk = testMap.get().delete(); if (!deleteOk) { throw new RequestFailedException(MessageType.Error, "Could not delete old mapfile: " + testMap); } } - if (map != null) { - Files.copy(map, testMap); + if (map.isPresent() && testMap.isPresent()) { + Files.copy(map.get(), testMap.get()); } - parseCustomPatchVersion(); - // first compile the script: File compiledScript = compileScript(gui, modelManager, compileArgs, testMap); - WurstModel model = modelManager.getModel(); - if (model == null || model.stream().noneMatch((CompilationUnit cu) -> cu.getCuInfo().getFile().endsWith("war3map.j"))) { + Optional model = Optional.ofNullable(modelManager.getModel()); + if (!model.isPresent() + || model + .get() + .stream() + .noneMatch((CompilationUnit cu) -> cu.getCuInfo().getFile().endsWith("war3map.j"))) { println("No 'war3map.j' file could be found inside the map nor inside the wurst folder"); println("If you compile the map with WurstPack once, this file should be in your wurst-folder. "); println("We will try to start the map now, but it will probably fail. "); @@ -369,12 +375,16 @@ protected File compileScript(ModelManager modelManager, WurstGui gui, @Nullable return compiledScript; } - private void parseCustomPatchVersion() { - if (wc3Path != null) { - W3Utils.parsePatchVersion(new File(wc3Path)); - if (W3Utils.getWc3PatchVersion() == null) { + private W3InstallationData getBestW3InstallationData() throws RequestFailedException { + if (wc3Path.isPresent()) { + W3InstallationData w3data = new W3InstallationData(new File(wc3Path.get())); + if (!w3data.getWc3PatchVersion().isPresent()) { throw new RequestFailedException(MessageType.Error, "Could not find Warcraft III installation at specified path: " + wc3Path); } + + return w3data; + } else { + return new W3InstallationData(); } } } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/RunMap.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/RunMap.java index 00f96a719..fc4145918 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/RunMap.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/RunMap.java @@ -11,7 +11,6 @@ import de.peeeq.wurstio.languageserver.WFile; import de.peeeq.wurstio.mpq.MpqEditor; import de.peeeq.wurstio.mpq.MpqEditorFactory; -import de.peeeq.wurstio.utils.W3Utils; import de.peeeq.wurstscript.WLogger; import de.peeeq.wurstscript.attributes.CompileError; import de.peeeq.wurstscript.gui.WurstGui; @@ -20,7 +19,6 @@ import net.moonlightflower.wc3libs.port.Orient; import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.math.RandomUtils; import org.eclipse.lsp4j.MessageType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,8 +32,8 @@ import java.nio.file.Paths; import java.time.Duration; import java.util.List; +import java.util.Optional; import java.util.Arrays; -import java.util.stream.Stream; import static de.peeeq.wurstio.languageserver.ProjectConfigBuilder.FILE_NAME; import static net.moonlightflower.wc3libs.port.GameVersion.*; @@ -45,10 +43,11 @@ */ public class RunMap extends MapRequest { - private File customTarget = null; + private @Nullable File customTarget = null; - public RunMap(ConfigProvider configProvider, WFile workspaceRoot, @Nullable String wc3Path, @Nullable File map, List compileArgs) { + public RunMap(ConfigProvider configProvider, WFile workspaceRoot, Optional wc3Path, Optional map, + List compileArgs) { super(configProvider, map, compileArgs, workspaceRoot, wc3Path); } @@ -75,15 +74,15 @@ public Object execute(ModelManager modelManager) throws IOException { WLogger.info("received runMap command: map=" + map + ", wc3dir=" + wc3Path + ", args=" + compileArgs); WurstGui gui = new WurstGuiImpl(getWorkspaceAbsolute()); try { - if (map != null && !map.exists()) { - throw new RequestFailedException(MessageType.Error, map.getAbsolutePath() + " does not exist."); + if (map.isPresent() && !map.get().exists()) { + throw new RequestFailedException(MessageType.Error, map.get().getAbsolutePath() + " does not exist."); } gui.sendProgress("Copying map"); // first we copy in same location to ensure validity File buildDir = getBuildDir(); - File testMap = map == null ? null : new File(buildDir, "WurstRunMap.w3x"); + Optional testMap = map.map($ -> new File(buildDir, "WurstRunMap.w3x")); File compiledScript = compileScript(modelManager, gui, testMap); if (runArgs.isHotReload()) { @@ -97,7 +96,7 @@ public Object execute(ModelManager modelManager) throws IOException { } - if (testMap != null) { + if (testMap.isPresent()) { // then inject the script into the map gui.sendProgress("Injecting mapscript"); try (MpqEditor mpqEditor = MpqEditorFactory.getEditor(testMap)) { @@ -114,14 +113,14 @@ public Object execute(ModelManager modelManager) throws IOException { } gui.sendProgress("Applying Map Config..."); - ProjectConfigBuilder.apply(projectConfig, testMap, compiledScript, buildDir, runArgs); + ProjectConfigBuilder.apply(projectConfig, testMap.get(), compiledScript, buildDir, runArgs, w3data); - File mapCopy = copyToWarcraftMapDir(testMap); + File mapCopy = copyToWarcraftMapDir(testMap.get()); WLogger.info("Starting wc3 ... "); String path = ""; if (customTarget != null) { - path = new File(customTarget, testMap.getName()).getAbsolutePath(); + path = new File(customTarget, testMap.get().getName()).getAbsolutePath(); } else if (mapCopy != null) { path = mapCopy.getAbsolutePath(); } @@ -129,24 +128,24 @@ public Object execute(ModelManager modelManager) throws IOException { if (path.length() > 0) { // now start the map - File gameExe = findGameExecutable(); - if (W3Utils.getWc3PatchVersion() == null) { + File gameExe = w3data.getGameExe().get(); + if (!w3data.getWc3PatchVersion().isPresent()) { throw new RequestFailedException(MessageType.Error, wc3Path + " does not exist."); } List cmd = Lists.newArrayList(gameExe.getAbsolutePath()); - String wc3RunArgs = configProvider.getWc3RunArgs(); - if (StringUtils.isBlank(wc3RunArgs)) { - if (W3Utils.getWc3PatchVersion().compareTo(VERSION_1_32) >= 0) { + Optional wc3RunArgs = configProvider.getWc3RunArgs(); + if (!wc3RunArgs.isPresent() || StringUtils.isBlank(wc3RunArgs.get())) { + if (w3data.getWc3PatchVersion().get().compareTo(VERSION_1_32) >= 0) { cmd.add("-launch"); } - if (W3Utils.getWc3PatchVersion().compareTo(VERSION_1_31) < 0) { + if (w3data.getWc3PatchVersion().get().compareTo(VERSION_1_31) < 0) { cmd.add("-window"); } else { cmd.add("-windowmode"); cmd.add("windowed"); } } else { - cmd.addAll(Arrays.asList(wc3RunArgs.split("\\s+"))); + cmd.addAll(Arrays.asList(wc3RunArgs.get().split("\\s+"))); } cmd.add("-loadfile"); cmd.add(path); @@ -192,7 +191,7 @@ private void callJhcrUpdate(File mapScript) throws IOException, InterruptedExcep ProcessBuilder pb = new ProcessBuilder(configProvider.getJhcrExe(), "update", mapScript.getName(), "--asm", "--preload-path", customMapDataPath.toAbsolutePath().toString()); pb.directory(mapScriptFolder); - Utils.ExecResult result = Utils.exec(pb, Duration.ofSeconds(30), System.err::println); + Utils.ExecResult $ = Utils.exec(pb, Duration.ofSeconds(30), System.err::println); } /** @@ -226,22 +225,6 @@ private String getWorkspaceAbsolute() { } } - /** - * Returns the executable for Warcraft III for starting maps - * since it changed with 1.28.3 - */ - private File findGameExecutable() { - if (W3Utils.getWc3PatchVersion().compareTo(VERSION_1_29) < 0) { - return (Stream.of("war3.exe", "War3.exe", "WAR3.EXE", "Warcraft III.exe", "Frozen Throne.exe")) - .map(exe -> new File(wc3Path, exe)) - .filter(File::exists) - .findFirst() - .orElseThrow(() -> new RequestFailedException(MessageType.Error, "No warcraft executatble found in path '" + wc3Path + "'. \n" + - "Please check your configuration.")); - } - return W3Utils.getGameExe(); - } - /** * Copies the map to the wc3 map directory *

@@ -265,12 +248,12 @@ private File copyToWarcraftMapDir(File testMap) throws IOException { } File myDocumentsFolder = FileSystemView.getFileSystemView().getDefaultDirectory(); - String documentPath = findMapDocumentPath(testMapName, myDocumentsFolder); + Optional documentPath = findMapDocumentPath(testMapName, myDocumentsFolder); // copy the map to the appropriate directory - File testFolder = new File(documentPath, "Maps" + File.separator + "Test"); - if (testFolder.mkdirs() || testFolder.exists()) { - File testMap2 = new File(testFolder, testMapName); + Optional testFolder = documentPath.map(path -> new File(path, "Maps" + File.separator + "Test")); + if (testFolder.isPresent() && (testFolder.get().mkdirs() || testFolder.get().exists())) { + File testMap2 = new File(testFolder.get(), testMapName); while (true) { try { Files.copy(testMap, testMap2); @@ -285,7 +268,7 @@ private File copyToWarcraftMapDir(File testMap) throws IOException { if (result == JOptionPane.CANCEL_OPTION) { return null; } else if(result == JOptionPane.NO_OPTION) { - testMap2 = new File(testFolder, testMapName + RandomStringUtils.randomNumeric(3)); + testMap2 = new File(testFolder.get(), testMapName + RandomStringUtils.randomNumeric(3)); } } @@ -298,32 +281,32 @@ private File copyToWarcraftMapDir(File testMap) throws IOException { return null; } - private String findMapDocumentPath(String testMapName, File myDocumentsFolder) { - String documentPath = configProvider.getMapDocumentPath(); - if (documentPath == null) { - documentPath = myDocumentsFolder.getAbsolutePath() + File.separator + "Warcraft III"; - if (!new File(documentPath).exists()) { - WLogger.info("Warcraft folder " + documentPath + " does not exist."); - // Try wine default: - documentPath = System.getProperty("user.home") - + "/.wine/drive_c/users/" + System.getProperty("user.name") + "/My Documents/Warcraft III"; - if (!new File(documentPath).exists()) { - WLogger.severe("Severe: Wine Warcraft folder " + documentPath + " does not exist."); - } + private Optional findMapDocumentPath(String testMapName, File myDocumentsFolder) { + Optional documentPath = Optional.of( + configProvider.getMapDocumentPath().orElseGet( + () -> myDocumentsFolder.getAbsolutePath() + File.separator + "Warcraft III")); + + if (!new File(documentPath.get()).exists()) { + WLogger.info("Warcraft folder " + documentPath + " does not exist."); + // Try wine default: + documentPath = Optional.of(System.getProperty("user.home") + + "/.wine/drive_c/users/" + System.getProperty("user.name") + "/My Documents/Warcraft III"); + if (!new File(documentPath.get()).exists()) { + WLogger.severe("Severe: Wine Warcraft folder " + documentPath + " does not exist."); } + } - - if (W3Utils.getWc3PatchVersion().compareTo(new GameVersion("1.27.9")) <= 0) { - // 1.27 and lower compat - WLogger.info("Version 1.27 or lower detected, changing file location"); - documentPath = wc3Path; - } else { - // For 1.28+ the wc3/maps/test folder must not contain a map of the same name - File oldFile = new File(wc3Path, "Maps" + File.separator + "Test" + File.separator + testMapName); - if (oldFile.exists()) { - if (!oldFile.delete()) { - WLogger.severe("Cannot delete old Wurst Test Map"); - } + if (w3data.getWc3PatchVersion().get().compareTo(new GameVersion("1.27.9")) <= 0) { + // 1.27 and lower compat + WLogger.info("Version 1.27 or lower detected, changing file location"); + documentPath = wc3Path; + } else { + // For 1.28+ the wc3/maps/test folder must not contain a map of the same name + Optional oldFile = wc3Path.map( + w3p -> new File(w3p, "Maps" + File.separator + "Test" + File.separator + testMapName)); + if (oldFile.isPresent() && oldFile.get().exists()) { + if (!oldFile.get().delete()) { + WLogger.severe("Cannot delete old Wurst Test Map"); } } } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/RunTests.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/RunTests.java index 1e6a3e0b0..6b0c361a8 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/RunTests.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/RunTests.java @@ -37,10 +37,10 @@ */ public class RunTests extends UserRequest { - private final WFile filename; + private final Optional filename; private final int line; private final int column; - private final String testName; + private final Optional testName; private List successTests = Lists.newArrayList(); private List failTests = Lists.newArrayList(); @@ -83,8 +83,8 @@ public String getMessageWithStackFrame() { } - public RunTests(String filename, int line, int column, String testName) { - this.filename = filename == null ? null : WFile.create(filename); + public RunTests(Optional filename, int line, int column, Optional testName) { + this.filename = filename.map(fname -> WFile.create(fname)); this.line = line; this.column = column; this.testName = testName; @@ -100,9 +100,9 @@ public Object execute(ModelManager modelManager) { WLogger.info("Starting tests " + filename + ", " + line + ", " + column); println("Running unit tests..\n"); - CompilationUnit cu = filename == null ? null : modelManager.getCompilationUnit(filename); + Optional cu = filename.map(fname -> modelManager.getCompilationUnit(fname)); WLogger.info("test.cu = " + Utils.printElement(cu)); - FuncDef funcToTest = getFunctionToTest(cu); + Optional funcToTest = getFunctionToTest(cu); WLogger.info("test.funcToTest = " + Utils.printElement(funcToTest)); @@ -137,17 +137,18 @@ public int getTotalTests() { } - public TestResult runTests(ImTranslator translator, ImProg imProg, @Nullable FuncDef funcToTest, @Nullable CompilationUnit cu) { + public TestResult runTests(ImTranslator translator, ImProg imProg, Optional funcToTest, Optional cu) { WurstGui gui = new TestGui(); - CompiletimeFunctionRunner cfr = new CompiletimeFunctionRunner(translator, imProg, null, null, gui, CompiletimeFunctions); + CompiletimeFunctionRunner cfr = new CompiletimeFunctionRunner(translator, imProg, Optional.empty(), null, gui, + CompiletimeFunctions); ILInterpreter interpreter = cfr.getInterpreter(); ProgramState globalState = cfr.getGlobalState(); if (globalState == null) { globalState = new ProgramState(gui, imProg, true); } if (interpreter == null) { - interpreter = new ILInterpreter(imProg, gui, null, globalState); + interpreter = new ILInterpreter(imProg, gui, Optional.empty(), globalState); interpreter.addNativeProvider(new ReflectionNativeProvider(interpreter)); } @@ -171,10 +172,10 @@ public TestResult runTests(ImTranslator translator, ImProg imProg, @Nullable Fun if (f.hasFlag(FunctionFlagEnum.IS_TEST)) { Element trace = f.attrTrace(); - if (cu != null && !Utils.elementContained(trace, cu)) { + if (cu.isPresent() && !Utils.elementContained(Optional.of(trace), cu.get())) { continue; } - if (funcToTest != null && trace != funcToTest) { + if (funcToTest.isPresent() && trace != funcToTest.get()) { continue; } @@ -309,12 +310,13 @@ private ImTranslator translateProg(ModelManager modelManager) { } - private FuncDef getFunctionToTest(CompilationUnit cu) { - if (testName != null) { - int dotPos = testName.indexOf("."); - String packageName = testName.substring(0, dotPos); - String funcName = testName.substring(dotPos+1); - Optional testFunc = cu.getPackages() + private Optional getFunctionToTest(Optional maybeCu) { + if (testName.isPresent()) { + int dotPos = testName.get().indexOf("."); + String packageName = testName.get().substring(0, dotPos); + String funcName = testName.get().substring(dotPos+1); + Optional testFunc = maybeCu.flatMap(cu -> + cu.getPackages() .stream() .filter(p -> p.getName().equals(packageName)) .flatMap(p -> p.getElements().stream()) @@ -322,21 +324,22 @@ private FuncDef getFunctionToTest(CompilationUnit cu) { .map(e -> (FuncDef) e) .filter(f -> f.hasAnnotation("@test")) .filter(f -> f.getName().equals(funcName)) - .findFirst(); + .findFirst() + ); if (testFunc.isPresent()) { - return testFunc.get(); + return testFunc; } } - if (filename == null || cu == null || line < 0) { - return null; + if (!filename.isPresent() || !maybeCu.isPresent() || line < 0) { + return Optional.empty(); } - Element e = Utils.getAstElementAtPos(cu, line, column, false); - while (e != null) { - if (e instanceof FuncDef) { - return (FuncDef) e; + Optional e = Utils.getAstElementAtPos(maybeCu.get(), line, column, false); + while (e.isPresent()) { + if (e.get() instanceof FuncDef) { + return e.map(el -> (FuncDef) el); } - e = e.getParent(); + e = e.flatMap(el -> Optional.ofNullable(el.getParent())); } return null; } @@ -366,7 +369,7 @@ public void showInfoMessage(String message) { } private class TestTimeOutException extends Throwable { - + private static final long serialVersionUID = -7080085729129882874L; @Override public String getMessage() { @@ -377,7 +380,6 @@ public String getMessage() { public String toString() { return super.toString(); } - } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/SignatureInfo.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/SignatureInfo.java index ee2179d13..110812ebb 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/SignatureInfo.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/languageserver/requests/SignatureInfo.java @@ -13,6 +13,7 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.Optional; public class SignatureInfo extends UserRequest { @@ -31,27 +32,27 @@ public SignatureInfo(TextDocumentPositionParams position) { @Override public SignatureHelp execute(ModelManager modelManager) { CompilationUnit cu = modelManager.getCompilationUnit(filename); - Element e = Utils.getAstElementAtPos(cu, line, column, false); - if (e instanceof StmtCall) { - StmtCall call = (StmtCall) e; + Optional e = Utils.getAstElementAtPos(cu, line, column, false); + if (e.get() instanceof StmtCall) { + StmtCall call = (StmtCall) e.get(); // TODO only when we are in parentheses return forCall(call); } - while (e != null) { - Element parent = e.getParent(); - if (parent instanceof Arguments) { - Arguments args = (Arguments) parent; - if (parent.getParent() instanceof StmtCall) { - StmtCall call = (StmtCall) parent.getParent(); + while (e.isPresent()) { + Optional parent = e.flatMap(el -> Optional.ofNullable(el.getParent())); + if (parent.isPresent() && parent.get() instanceof Arguments) { + Arguments args = (Arguments) parent.get(); + if (parent.get().getParent() instanceof StmtCall) { + StmtCall call = (StmtCall) parent.get().getParent(); SignatureHelp info = forCall(call); info.setActiveParameter(args.indexOf(e)); return info; } break; - } else if (parent instanceof StmtCall) { - StmtCall call = (StmtCall) parent; + } else if (parent.isPresent() && parent.get() instanceof StmtCall) { + StmtCall call = (StmtCall) parent.get(); return forCall(call); } e = parent; diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/map/importer/ImportFile.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/map/importer/ImportFile.java index c42af20c8..82eeb796e 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/map/importer/ImportFile.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/map/importer/ImportFile.java @@ -14,6 +14,7 @@ import java.nio.ByteOrder; import java.nio.file.Path; import java.util.LinkedList; +import java.util.Optional; public class ImportFile { private static final String DEFAULT_IMPORT_PATH = "war3mapImported\\"; @@ -42,7 +43,7 @@ public static void extractImportsFromMap(File mapFile, RunArgs runArgs) { } private static void extractImportsFrom(File importDirectory, File tempMap, RunArgs runArgs) throws Exception { - try (MpqEditor editor = MpqEditorFactory.getEditor(tempMap)) { + try (MpqEditor editor = MpqEditorFactory.getEditor(Optional.of(tempMap))) { LinkedList failed = extractImportedFiles(editor, importDirectory); if (failed.isEmpty()) { diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/mpq/MpqEditorFactory.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/mpq/MpqEditorFactory.java index a56f173b0..f4ee0417a 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/mpq/MpqEditorFactory.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/mpq/MpqEditorFactory.java @@ -1,14 +1,17 @@ package de.peeeq.wurstio.mpq; import java.io.File; +import java.util.Optional; + +import javax.annotation.Nullable; public class MpqEditorFactory { - static public MpqEditor getEditor(File f) throws Exception { - if (f == null) { + static public @Nullable MpqEditor getEditor(Optional f) throws Exception { + if (!f.isPresent()) { return null; } - return new Jmpq3BasedEditor(f); + return new Jmpq3BasedEditor(f.get()); } } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/utils/W3InstallationData.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/utils/W3InstallationData.java new file mode 100644 index 000000000..35b59cc53 --- /dev/null +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/utils/W3InstallationData.java @@ -0,0 +1,95 @@ +package de.peeeq.wurstio.utils; + +import de.peeeq.wurstscript.WLogger; +import net.moonlightflower.wc3libs.bin.GameExe; +import net.moonlightflower.wc3libs.port.GameVersion; +import net.moonlightflower.wc3libs.port.NotFoundException; +import net.moonlightflower.wc3libs.port.Orient; +import net.moonlightflower.wc3libs.port.StdGameExeFinder; +import net.moonlightflower.wc3libs.port.StdGameVersionFinder; +import net.moonlightflower.wc3libs.port.win.WinGameExeFinder; + +import java.io.File; +import java.io.IOException; +import java.util.Optional; + +public class W3InstallationData { + private Optional gameExe = Optional.empty(); + + private Optional version = Optional.empty(); + + /** Evaluates the game path and version by discovering the system environment. */ + public W3InstallationData() { + discoverExePath(); + discoverVersion(); + } + + /** + * Evaluates the game path and version, attempting to use the provided path if possible, before discovering the + * system environment. + */ + public W3InstallationData(File wc3Path) { + if (!Orient.isWindowsSystem()) { + WLogger.warning("Game path configuration only works on windows"); + discoverExePath(); + discoverVersion(); + return; + } + + try { + gameExe = Optional.ofNullable(WinGameExeFinder.fromDirIgnoreVersion(wc3Path)); + } catch (NotFoundException e) { + WLogger.severe(e); + } + WLogger.info("Game Executable from path: " + gameExe); + + version = gameExe.flatMap(exe -> { + try { + return Optional.ofNullable(GameExe.getVersion(exe)); + } catch (IOException e) { + WLogger.severe(e); + } + + return Optional.empty(); + }); + WLogger.info("Parsed custom game version from executable: " + version); + + if (!gameExe.isPresent()) { + WLogger.warning("The provided wc3 path wasn't suitable. Falling back to discovery."); + discoverExePath(); + discoverVersion(); + } + } + + private void discoverExePath() { + try { + gameExe = Optional.ofNullable(new StdGameExeFinder().get()); + WLogger.info("Parsed game path: " + gameExe); + } catch (NotFoundException e) { + e.printStackTrace(); + } + } + + private void discoverVersion() { + try { + version = Optional.ofNullable(new StdGameVersionFinder().get()); + WLogger.info("Parsed game version: " + version); + } catch (NotFoundException e) { + e.printStackTrace(); + } + } + + /** + * @return The wc3 patch version or empty if none has been found + */ + public Optional getWc3PatchVersion() { + return version; + } + + /** + * @return The wc3 path or empty if none has been found + */ + public Optional getGameExe() { + return gameExe; + } +} diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/utils/W3Utils.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/utils/W3Utils.java deleted file mode 100644 index 38a3b2303..000000000 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/utils/W3Utils.java +++ /dev/null @@ -1,82 +0,0 @@ -package de.peeeq.wurstio.utils; - -import de.peeeq.wurstscript.WLogger; -import net.moonlightflower.wc3libs.bin.GameExe; -import net.moonlightflower.wc3libs.port.GameVersion; -import net.moonlightflower.wc3libs.port.NotFoundException; -import net.moonlightflower.wc3libs.port.Orient; -import net.moonlightflower.wc3libs.port.StdGameExeFinder; -import net.moonlightflower.wc3libs.port.mac.MacGameVersionFinder; -import net.moonlightflower.wc3libs.port.win.WinGameExeFinder; - -import java.io.File; -import java.io.IOException; - -public class W3Utils { - private static File gameExe; - - private static GameVersion version = null; - - /** - * @return The wc3 patch version or -1 if none has been found - */ - public static GameVersion getWc3PatchVersion() { - if (gameExe == null && Orient.isWindowsSystem()) { - try { - gameExe = new StdGameExeFinder().get(); - } catch (NotFoundException e) { - e.printStackTrace(); - } - } - if (version == null && gameExe != null) { - try { - version = GameExe.getVersion(gameExe); - WLogger.info("Parsed game version: " + version); - } catch (IOException e) { - e.printStackTrace(); - } - } - return version; - } - - /** - * Pass a custom directory here to attempt parsing patch level from. - * - * @return The wc3 patch version or -1 if none has been found - */ - public static GameVersion parsePatchVersion(File wc3Path) { - try { - if (Orient.isWindowsSystem()) { - gameExe = WinGameExeFinder.fromDirIgnoreVersion(wc3Path); - WLogger.info("Game Executable: " + gameExe); - } else { - WLogger.warning("Game path configuration only works on windows"); - throw new NotFoundException(); - } - } catch (NotFoundException e) { - try { - gameExe = new StdGameExeFinder().get(); - } catch (NotFoundException ex) { - WLogger.severe(e); - } - } - if (gameExe != null) { - try { - if (Orient.isWindowsSystem()) { - W3Utils.version = GameExe.getVersion(gameExe); - } else if (Orient.isMacSystem()) { - W3Utils.version = new MacGameVersionFinder().get(); - } - WLogger.info("Parsed custom game version: " + version); - } catch (IOException | NotFoundException e) { - WLogger.severe(e); - } - } - return version; - } - - - public static File getGameExe() { - return gameExe; - } -} diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrExprExpectedType.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrExprExpectedType.java index 3c67ee0f2..822301048 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrExprExpectedType.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrExprExpectedType.java @@ -7,6 +7,7 @@ import org.eclipse.jdt.annotation.NonNull; import java.util.Collection; +import java.util.Optional; /** * This attribute calculates the expected type for an expression @@ -97,8 +98,10 @@ public class AttrExprExpectedType { } } } catch (CyclicDependencyError | CompileError t) { - WLogger.info("Something went wrong while computing the expected type for " + Utils.printElementWithSource(expr) + "\n" + - "This is probably not a bug, but we are logging it anyway since it might help to improve error messages."); + WLogger.info("Something went wrong while computing the expected type for " + + Utils.printElementWithSource(Optional.of(expr)) + + "\nThis is probably not a bug, but we are logging it anyway since it might help to improve error " + + "messages."); WLogger.info(t); } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrExprType.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrExprType.java index 38ccbc35f..5a06551f0 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrExprType.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrExprType.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; /** @@ -68,7 +69,7 @@ public static WurstType calculate(ExprVarAccess term) { return WurstTypeUnknown.instance(); } if (varDef.getDef() instanceof VarDef) { - if (Utils.getParentVarDef(term) == varDef.getDef()) { + if (Utils.getParentVarDef(Optional.of(term)) == Optional.of((VarDef) varDef.getDef())) { term.addError("Recursive variable definition is not allowed."); return WurstTypeUnknown.instance(); } @@ -217,7 +218,7 @@ public static WurstType calculate(final ExprBinary term) { return WurstTypeBool.instance(); } - if (Utils.isJassCode(term)) { + if (Utils.isJassCode(Optional.of(term))) { if (leftType.isSubtypeOf(WurstTypeReal.instance(), term) || leftType.isSubtypeOf(WurstTypeInt.instance(), term)) { if (rightType.isSubtypeOf(WurstTypeReal.instance(), term) || rightType.isSubtypeOf(WurstTypeInt.instance(), term)) { // in jass code it is allowed to compare reals and ints @@ -278,7 +279,7 @@ public static WurstType calculate(final ExprBinary term) { return handleOperatorOverloading(term); } case DIV_REAL: - if (Utils.isJassCode(term)) { + if (Utils.isJassCode(Optional.of(term))) { return caseMathOperation(term); } else if (bothTypesRealOrInt(term)) { return WurstTypeReal.instance(); diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrTypeDef.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrTypeDef.java index 8fc5a3519..5ad5efe09 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrTypeDef.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrTypeDef.java @@ -3,6 +3,9 @@ import de.peeeq.wurstscript.ast.*; import de.peeeq.wurstscript.types.*; import de.peeeq.wurstscript.utils.Utils; + +import java.util.Optional; + import org.eclipse.jdt.annotation.Nullable; @@ -34,7 +37,7 @@ public class AttrTypeDef { return r; } - WurstType nativeType = NativeTypes.nativeType(typeName, Utils.isJassCode(node)); + WurstType nativeType = NativeTypes.nativeType(typeName, Utils.isJassCode(Optional.of(node))); if (nativeType != null) { return null; // native types have no definitionPos } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrTypeExprType.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrTypeExprType.java index 5e331a4dd..017d21fd9 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrTypeExprType.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrTypeExprType.java @@ -1,9 +1,8 @@ package de.peeeq.wurstscript.attributes; +import java.util.Optional; + import de.peeeq.wurstscript.ast.*; -import de.peeeq.wurstscript.attributes.AttrConstantValue.ConstantValueCalculationException; -import de.peeeq.wurstscript.intermediatelang.ILconst; -import de.peeeq.wurstscript.intermediatelang.ILconstInt; import de.peeeq.wurstscript.types.*; import de.peeeq.wurstscript.utils.Utils; @@ -75,7 +74,7 @@ public static WurstType calculate(TypeExprArray typeExprArray) { private static WurstType getBaseType(TypeExprSimple node) { final String typename = node.getTypeName(); - final boolean isJassCode = Utils.isJassCode(node); + final boolean isJassCode = Utils.isJassCode(Optional.of(node)); TypeDef t = node.attrTypeDef(); if (t == null) { WurstType nativeType = NativeTypes.nativeType(typename, isJassCode); diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/OverloadingResolver.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/OverloadingResolver.java index bb27d90fc..b49d97b76 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/OverloadingResolver.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/OverloadingResolver.java @@ -87,7 +87,7 @@ && getParameterType(f, i) instanceof WurstTypeTypeParam) { return "function " + func.getName() + " defined in " + " line " + func.getSource().getLine(); } - return Utils.printElementWithSource(f); + return Utils.printElementWithSource(Optional.of(f)); }).collect(Collectors.joining("\n * ")); handleError(Utils.list("call is ambiguous, there are several alternatives: \n * " + alts)); diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/SmallHelpers.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/SmallHelpers.java index 14156e0cd..1a5a76aed 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/SmallHelpers.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/SmallHelpers.java @@ -26,7 +26,7 @@ public static boolean hasEmptyBody(FunctionLike f) { } public static boolean isModuleUseTypeArg(TypeExpr e) { - Optional mUse = Utils.getNearestByType(e, ModuleUse.class); + Optional mUse = Utils.getNearestByType(Optional.of(e), ModuleUse.class); return mUse.map(moduleUse -> moduleUse.isSubtreeOf(e)).orElse(false); } @@ -39,7 +39,7 @@ public static boolean isSubtreeOf(@Nullable Element subtree, Element of) { } public static boolean isStructureDefTypeParam(TypeParamDef tp) { - Optional sDef = Utils.getNearestByType(tp, StructureDef.class); + Optional sDef = Utils.getNearestByType(Optional.of(tp), StructureDef.class); if (!sDef.isPresent()) { return false; } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/NameLink.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/NameLink.java index 61946031c..04bb5a954 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/NameLink.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/NameLink.java @@ -3,8 +3,6 @@ import de.peeeq.wurstscript.ast.*; import de.peeeq.wurstscript.types.VariableBinding; import de.peeeq.wurstscript.types.WurstType; -import de.peeeq.wurstscript.types.WurstTypeBoundTypeParam; -import io.vavr.collection.TreeMap; import java.util.List; import java.util.stream.Stream; @@ -21,25 +19,6 @@ public NameLink(Visibility visibility, WScope definedIn, List type this.typeParams = typeParams; } - - // @Deprecated -// public static NameLink create(NameDef nameDef, WScope definedIn) { -// Visibility visibiliy = calcVisibility(definedIn, nameDef); -// NameLinkType type = calcNameLinkType(nameDef); -// List typeParams = Streams.concat(typeParams(definedIn), typeParams(nameDef)).collect(Collectors.toList()); -// WurstType lreturnType = null; -// List lparameterTypes = null; -// if (nameDef instanceof FunctionDefinition) { -// FunctionDefinition func = (FunctionDefinition) nameDef; -// lparameterTypes = func.getParameters().stream() -// .map(WParameter::attrTyp) -// .collect(Collectors.toList()); -// lreturnType = func.attrTyp(); -// } -// WurstType lreceiverType = calcReceiverType(definedIn, nameDef, type); -// return new NameLink(visibiliy, type, definedIn, nameDef, typeParams, lreceiverType, lparameterTypes, lreturnType); -// } - protected static Stream typeParams(Element scope) { if (scope instanceof AstElementWithTypeParameters) { return ((AstElementWithTypeParameters) scope).getTypeParameters().stream(); diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/NameLinks.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/NameLinks.java index bd054032b..3e24d3a08 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/NameLinks.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/NameLinks.java @@ -207,7 +207,7 @@ public static ImmutableMultimap calculate(WPackage p) { } WPackage importedPackage = imp.attrImportedPackage(); if (importedPackage == null) { - WLogger.info("could not resolve import: " + Utils.printElementWithSource(imp)); + WLogger.info("could not resolve import: " + Utils.printElementWithSource(Optional.of(imp))); continue; } if (p.getName().equals("WurstREPL")) { diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/NameResolution.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/NameResolution.java index 8cc829524..d0d3429b9 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/NameResolution.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/NameResolution.java @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; public class NameResolution { @@ -117,7 +118,7 @@ public static NameLink lookupVarNoConfig(Element node, String name, boolean show if (scope instanceof LoopStatementWithVarDef) { LoopStatementWithVarDef loop = (LoopStatementWithVarDef) scope; // only consider this scope if node is in the body: - if (!Utils.elementContained(node, loop.getBody())) { + if (!Utils.elementContained(Optional.of(node), loop.getBody())) { continue; } } @@ -161,8 +162,8 @@ public static NameLink lookupVarNoConfig(Element node, String name, boolean show if (privateCandidate == null) { node.addError("Could not find variable " + name + "."); } else { - node.addError(Utils.printElementWithSource(privateCandidate.getDef()) + " is not visible inside this package." + - " If you want to access it, declare it public."); + node.addError(Utils.printElementWithSource(Optional.of(privateCandidate.getDef())) + + " is not visible inside this package. If you want to access it, declare it public."); return privateCandidate; } } @@ -260,8 +261,8 @@ public static DefLink matchDefLinkReceiver(DefLink n, WurstType receiverType, El if (privateCandidate == null) { node.addError("Could not find type " + name + "."); } else { - node.addError(Utils.printElementWithSource(privateCandidate.getDef()) + " is not visible inside this package." + - " If you want to access it, declare it public."); + node.addError(Utils.printElementWithSource(Optional.of(privateCandidate.getDef())) + + " is not visible inside this package. If you want to access it, declare it public."); return (TypeDef) privateCandidate.getDef(); } } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/VarLink.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/VarLink.java index aaf01b603..b4bed470f 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/VarLink.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/names/VarLink.java @@ -7,10 +7,8 @@ import de.peeeq.wurstscript.ast.*; import de.peeeq.wurstscript.types.VariableBinding; import de.peeeq.wurstscript.types.WurstType; -import de.peeeq.wurstscript.types.WurstTypeBoundTypeParam; import de.peeeq.wurstscript.types.WurstTypeVararg; import de.peeeq.wurstscript.utils.Utils; -import io.vavr.collection.TreeMap; import org.eclipse.jdt.annotation.Nullable; import java.util.List; @@ -136,7 +134,7 @@ public String toString() { if (getReceiverType() != null) { r += getReceiverType() + "."; } - return r + Utils.printElementWithSource(def); + return r + Utils.printElementWithSource(Optional.of(def)); } public VarLink withTypeArgBinding(Element context, VariableBinding binding) { diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/intermediatelang/interpreter/ILInterpreter.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/intermediatelang/interpreter/ILInterpreter.java index 314fe1dd0..86f191426 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/intermediatelang/interpreter/ILInterpreter.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/intermediatelang/interpreter/ILInterpreter.java @@ -19,6 +19,7 @@ import java.io.File; import java.util.Arrays; +import java.util.Optional; import java.util.stream.Collectors; public class ILInterpreter implements AbstractInterpreter { @@ -26,14 +27,14 @@ public class ILInterpreter implements AbstractInterpreter { private final ProgramState globalState; private final TimerMockHandler timerMockHandler = new TimerMockHandler(); - public ILInterpreter(ImProg prog, WurstGui gui, @Nullable File mapFile, ProgramState globalState) { + public ILInterpreter(ImProg prog, WurstGui gui, Optional mapFile, ProgramState globalState) { this.prog = prog; this.globalState = globalState; globalState.addNativeProvider(new BuiltinFuncs(globalState)); globalState.addNativeProvider(new NativeFunctions()); } - public ILInterpreter(ImProg prog, WurstGui gui, @Nullable File mapFile, boolean isCompiletime) { + public ILInterpreter(ImProg prog, WurstGui gui, Optional mapFile, boolean isCompiletime) { this(prog, gui, mapFile, new ProgramState(gui, prog, isCompiletime)); } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imoptimizer/GlobalsInliner.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imoptimizer/GlobalsInliner.java index dbf5e6613..b92ffe9a6 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imoptimizer/GlobalsInliner.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imoptimizer/GlobalsInliner.java @@ -9,6 +9,7 @@ import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -71,7 +72,9 @@ public int optimize(ImTranslator trans) { v.attrWrites().iterator().next().replaceBy(ImHelper.nullExpr()); } } catch (Exception e) { - throw new CompileError(write.attrTrace().attrErrorPos(), "Could not inline " + Utils.printElementWithSource(v.getTrace()), CompileError.ErrorType.ERROR, e); + throw new CompileError(write.attrTrace().attrErrorPos(), + "Could not inline " + Utils.printElementWithSource(Optional.of(v.getTrace())), + CompileError.ErrorType.ERROR, e); } } } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/ExprTranslation.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/ExprTranslation.java index 34bce881f..378b5ead8 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/ExprTranslation.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/ExprTranslation.java @@ -22,6 +22,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import static de.peeeq.wurstscript.jassIm.JassIm.*; @@ -149,7 +150,7 @@ public static ImExpr translateIntern(ExprBinary e, ImTranslator t, ImFunction f) return ImFunctionCall(e, calledFunc, ImTypeArguments(), ImExprs(left, right), false, CallType.NORMAL); } if (op == WurstOperator.DIV_REAL) { - if (Utils.isJassCode(e)) { + if (Utils.isJassCode(Optional.of(e))) { if (e.getLeft().attrTyp().isSubtypeOf(WurstTypeInt.instance(), e) && e.getRight().attrTyp().isSubtypeOf(WurstTypeInt.instance(), e)) { // in jass when we have int1 / int2 this actually means int1 diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/ImTranslator.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/ImTranslator.java index df109e455..46707768d 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/ImTranslator.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/ImTranslator.java @@ -145,9 +145,11 @@ public ImProg translateProg() { throw t; } catch (Throwable t) { WLogger.severe(t); - throw new RuntimeException("There was a Wurst bug in the translation of " + Utils.printElementWithSource(lasttranslatedThing) + ": " + t - .getMessage() + - "\nPlease open a ticket with source code and the error log.", t); + throw new RuntimeException("There was a Wurst bug in the translation of " + + Utils.printElementWithSource(Optional.of(lasttranslatedThing)) + + ": " + + t.getMessage() + + "\nPlease open a ticket with source code and the error log.", t); } } @@ -1077,7 +1079,10 @@ public Map getClassesWithImplementation(Collection } } if (funcNameLink == null) { - throw new Error("Could not find " + Utils.printElementWithSource(func) + " in " + Utils.printElementWithSource(c)); + throw new Error("Could not find " + + Utils.printElementWithSource(Optional.of(func)) + + " in " + + Utils.printElementWithSource(Optional.of(c))); } for (NameLink nameLink : c.attrNameLinks().get(func.getName())) { NameDef nameDef = nameLink.getDef(); diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/types/WurstTypeInt.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/types/WurstTypeInt.java index 1d06da1c5..3e4d7ad34 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/types/WurstTypeInt.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/types/WurstTypeInt.java @@ -5,6 +5,9 @@ import de.peeeq.wurstscript.jassIm.JassIm; import de.peeeq.wurstscript.translation.imtranslation.ImTranslator; import de.peeeq.wurstscript.utils.Utils; + +import java.util.Optional; + import org.eclipse.jdt.annotation.Nullable; @@ -18,10 +21,11 @@ protected WurstTypeInt() { } @Override - VariableBinding matchAgainstSupertypeIntern(WurstType other, @Nullable Element location, VariableBinding mapping, VariablePosition variablePosition) { + VariableBinding matchAgainstSupertypeIntern(WurstType other, @Nullable Element location, VariableBinding mapping, + VariablePosition variablePosition) { return (other instanceof WurstTypeInt // in jass code we can use an int where a real is expected - || other instanceof WurstTypeReal && Utils.isJassCode(location)) ? mapping : null; + || other instanceof WurstTypeReal && Utils.isJassCode(Optional.ofNullable(location))) ? mapping : null; } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/types/WurstTypeNull.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/types/WurstTypeNull.java index 01aee03d3..70b783c93 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/types/WurstTypeNull.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/types/WurstTypeNull.java @@ -2,11 +2,13 @@ import de.peeeq.wurstscript.ast.Element; import de.peeeq.wurstscript.jassIm.ImExprOpt; -import de.peeeq.wurstscript.jassIm.ImSimpleType; import de.peeeq.wurstscript.jassIm.ImType; import de.peeeq.wurstscript.jassIm.JassIm; import de.peeeq.wurstscript.translation.imtranslation.ImTranslator; import de.peeeq.wurstscript.utils.Utils; + +import java.util.Optional; + import org.eclipse.jdt.annotation.Nullable; @@ -17,27 +19,16 @@ public class WurstTypeNull extends WurstType { private WurstTypeNull() { } @Override - VariableBinding matchAgainstSupertypeIntern(WurstType other, @Nullable Element location, VariableBinding mapping, VariablePosition variablePosition) { + VariableBinding matchAgainstSupertypeIntern(WurstType other, @Nullable Element location, VariableBinding mapping, + VariablePosition variablePosition) { if (other.isNullable()) { return mapping; } - if (Utils.isJassCode(location) && (other instanceof WurstTypeInt || other instanceof WurstTypeIntLiteral)) { + if (Utils.isJassCode(Optional.of(location)) + && (other instanceof WurstTypeInt || other instanceof WurstTypeIntLiteral)) { return mapping; } -// other instanceof WurstTypeNull -// || other instanceof WurstTypeHandle -// || other instanceof WurstNativeType -// || other instanceof WurstTypeString -// || other instanceof WurstTypeCode -// || other instanceof WurstTypeClass -// || other instanceof WurstTypeInterface -// || other instanceof WurstTypeModule -// || other instanceof WurstTypeModuleInstanciation -// || -// other instanceof WurstTypeTypeParam -// other instanceof WurstTypeBoundTypeParam - return null; } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/types/WurstTypeTuple.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/types/WurstTypeTuple.java index ee4b3cb05..1099f6793 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/types/WurstTypeTuple.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/types/WurstTypeTuple.java @@ -11,6 +11,7 @@ import org.eclipse.jdt.annotation.Nullable; import java.util.List; +import java.util.Optional; public class WurstTypeTuple extends WurstType { @@ -80,7 +81,11 @@ public int getTupleIndex(VarDef varDef) { WParameter v = (WParameter) varDef; int index = tupleDef.getParameters().indexOf(v); if (index < 0) { - throw new CompileError(varDef.getSource(), "Could not determine tuple index of " + Utils.printElementWithSource(varDef) + " in tuple " + this); + throw new CompileError(varDef.getSource(), + "Could not determine tuple index of " + + Utils.printElementWithSource(Optional.of(varDef)) + + " in tuple " + + this); } return index; } diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/utils/Utils.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/utils/Utils.java index 5f302ebef..4ed134a95 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/utils/Utils.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/utils/Utils.java @@ -68,15 +68,6 @@ public static List removedDuplicates(List list) { return result; } - // } - // } - // p = p.postOrder(); - // func.apply(p); - // while (p != null) { - // p = p.postOrderStart(); - // func) { - // public static void visitPostOrder(SortPos p, Function - public static void printSep(StringBuilder sb, String seperator, T[] args) { @@ -143,12 +134,12 @@ public static String printSep(String sep, List args) { /** * is a piece of code jass code? */ - public static boolean isJassCode(@Nullable Element pos) { - while (pos != null) { - if (pos instanceof WPackage) { + public static boolean isJassCode(Optional pos) { + while (pos.isPresent()) { + if (pos.get() instanceof WPackage) { return false; // code is inside package -> wurstscript code } - pos = pos.getParent(); + pos = Optional.ofNullable(pos.get().getParent()); } return true; // no package found -> jass code } @@ -253,71 +244,58 @@ public static T getLast(List ts) { } - private static void topSortHelperIgnoreCycles(List result, - Set visitedItems, - java.util.function.Function> biggerItems, T item) { - if (visitedItems.contains(item)) { - return; - } - visitedItems.add(item); - for (T t : biggerItems.apply(item)) { - if (t == null) - throw new IllegalArgumentException(); - topSortHelperIgnoreCycles(result, visitedItems, biggerItems, t); - } - result.add(item); - } - - - public static String printElement(@Nullable Element e) { - if (e == null) { - return "null"; - } - String type = makeReadableTypeName(e); - String name = ""; - if (e instanceof ExprFunctionCall) { - ExprFunctionCall fc = (ExprFunctionCall) e; - return "function call " + fc.getFuncName() + "()"; - } else if (e instanceof FuncDef) { - FuncDef fd = (FuncDef) e; - return "function " + fd.getName(); - } else if (e instanceof OnDestroyDef) { - return "destroy function for " - + e.attrNearestStructureDef().getName(); - } else if (e instanceof ConstructorDef) { - return "constructor for " + e.attrNearestStructureDef().getName(); - } else if (e instanceof LocalVarDef) { - LocalVarDef l = (LocalVarDef) e; - return "local variable " + l.getName(); - } else if (e instanceof VarDef) { - VarDef l = (VarDef) e; - return "variable " + l.getName(); - } else if (e instanceof AstElementWithNameId) { - name = ((AstElementWithNameId) e).getNameId().getName(); - } else if (e instanceof WImport) { - WImport wImport = (WImport) e; - return "import " + wImport.getPackagename(); - } else if (e instanceof TypeExprSimple) { - TypeExprSimple t = (TypeExprSimple) e; - name = t.getTypeName(); - if (t.getTypeArgs().size() > 0) { - name += "{"; - boolean first = true; - StringBuilder builder = new StringBuilder(); - builder.append(name); - for (TypeExpr ta : t.getTypeArgs()) { - if (!first) { - builder.append(", "); + public static String printElement(Optional el) { + return el.map(e -> { + String type = makeReadableTypeName(e); + String name = ""; + if (e instanceof ExprFunctionCall) { + ExprFunctionCall fc = (ExprFunctionCall) e; + return "function call " + fc.getFuncName() + "()"; + } else if (e instanceof FuncDef) { + FuncDef fd = (FuncDef) e; + return "function " + fd.getName(); + } else if (e instanceof OnDestroyDef) { + return "destroy function for " + + e.attrNearestStructureDef().getName(); + } else if (e instanceof ConstructorDef) { + return "constructor for " + e.attrNearestStructureDef().getName(); + } else if (e instanceof LocalVarDef) { + LocalVarDef l = (LocalVarDef) e; + return "local variable " + l.getName(); + } else if (e instanceof VarDef) { + VarDef l = (VarDef) e; + return "variable " + l.getName(); + } else if (e instanceof AstElementWithNameId) { + name = ((AstElementWithNameId) e).getNameId().getName(); + } else if (e instanceof WImport) { + WImport wImport = (WImport) e; + return "import " + wImport.getPackagename(); + } else if (e instanceof TypeExprSimple) { + TypeExprSimple t = (TypeExprSimple) e; + name = t.getTypeName(); + if (t.getTypeArgs().size() > 0) { + name += "{"; + boolean first = true; + StringBuilder builder = new StringBuilder(); + builder.append(name); + for (TypeExpr ta : t.getTypeArgs()) { + if (!first) { + builder.append(", "); + } + builder.append(printElement(ta)); + first = false; } - builder.append(printElement(ta)); - first = false; + name = builder.toString(); + name += "}"; } - name = builder.toString(); - name += "}"; + type = "type"; } - type = "type"; - } - return type + " " + name; + return type + " " + name; + }).orElse("null"); + } + + public static String printElement(@Nullable Element e) { + return printElement(Optional.ofNullable(e)); } private static String makeReadableTypeName(Element e) { @@ -362,56 +340,51 @@ public static String printExceptionWithStackTrace(Throwable t) { } - public static Element getAstElementAtPos(Element elem, + public static Optional getAstElementAtPos(Element elem, int caretPosition, boolean usesMouse) { List betterResults = Lists.newArrayList(); for (int i = 0; i < elem.size(); i++) { - Element e = elem.get(i); - if (elementContainsPos(e, caretPosition, usesMouse)) { - betterResults.add(getAstElementAtPos(e, caretPosition, usesMouse)); - } + getAstElementAtPos(elem.get(i), caretPosition, usesMouse).map(el -> betterResults.add(el)); } if (betterResults.size() == 0) { if (elem instanceof Identifier) { - return elem.getParent(); + return Optional.ofNullable(elem.getParent()); } - return elem; + return Optional.ofNullable(elem); } else { return bestResult(betterResults); } } - public static Element getAstElementAtPos(Element elem, int line, int column, boolean usesMouse) { -// System.out.println("get element " + Utils.printElement(elem) -// + "(" + elem.attrSource().getLeftPos() + " - " + elem.attrSource().getRightPos() + ")"); + public static Optional getAstElementAtPos(Element elem, int line, int column, boolean usesMouse) { if (elem instanceof ModuleInstanciation) { // do not helicopter into module instantiations - return elem; + return Optional.of(elem); } List betterResults = Lists.newArrayList(); for (int i = 0; i < elem.size(); i++) { Element e = elem.get(i); if (elementContainsPos(e, line, column, usesMouse) || e.attrSource().isArtificial()) { - betterResults.add(getAstElementAtPos(e, line, column, usesMouse)); + getAstElementAtPos(e, line, column, usesMouse).map(el -> betterResults.add(el)); } } - Element bestResult = bestResult(betterResults); - if (bestResult == null) { + Optional bestResult = bestResult(betterResults); + if (!bestResult.isPresent()) { if (elem instanceof Identifier) { - return elem.getParent(); + return Optional.ofNullable(elem.getParent()); } - return elem; + return Optional.of(elem); } else { return bestResult; } } - public static Element getAstElementAtPosIgnoringLists(Element elem, + public static Optional getAstElementAtPosIgnoringLists(Element elem, int caretPosition, boolean usesMouse) { - Element r = getAstElementAtPos(elem, caretPosition, usesMouse); - while (r instanceof List) { - r = r.getParent(); + Optional r = getAstElementAtPos(elem, caretPosition, usesMouse); + while (r.isPresent() && r.get() instanceof List) { + r = r.flatMap(el -> Optional.ofNullable(el.getParent())); } return r; } @@ -419,9 +392,9 @@ public static Element getAstElementAtPosIgnoringLists(Element elem, /** * return the element with the smallest size */ - private static Element bestResult(List betterResults) { + private static Optional bestResult(List betterResults) { int minSize = Integer.MAX_VALUE; - Element min = null; + Optional min = Optional.empty(); for (Element e : betterResults) { WPos source = e.attrSource(); int size = source.isArtificial() ? @@ -429,7 +402,7 @@ private static Element bestResult(List betterResults) { : source.getRightPos() - source.getLeftPos(); if (size < minSize) { minSize = size; - min = e; + min = Optional.of(e); } } return min; @@ -464,15 +437,15 @@ public static String printPos(WPos source) { return source.getFile() + ", line " + source.getLine(); } - public static boolean isEmptyCU(@Nullable CompilationUnit cu) { - return (cu == null) - || (cu.getJassDecls().size() + cu.getPackages().size() == 0); + public static boolean isEmptyCU(Optional cu) { + return !cu.isPresent() + || (cu.get().getJassDecls().size() + cu.get().getPackages().size() == 0); } - public static String printElementWithSource(Element e) { - WPos src = e.attrSource(); - return printElement(e) + " (" + src.getFile() + ":" - + src.getLine() + ")"; + public static String printElementWithSource(Optional e) { + Optional src = e.map(el -> el.attrSource()); + return printElement(e) + " (" + src.map(sf -> sf.getFile()) + ":" + + src.map(sf -> sf.getLine()) + ")"; } public static int[] copyArray(int[] ar) { @@ -488,12 +461,12 @@ public static String toFirstUpper(String s) { return s.substring(0, 1).toUpperCase() + s.substring(1); } - public static @Nullable VarDef getParentVarDef(@Nullable Element node) { - while (node != null) { - if (node instanceof VarDef) { - return (VarDef) node; + public static Optional getParentVarDef(Optional node) { + while (node.isPresent()) { + if (node.get() instanceof VarDef) { + return node.map(n -> (VarDef) n); } - node = node.getParent(); + node = node.map(n -> n.getParent()); } return null; } @@ -580,23 +553,9 @@ public static List subsequenceLengthes(String a, String b) { * checks if b contains the first n characters of a as a substring */ private static boolean containsPrefix(String b, String a, int n) { - // TODO performance return b.contains(a.substring(0, n)); } - private static double average(List l) { - Preconditions.checkArgument(l.size() > 0); - return sum(l) * 1. / l.size(); - } - - private static int sum(List l) { - int sum = 0; - for (int i : l) { - sum += i; - } - return sum; - } - public static T getFirstAndOnly(Collection c) { if (c.size() != 1) { throw new Error("Size must be 1 but was " + c.size()); @@ -644,7 +603,6 @@ public static String escapeString(String v) { } public static String escapeHtml(String s) { - // TODO could use apache commons library? s = s.replace("<", "<"); s = s.replace(">", ">"); return s; @@ -696,9 +654,9 @@ public void remove() { public static String readWholeStream(BufferedReader r) throws IOException { StringBuilder sb = new StringBuilder(); - String line; - while ((line = r.readLine()) != null) { - sb.append(line); + Optional line; + while ((line = Optional.ofNullable(r.readLine())).isPresent()) { + line.map(l -> sb.append(l)); } return sb.toString(); } @@ -709,12 +667,12 @@ public static String readWholeStream(InputStream inputStream) throws IOException @SuppressWarnings("unchecked") - public static Optional getNearestByType(@Nullable Element e, Class clazz) { - while (e != null) { - if (clazz.isInstance(e)) { - return Optional.of((T) e); + public static Optional getNearestByType(Optional e, Class clazz) { + while (e.isPresent()) { + if (clazz.isInstance(e.get())) { + return Optional.of((T) e.get()); } - e = e.getParent(); + e = e.flatMap(el -> Optional.ofNullable(el.getParent())); } return Optional.empty(); } @@ -868,12 +826,12 @@ public static String repeat(char c, int size) { return result.toString(); } - public static boolean elementContained(Element e, Element in) { - while (e != null) { - if (e == in) { + public static boolean elementContained(Optional e, Element in) { + while (e.isPresent()) { + if (e.get() == in) { return true; } - e = e.getParent(); + e = e.flatMap(el -> Optional.ofNullable(el.getParent())); } return false; } @@ -906,8 +864,9 @@ public static String exec(File folder, String... cmds) { * see http://stackoverflow.com/questions/309424/read-convert-an-inputstream-to-a-string */ public static String convertStreamToString(InputStream is) { - Scanner s = new Scanner(is).useDelimiter("\\A"); - return s.hasNext() ? s.next() : ""; + try(Scanner s = new Scanner(is).useDelimiter("\\A")) { + return s.hasNext() ? s.next() : ""; + } } public static byte[] convertStreamToBytes(InputStream is) throws IOException { @@ -944,21 +903,22 @@ public static synchronized String getResourceFile(String name) { */ public static synchronized File getResourceFileF(String name) { try { - File f = resourceMap.get(name); - if (f != null && f.exists()) { - return f; + Optional f = Optional.ofNullable(resourceMap.get(name)); + if (f.isPresent() && f.get().exists()) { + return f.get(); } + String[] parts = splitFilename(name); - f = File.createTempFile(parts[0], parts[1]); - f.deleteOnExit(); + File fi = File.createTempFile(parts[0], parts[1]); + fi.deleteOnExit(); try (InputStream is = Pjass.class.getClassLoader().getResourceAsStream(name)) { if (is == null) { throw new RuntimeException("Could not find resource file " + name); } byte[] bytes = Utils.convertStreamToBytes(is); - Files.write(bytes, f); - resourceMap.put(name, f); - return f; + Files.write(bytes, fi); + resourceMap.put(name, fi); + return fi; } } catch (IOException e) { throw new RuntimeException(e); @@ -978,12 +938,12 @@ private static String[] splitFilename(String name) { public static String elementNameWithPath(AstElementWithNameId n) { StringBuilder result = new StringBuilder(n.getNameId().getName()); - Element e = n.getParent(); - while (e != null) { - if (e instanceof AstElementWithNameId) { - result.insert(0, ((AstElementWithNameId) e).getNameId().getName() + "_"); + Optional e = Optional.ofNullable(n.getParent()); + while (e.isPresent()) { + if (e.get() instanceof AstElementWithNameId) { + result.insert(0, ((AstElementWithNameId) e.get()).getNameId().getName() + "_"); } - e = e.getParent(); + e = e.flatMap(el -> Optional.ofNullable(el.getParent())); } return result.toString(); } @@ -1088,10 +1048,10 @@ class Collector extends Thread { @Override public void run() { try (BufferedReader input = new BufferedReader(new InputStreamReader(in))) { - String line; - while ((line = input.readLine()) != null) { - onInput.accept(line); - sb.append(line).append("\n"); + Optional line; + while ((line = Optional.ofNullable(input.readLine())).isPresent()) { + onInput.accept(line.get()); + sb.append(line.get()).append("\n"); } } catch (IOException e) { throw new RuntimeException(e); diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/WurstValidator.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/WurstValidator.java index 33e401141..8f8a3f80e 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/WurstValidator.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/validation/WurstValidator.java @@ -344,7 +344,9 @@ private void check(Element e) { cde.printStackTrace(); Element element = cde.getElement(); String attr = cde.getAttributeName().replaceFirst("^attr", ""); - WLogger.info(Utils.printElementWithSource(element) + " depends on itself when evaluating attribute " + attr); + WLogger.info(Utils.printElementWithSource(Optional.of(element)) + + " depends on itself when evaluating attribute " + + attr); WLogger.info(cde); throw new CompileError(element.attrSource(), Utils.printElement(element) + " depends on itself when evaluating attribute " + attr); @@ -712,7 +714,7 @@ private void checkTypeParameters(AstElementWithTypeParameters e) { } private void checkExprNull(ExprNull e) { - if (!Utils.isJassCode(e) && e.attrExpectedTyp() instanceof WurstTypeUnknown) { + if (!Utils.isJassCode(Optional.of(e)) && e.attrExpectedTyp() instanceof WurstTypeUnknown) { e.addError( "Cannot use 'null' constant here because " + "the compiler cannot infer which kind of null it is."); } @@ -764,7 +766,7 @@ private void checkStmtSet(StmtSet s) { WurstType leftType = s.getUpdatedExpr().attrTyp(); WurstType rightType = s.getRight().attrTyp(); - checkAssignment(Utils.isJassCode(s), s, leftType, rightType); + checkAssignment(Utils.isJassCode(Optional.of(s)), s, leftType, rightType); checkIfAssigningToConstant(s.getUpdatedExpr()); @@ -936,7 +938,7 @@ private void visit(LocalVarDef s) { WurstType leftType = s.attrTyp(); WurstType rightType = initial.attrTyp(); - checkAssignment(Utils.isJassCode(s), s, leftType, rightType); + checkAssignment(Utils.isJassCode(Optional.of(s)), s, leftType, rightType); } else if (s.getInitialExpr() instanceof ArrayInitializer) { ArrayInitializer arInit = (ArrayInitializer) s.getInitialExpr(); checkArrayInit(s, arInit); @@ -977,7 +979,7 @@ private void checkIfRead(VarDef s) { // (same convention as in Erlang) return; } - if (Utils.isJassCode(s)) { + if (Utils.isJassCode(Optional.of(s))) { return; } if (s.getParent() instanceof StmtForRange) { @@ -994,7 +996,7 @@ private void checkVarName(VarDef s, boolean isConstant) { String varName = s.getName(); if (!isValidVarnameStart(varName) // first letter not lower case - && !Utils.isJassCode(s) // not in jass code + && !Utils.isJassCode(Optional.of(s)) // not in jass code && !varName.matches("[A-Z0-9_]+") // not a constant ) { s.addWarning("Variable names should start with a lower case character. (" + varName + ")"); @@ -1059,7 +1061,7 @@ private void visit(GlobalVarDef s) { Expr initial = (Expr) s.getInitialExpr(); WurstType leftType = s.attrTyp(); WurstType rightType = initial.attrTyp(); - checkAssignment(Utils.isJassCode(s), s, leftType, rightType); + checkAssignment(Utils.isJassCode(Optional.of(s)), s, leftType, rightType); } else if (s.getInitialExpr() instanceof ArrayInitializer) { checkArrayInit(s, (ArrayInitializer) s.getInitialExpr()); } @@ -1090,7 +1092,7 @@ private void visit(ExtensionFuncDef func) { } private void checkFunctionName(FunctionDefinition f) { - if (!Utils.isJassCode(f)) { + if (!Utils.isJassCode(Optional.of(f))) { if (!isValidVarnameStart(f.getName())) { f.addWarning("Function names should start with an lower case character."); } @@ -1118,7 +1120,7 @@ private void checkReachability(WStatement s) { if (s.attrPreviousStatements().isEmpty()) { if (s.attrListIndex() > 0 || !(stmts.getParent() instanceof TranslatedToImFunction || stmts.getParent() instanceof ExprStatementsBlock)) { - if (Utils.isJassCode(s)) { + if (Utils.isJassCode(Optional.of(s))) { // in jass this is just a warning, because // the shitty code emitted by jasshelper sometimes // contains unreachable code @@ -1184,7 +1186,7 @@ private void checkUninitializedVars(FunctionLike f) { && !f.getSource().getFile().endsWith("blizzard.j") && !f.getSource().getFile().endsWith("war3map.j") && !FileUtils.getWPosParent(f.getSource()).equals("jassdoc")) { - new DataflowAnomalyAnalysis(Utils.isJassCode(f)).execute(f); + new DataflowAnomalyAnalysis(Utils.isJassCode(Optional.of(f))).execute(f); } } } @@ -1985,7 +1987,7 @@ private void checkBannedFunctions(ExprFunctionCall e) { if (funcs.size() > 1) { StringBuilder alternatives = new StringBuilder(); for (NameLink nameLink : funcs) { - alternatives.append("\n - ").append(Utils.printElementWithSource(nameLink.getDef())); + alternatives.append("\n - ").append(Utils.printElementWithSource(Optional.of(nameLink.getDef()))); } e.addError("Ambiguous function name: " + exFunc + ". Alternatives are: " + alternatives); return; @@ -2086,20 +2088,36 @@ public static String checkOverride(FuncLink func1, FuncLink func2, boolean allow return "Static method " + func1.getName() + " cannot override other methods."; } if (func2.isStatic()) { - return "Static " + Utils.printElementWithSource(func2.getDef()) + " cannot be overridden."; + return "Static " + Utils.printElementWithSource(Optional.of(func2.getDef())) + " cannot be overridden."; } } else { if (func1.isStatic() && !func2.isStatic()) { - return "Static method " + func1.getName() + " cannot override dynamic " + Utils.printElementWithSource(func2.getDef()) + "."; + return "Static method " + + func1.getName() + + " cannot override dynamic " + + Utils.printElementWithSource(Optional.of(func2.getDef())) + + "."; } else if (!func1.isStatic() && func2.isStatic()) { - return "Method " + func1.getName() + " cannot override static " + Utils.printElementWithSource(func2.getDef()) + "."; + return "Method " + + func1.getName() + + " cannot override static " + + Utils.printElementWithSource(Optional.of(func2.getDef())) + + "."; } } if (func1.isVarargMethod() && !func2.isVarargMethod()) { - return "Vararg method " + func1.getName() + " cannot override non-vararg method " + Utils.printElementWithSource(func2.getDef()) + "."; + return "Vararg method " + + func1.getName() + + " cannot override non-vararg method " + + Utils.printElementWithSource(Optional.of(func2.getDef())) + + "."; } if (!func1.isVarargMethod() && func2.isVarargMethod()) { - return "Non-vararg method " + func1.getName() + " cannot override vararg method " + Utils.printElementWithSource(func2.getDef()) + "."; + return "Non-vararg method " + + func1.getName() + + " cannot override vararg method " + + Utils.printElementWithSource(Optional.of(func2.getDef())) + + "."; } int paramCount2 = func2.getParameterTypes().size(); int paramCount1 = func1.getParameterTypes().size(); @@ -2114,12 +2132,16 @@ public static String checkOverride(FuncLink func1, FuncLink func2, boolean allow WurstType type2 = func2.getParameterType(i); if (!type1.isSupertypeOf(type2, func1.getDef())) { return "Parameter " + type1 + " " + func1.getParameterName(i) + " should have type " + type2 - + " to override " + Utils.printElementWithSource(func2.getDef()) + "."; + + " to override " + Utils.printElementWithSource(Optional.of(func2.getDef())) + "."; } } // covariant return types if (!func1.getReturnType().isSubtypeOf(func2.getReturnType(), func1.getDef())) { - return "Return type should be " + func2.getReturnType() + " to override " + Utils.printElementWithSource(func2.getDef()) + "."; + return "Return type should be " + + func2.getReturnType() + + " to override " + + Utils.printElementWithSource(Optional.of(func2.getDef())) + + "."; } // no error return null; @@ -2148,7 +2170,7 @@ private void checkForDuplicateNames(WScope scope) { NameLink l1 = other.get(0); for (int j = 1; j < other.size(); j++) { other.get(j).getDef().addError("An element with name " + name + " already exists: " - + Utils.printElementWithSource(l1.getDef())); + + Utils.printElementWithSource(Optional.of(l1.getDef()))); } } if (funcs.size() <= 1) { @@ -2160,9 +2182,9 @@ private void checkForDuplicateNames(WScope scope) { FuncLink f2 = funcs.get(j); if (!distinctFunctions(f1, f2)) { f1.getDef().addError( - "Function already defined : " + Utils.printElementWithSource(f2.getDef())); + "Function already defined : " + Utils.printElementWithSource(Optional.of(f2.getDef()))); f2.getDef().addError( - "Function already defined : " + Utils.printElementWithSource(f1.getDef())); + "Function already defined : " + Utils.printElementWithSource(Optional.of(f1.getDef()))); } } } diff --git a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/AnnotationTests.java b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/AnnotationTests.java index c46cd4ec6..9ef23dda1 100644 --- a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/AnnotationTests.java +++ b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/AnnotationTests.java @@ -1,11 +1,7 @@ package tests.wurstscript.tests; -import de.peeeq.wurstio.jassinterpreter.DebugPrintError; import org.testng.annotations.Test; -import java.io.File; -import java.io.IOException; - public class AnnotationTests extends WurstScriptTest { diff --git a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/BugTests.java b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/BugTests.java index 9c28723d0..1cfa168ce 100644 --- a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/BugTests.java +++ b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/BugTests.java @@ -11,8 +11,6 @@ import java.io.IOException; public class BugTests extends WurstScriptTest { - - private static final String TEST_DIR = "./testscripts/concept/"; @Test diff --git a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/ModelManagerTests.java b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/ModelManagerTests.java index bf21732df..dbfe0cadd 100644 --- a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/ModelManagerTests.java +++ b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/ModelManagerTests.java @@ -19,7 +19,6 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; @@ -159,7 +158,7 @@ public void movingFiles() throws IOException { // #712 { // check that jump to decl in package A works correctly CompilationUnit cu = manager.getCompilationUnit(fileA); - FunctionCall functionCallFoo = (FunctionCall) Utils.getAstElementAtPos(cu, 4, 5, false); + FunctionCall functionCallFoo = (FunctionCall) Utils.getAstElementAtPos(cu, 4, 5, false).get(); FunctionDefinition def = functionCallFoo.attrFuncDef(); assertEquals(WFile.create(def.attrSource().getFile()), fileTest1); } @@ -174,7 +173,7 @@ public void movingFiles() throws IOException { // #712 { // check that jump to decl in package A works correctly after the change CompilationUnit cu = manager.getCompilationUnit(fileA); - FunctionCall functionCallFoo = (FunctionCall) Utils.getAstElementAtPos(cu, 4, 5, false); + FunctionCall functionCallFoo = (FunctionCall) Utils.getAstElementAtPos(cu, 4, 5, false).get(); FunctionDefinition def = functionCallFoo.attrFuncDef(); assertNotNull(def); assertEquals(WFile.create(def.attrSource().getFile()), fileTest2); diff --git a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/MpqTest.java b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/MpqTest.java index 4b7052da1..5350fcaac 100644 --- a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/MpqTest.java +++ b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/MpqTest.java @@ -8,6 +8,7 @@ import java.io.File; import java.io.IOException; +import java.util.Optional; public class MpqTest { private static final String TEST_W3X = "./testscripts/mpq/test_temp.w3x"; @@ -30,15 +31,15 @@ public void after() { @Test public void test_insert() throws Exception { - try (MpqEditor edit = MpqEditorFactory.getEditor(new File(TEST_W3X))) { + try (MpqEditor edit = MpqEditorFactory.getEditor(Optional.of(new File(TEST_W3X)))) { if (edit.hasFile("test.txt")) { edit.deleteFile("test.txt"); } } - try (MpqEditor edit = MpqEditorFactory.getEditor(new File(TEST_W3X))) { + try (MpqEditor edit = MpqEditorFactory.getEditor(Optional.of(new File(TEST_W3X)))) { edit.insertFile("test.txt", new File("./testscripts/mpq/test.txt")); } - try (MpqEditor edit = MpqEditorFactory.getEditor(new File(TEST_W3X))) { + try (MpqEditor edit = MpqEditorFactory.getEditor(Optional.of(new File(TEST_W3X)))) { Assert.assertTrue(edit.hasFile("test.txt")); } @@ -46,12 +47,12 @@ public void test_insert() throws Exception { @Test public void test_extract() throws Exception { - try (MpqEditor edit = MpqEditorFactory.getEditor(new File(TEST_W3X))) { + try (MpqEditor edit = MpqEditorFactory.getEditor(Optional.of(new File(TEST_W3X)))) { if (!edit.hasFile("test.txt")) { edit.insertFile("test.txt", new File("./testscripts/mpq/test.txt")); } } - try (MpqEditor edit = MpqEditorFactory.getEditor(new File(TEST_W3X))) { + try (MpqEditor edit = MpqEditorFactory.getEditor(Optional.of(new File(TEST_W3X)))) { byte[] f = edit.extractFile("war3map.j"); Assert.assertTrue(f.length > 5); } @@ -60,13 +61,13 @@ public void test_extract() throws Exception { @Test public void test_delete() throws Exception { - try (MpqEditor edit = MpqEditorFactory.getEditor(new File(TEST_W3X))) { + try (MpqEditor edit = MpqEditorFactory.getEditor(Optional.of(new File(TEST_W3X)))) { edit.insertFile("test.txt", new File("./testscripts/mpq/test.txt")); } - try (MpqEditor edit = MpqEditorFactory.getEditor(new File(TEST_W3X))) { + try (MpqEditor edit = MpqEditorFactory.getEditor(Optional.of(new File(TEST_W3X)))) { edit.deleteFile("test.txt"); } - try (MpqEditor edit = MpqEditorFactory.getEditor(new File(TEST_W3X))) { + try (MpqEditor edit = MpqEditorFactory.getEditor(Optional.of(new File(TEST_W3X)))) { Assert.assertFalse(edit.hasFile("test.txt")); } } diff --git a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/PositionTests.java b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/PositionTests.java index 5b0b3e1cf..d22e50a3a 100644 --- a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/PositionTests.java +++ b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/PositionTests.java @@ -17,7 +17,7 @@ public void testFuncCallPos() { "" )); - FunctionCall c = (FunctionCall) Utils.getAstElementAtPos(model.get(0), 3, 12, false); + FunctionCall c = (FunctionCall) Utils.getAstElementAtPos(model.get(0), 3, 12, false).get(); WPos pos = c.attrErrorPos(); System.out.println("pos = " + pos.getLine()); diff --git a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/RealWorldExamples.java b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/RealWorldExamples.java index ce9a36770..831d02231 100644 --- a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/RealWorldExamples.java +++ b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/RealWorldExamples.java @@ -42,8 +42,6 @@ public void linkedHashMap() throws IOException { // see bug #478 boolean executeProg = false; boolean withStdLib = true; boolean executeTests = true; - // - //testScript(Iterable inputFiles, Map inputs, String name, boolean executeProg, boolean withStdLib, boolean executeTests) { new TestConfig(name) .withStdLib(withStdLib) @@ -54,7 +52,6 @@ public void linkedHashMap() throws IOException { // see bug #478 .withInputs(inputs) .run() .getModel(); - //super.testAssertOkFileWithStdLib(new File(BUG_DIR + "LinkedHashMap.wurst"), true); } @Test @@ -62,11 +59,6 @@ public void module() throws IOException { super.testAssertOkFileWithStdLib(new File(BUG_DIR + "module.wurst"), false); } -// @Test -// public void testCyclic() throws IOException { -// super.testAssertErrorFileWithStdLib(new File(BUG_DIR + "cyclic.wurst"), "cyclic dependency", true); -// } - @Test public void testLists() throws IOException { super.testAssertOkFileWithStdLib(new File(TEST_DIR + "ListsTest.wurst"), false); @@ -110,11 +102,6 @@ public void frottyTupleBug() throws IOException { super.testAssertOkFileWithStdLib(new File(TEST_DIR + "tupleBug.wurst"), false); } -// @Test -// public void optimizer() throws IOException { -// super.testAssertOkFileWithStdLib(new File(TEST_DIR + "optimizer.wurst"), false); -// } - @Test public void optimizerNew() throws IOException { super.testAssertOkFileWithStdLib(new File(TEST_DIR + "optimizerNewTests.wurst"), false); diff --git a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/StdLib.java b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/StdLib.java index 6fcf0aa3f..2fa9397ba 100644 --- a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/StdLib.java +++ b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/StdLib.java @@ -1,9 +1,13 @@ package tests.wurstscript.tests; -import de.peeeq.wurstscript.utils.Utils; +import de.peeeq.wurstscript.WLogger; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.lib.Constants; import org.testng.annotations.Test; import java.io.File; +import java.io.IOException; /** * Helper class to download the standard library, which is required by some test @@ -31,44 +35,52 @@ public class StdLib { @Test public void download() { - downloadStandardlib(); + assert(downloadStandardlib()); } - public synchronized static void downloadStandardlib() { + public synchronized static boolean downloadStandardlib() { if (isInitialized) { - return; + return true; } - try { - + try { if (!stdLibFolder.exists()) { tempFolder.mkdirs(); - Utils.exec(tempFolder, "git", "clone", gitRepo, stdLibFolder.getName()); + try (Git git = Git + .cloneRepository() + .setDirectory(stdLibFolder) + .setURI(gitRepo) + .call()) { + git.checkout().setName(Constants.MASTER).call(); + }; } - String revision = Utils.exec(stdLibFolder, "git", "rev-parse", "HEAD").trim(); - if (!revision.equals(version)) { - System.out.println("Wrong version '" + revision + "', executing git pull to get '" + version + "'"); - Utils.exec(stdLibFolder, "git", "checkout", "master"); - Utils.exec(stdLibFolder, "git", "pull"); - Utils.exec(stdLibFolder, "git", "checkout", version, "-f"); + try (Git git = Git.open(stdLibFolder)) { + String head = git.getRepository().resolve(Constants.HEAD).getName(); + if (!head.equals(version)) { + System.out.println("Wrong version '" + head + "', executing git pull to get '" + version + "'"); + + git.checkout().setName(Constants.MASTER).call(); + git.pull().call(); + git.checkout().setName(version).setForceRefUpdate(true).call(); + } } // reset all possible changes - Utils.exec(stdLibFolder, "git", "clean", "-fdx"); - Utils.exec(stdLibFolder, "git", "checkout", "."); - Utils.exec(stdLibFolder, "git", "checkout", version); + Git.open(stdLibFolder).clean().setForce(true).setCleanDirectories(true).setIgnore(false).call(); + Git.open(stdLibFolder).checkout().setName(version).call(); isInitialized = true; - } catch (Exception e) { - throw new RuntimeException(e); + } catch (IOException | GitAPIException e) { + WLogger.severe(e.getStackTrace().toString()); + return false; } + + return true; } public static String getLib() { downloadStandardlib(); return stdLibFolder.getPath(); } - - } diff --git a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/WurstScriptTest.java b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/WurstScriptTest.java index ea6036a81..3edebc661 100644 --- a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/WurstScriptTest.java +++ b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/WurstScriptTest.java @@ -22,7 +22,6 @@ import de.peeeq.wurstscript.jassinterpreter.TestFailException; import de.peeeq.wurstscript.jassinterpreter.TestSuccessException; import de.peeeq.wurstscript.jassprinter.JassPrinter; -import de.peeeq.wurstscript.translation.lua.translation.LuaTranslator; import de.peeeq.wurstscript.luaAst.LuaCompilationUnit; import de.peeeq.wurstscript.translation.imtranslation.ImTranslator; import de.peeeq.wurstscript.utils.Utils; @@ -217,8 +216,15 @@ private CompilationResult testScript() { } public void file(File file) throws IOException { - String content = Files.toString(file, StandardCharsets.UTF_8); - additionalCompilationUnits.add(new CU(file.getName(), content)); + try { + String content = Files.asCharSource(file, StandardCharsets.UTF_8).read(); + additionalCompilationUnits.add(new CU(file.getName(), content)); + } catch (FileNotFoundException e) { + throw new FileNotFoundException("Failed to open file " + + file.getAbsolutePath() + + " - can read? " + + file.canRead()); + } run(); } @@ -547,7 +553,7 @@ private void runPjass(File outputFile) throws Error { private void executeImProg(WurstGui gui, ImProg imProg) throws TestFailException { try { // run the interpreter on the intermediate language - ILInterpreter interpreter = new ILInterpreter(imProg, gui, null, false); + ILInterpreter interpreter = new ILInterpreter(imProg, gui, Optional.empty(), false); interpreter.addNativeProvider(new ReflectionNativeProvider(interpreter)); interpreter.executeFunction("main", null); } catch (TestSuccessException e) { @@ -571,8 +577,8 @@ private void executeJassProg(JassProg prog) } private void executeTests(WurstGui gui, ImTranslator translator, ImProg imProg) { - RunTests runTests = new RunTests(null, 0, 0, null); - RunTests.TestResult res = runTests.runTests(translator, imProg, null, null); + RunTests runTests = new RunTests(Optional.empty(), 0, 0, Optional.empty()); + RunTests.TestResult res = runTests.runTests(translator, imProg, Optional.empty(), Optional.empty()); if (res.getPassedTests() < res.getTotalTests()) { throw new Error("tests failed: " + res.getPassedTests() + " / " + res.getTotalTests() + "\n" + gui.getErrors());