Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ jobs:
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
runs-on: ${{ matrix.os }}
permissions:
checks: write
contents: read
env:
JAVA_TOOL_OPTIONS: >-
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,5 @@ WurstSetup/proguard.map
de.peeeq.wurstscript/output.txt
/HelperScripts/gamedata
/HelperScripts/.gradle
/.gradle-user-home
/gradle-home-temp
43 changes: 42 additions & 1 deletion de.peeeq.wurstscript/deploy.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def jreImageDir = layout.buildDirectory.dir("jre-wurst-25")

def distRoot = layout.buildDirectory.dir("dist/slim-${plat}")
def releasesDir = layout.buildDirectory.dir("releases")
def appCdsArchive = distRoot.map { it.file("wurst-runtime/wurst-lsp.jsa") }

// ----------------------- Toolchain / tool paths (providers) -------------------------
def toolchainSvc = extensions.getByType(JavaToolchainService)
Expand Down Expand Up @@ -223,11 +224,51 @@ tasks.named("assembleSlimCompilerDist", Copy) { t ->
}
}

tasks.register("generateAppCdsArchive", Exec) {
description = "Best-effort AppCDS archive generation for language-server startup."
group = "distribution"
dependsOn("assembleSlimCompilerDist")

inputs.file(fatJar)
inputs.dir(distRoot)
outputs.file(appCdsArchive)
ignoreExitValue = true

doFirst {
def distDir = distRoot.get().asFile
def archiveFile = appCdsArchive.get().asFile
def runtimeJava = new File(distDir, "wurst-runtime/bin/java${os.isWindows() ? '.exe' : ''}")
def compilerJar = new File(distDir, "wurst-compiler/${fatJar.get().asFile.name}")

archiveFile.parentFile.mkdirs()
if (archiveFile.exists()) {
archiveFile.delete()
}

executable = runtimeJava.absolutePath
args "-Xshare:auto",
"-XX:ArchiveClassesAtExit=${archiveFile.absolutePath}",
Comment thread
Frotty marked this conversation as resolved.
"-jar", compilerJar.absolutePath,
"-languageServerAppCdsTrain"

logger.lifecycle("[appcds] Training LS startup with ${runtimeJava.absolutePath}")
}

doLast {
def archiveFile = appCdsArchive.get().asFile
if (executionResult.get().exitValue != 0 || !archiveFile.exists()) {
logger.warn("[appcds] Archive generation did not succeed on ${plat}; continuing without shipped AppCDS archive.")
} else {
logger.lifecycle("[appcds] Wrote ${archiveFile.absolutePath}")
}
}
}

// 4) Package ZIP on all platforms
tasks.register("packageSlimCompilerDistZip", Zip) {
description = "Packages slim dist as a ZIP archive (all platforms)."
group = "distribution"
dependsOn("assembleSlimCompilerDist")
dependsOn("generateAppCdsArchive")

from(distRoot)
destinationDirectory.set(releasesDir)
Expand Down
5 changes: 5 additions & 0 deletions de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ public static void main(String[] args) {
return;
}

if (runArgs.isLanguageServerAppCdsTrain()) {
LanguageServerStarter.trainForAppCds();
return;
}

if (runArgs.isLanguageServer()) {
LanguageServerStarter.start();
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -616,9 +616,11 @@ public static void exportToWurst(List<? extends ObjMod.Obj> customObjs, ObjectFi
* <p>Fields that have no known wrapper method are emitted as commented-out raw
* calls so the output is still useful even when coverage is incomplete.
*
* <p>Returns {@code false} only when there is no wrapper class at all for this
* <p>Returns {@code false} when there is no wrapper class at all for this
* object type / base ID (e.g. doodads, upgrades, or an unknown ability base ID),
* in which case the caller should fall back to the fully raw format.
* or when a mapped wrapper setter exists but its parameter type is not yet
* supported for source re-emission. In those cases the caller should fall back
* to the fully raw format so no object data is lost on re-export.
*/
private static boolean tryExportWithWrapper(Appendable out, ObjectFileType fileType,
String newId, String oldId,
Expand Down Expand Up @@ -677,11 +679,8 @@ private static boolean tryExportWithWrapper(Appendable out, ObjectFileType fileT
return false;
}

for (ObjMod.Obj.Mod m : mods) {
StdlibObjectMappings.FieldMethodInfo info = fieldMethods.get(fieldKey(m, fileType));
if (info != null && !canUseWrapperForMod(m, info)) {
return false;
}
if (hasUnsupportedMappedWrapperField(mods, fieldMethods, fileType)) {
return false;
}

out.append("@compiletime function create_").append(fileType.getExt()).append("_").append(newId)
Expand All @@ -690,7 +689,7 @@ private static boolean tryExportWithWrapper(Appendable out, ObjectFileType fileT

for (ObjMod.Obj.Mod m : mods) {
StdlibObjectMappings.FieldMethodInfo info = fieldMethods.get(fieldKey(m, fileType));
if (info != null) {
if (info != null && canUseWrapperForMod(m, info)) {
Comment thread
Frotty marked this conversation as resolved.
out.append("\t..").append(info.methodName()).append("(");
if (info.hasLevel() && m instanceof ObjMod.Obj.ExtendedMod) {
out.append(String.valueOf(((ObjMod.Obj.ExtendedMod) m).getLevel())).append(", ");
Expand All @@ -707,6 +706,21 @@ private static boolean tryExportWithWrapper(Appendable out, ObjectFileType fileT
return true;
}

private static boolean hasUnsupportedMappedWrapperField(List<ObjMod.Obj.Mod> mods,
Map<String, StdlibObjectMappings.FieldMethodInfo> fieldMethods,
ObjectFileType fileType) {
for (ObjMod.Obj.Mod mod : mods) {
StdlibObjectMappings.FieldMethodInfo info = fieldMethods.get(fieldKey(mod, fileType));
if (info == null) {
continue;
}
if (!canUseWrapperForMod(mod, info)) {
return true;
}
}
return false;
}

/**
* Returns the lookup key used to match a mod to a {@link StdlibObjectMappings.FieldMethodInfo}.
* Uses the mod's actual dataPtr when it is an {@link ObjMod.Obj.ExtendedMod}, regardless of
Expand All @@ -724,8 +738,7 @@ static String fieldKey(ObjMod.Obj.Mod m, ObjectFileType fileType) {
}

private static boolean canUseWrapperForMod(ObjMod.Obj.Mod m, StdlibObjectMappings.FieldMethodInfo info) {
if (!info.parameterType().isEmpty() && !isPrimitiveParameter(info.parameterType())
&& !isEnumParameter(info.parameterType())) {
if (!supportsWrapperParameterType(info.parameterType())) {
return false;
}
if (isEnumParameter(info.parameterType())) {
Expand All @@ -734,6 +747,12 @@ private static boolean canUseWrapperForMod(ObjMod.Obj.Mod m, StdlibObjectMapping
return true;
}

private static boolean supportsWrapperParameterType(String parameterType) {
return parameterType.isEmpty()
|| isPrimitiveParameter(parameterType)
|| isEnumParameter(parameterType);
}

private static boolean isEnumParameter(String parameterType) {
return ENUM_OBJECT_STRING_TO_CONSTANT.containsKey(parameterType);
}
Expand Down Expand Up @@ -848,6 +867,7 @@ private static Map<String, String> enumConstants(String... valueConstantPairs) {
"mline", "MissileLine"
),
"WeaponSound", enumConstants(
"", "Nothing",
Comment thread
Frotty marked this conversation as resolved.
"Nothing", "Nothing",
"AxeMediumChop", "AxeMediumChop",
"MetalHeavyBash", "MetalHeavyBash",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,15 @@ public static void start() {
server.setRemoteEndpoint(launcher.getRemoteEndpoint());
}

public static void trainForAppCds() {
WurstLanguageServer server = new WurstLanguageServer();
try {
server.getTextDocumentService();
server.getWorkspaceService();
} finally {
server.shutdown().join();
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public void setRootPath(WFile rootPath) {
lock.notify();
}
});
private boolean initialBuildPending = false;
private final BufferManager bufferManager = new BufferManager();
private LanguageClient languageClient;

Expand Down Expand Up @@ -200,9 +201,6 @@ private Workitem getNextWorkItem() {
changesToReconcile = ModelManager.Changes.empty();
reconcileNowRequested = false;
return new Workitem("reconcile files (save)", () -> modelManager.reconcile(changes));
} else if (!userRequests.isEmpty()) {
UserRequest<?> req = userRequests.remove();
return new Workitem(req.toString(), () -> req.run(modelManager));
} else if (!changes.isEmpty()) {
// TODO this can be done more efficiently than doing one at a time
PendingChange change = removeFirst(changes);
Expand Down Expand Up @@ -246,6 +244,12 @@ private Workitem getNextWorkItem() {
return new Workitem("reconcile files", () -> {
modelManager.reconcile(changes);
});
} else if (initialBuildPending) {
initialBuildPending = false;
return new Workitem("initial full build", () -> doInitialBuild());
Comment thread
Frotty marked this conversation as resolved.
} else if (!userRequests.isEmpty()) {
UserRequest<?> req = userRequests.remove();
return new Workitem(req.toString(), () -> req.run(modelManager));
}
return null;
}
Expand All @@ -271,11 +275,20 @@ private void doInit(WFile rootPath) {
log("Handle init " + rootPath);
modelManager = new ModelManagerImpl(rootPath.getFile(), bufferManager);
modelManager.onCompilationResult(this::onCompilationResult);
initialBuildPending = true;
} catch (Exception e) {
WLogger.severe(e);
}
}

log("Start building " + rootPath);
private void doInitialBuild() {
try {
if (modelManager == null || rootPath == null) {
return;
}
log("Start background full build " + rootPath);
modelManager.buildProject();

log("Finished building " + rootPath);
log("Finished background full build " + rootPath);
} catch (Exception e) {
WLogger.severe(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -516,20 +516,11 @@ private void resolveImports(WurstGui gui) {
}

private void replaceCompilationUnit(WFile filename) {
File f;
try {
f = filename.getFile();
} catch (FileNotFoundException e) {
WLogger.info("Cannot replaceCompilationUnit for " + filename + "\n" + e);
return;
}
if (!f.exists()) {
removeCompilationUnit(filename);
return;
}
try {
String contents = Files.toString(f, Charsets.UTF_8);
bufferManager.updateFile(WFile.create(f), contents);
String contents = readCompilationUnitContents(filename, true);
if (contents == null) {
return;
}
replaceCompilationUnit(filename, contents, true);
} catch (IOException e) {
WLogger.severe(e);
Expand Down Expand Up @@ -582,13 +573,10 @@ public Changes syncCompilationUnit(WFile f) {
WLogger.debug("syncCompilationUnit File " + f);
String contents;
try {
File file = f.getFile();
if (!file.exists()) {
removeCompilationUnit(f);
contents = readCompilationUnitContents(f, true);
if (contents == null) {
return Changes.empty();
}
contents = Files.toString(file, Charsets.UTF_8);
bufferManager.updateFile(WFile.create(file), contents);
} catch (IOException e) {
WLogger.severe(e);
throw new ModelManagerException(e);
Expand All @@ -608,6 +596,28 @@ public Changes syncCompilationUnit(WFile f) {
return new Changes(io.vavr.collection.HashSet.of(f), oldPackages);
}

private @Nullable String readCompilationUnitContents(WFile filename, boolean preferOpenBuffer) throws IOException {
if (preferOpenBuffer && bufferManager.getTextDocumentVersion(filename) >= 0) {
return bufferManager.getBuffer(filename);
}
File file;
try {
file = filename.getFile();
} catch (FileNotFoundException e) {
WLogger.info("Cannot read compilation unit for " + filename + "\n" + e);
return null;
}
if (!file.exists()) {
removeCompilationUnit(filename);
return null;
}
String contents = Files.toString(file, Charsets.UTF_8);
if (bufferManager.getTextDocumentVersion(filename) < 0) {
bufferManager.updateFile(WFile.create(file), contents);
}
return contents;
}

private CompilationUnit replaceCompilationUnit(WFile filename, String contents, boolean reportErrors) {
if (!isInWurstFolder(filename) && !isAlreadyLoaded(filename)) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public class RunArgs {
private final RunOption optionExtractImports;
private final RunOption optionStartServer;
private final RunOption optionLanguageServer;
private final RunOption optionLanguageServerAppCdsTrain;
private final RunOption optionNoExtractMapScript;
private final RunOption optionFixInstall;
private final RunOption optionCopyMap;
Expand Down Expand Up @@ -136,6 +137,7 @@ public RunArgs(String... args) {

optionLanguageServer = addOption("languageServer", "Starts a language server which can be used by editors to get services "
+ "like code completion, validations, and find declaration. The communication to the language server is via standard input output.");
optionLanguageServerAppCdsTrain = addOption("languageServerAppCdsTrain", "Starts and immediately stops a lightweight language-server startup path for AppCDS training.");

optionHelp = addOption("help", "Prints this help message.");
optionDisablePjass = addOption("noPJass", "Disables PJass checks for the generated code.");
Expand Down Expand Up @@ -352,6 +354,10 @@ public boolean isLanguageServer() {
return optionLanguageServer.isSet;
}

public boolean isLanguageServerAppCdsTrain() {
return optionLanguageServerAppCdsTrain.isSet;
}

public boolean isNoExtractMapScript() {
return optionNoExtractMapScript.isSet;
}
Expand Down
Loading
Loading