add AppMode for best boundaries over stdlib #10

Merged
bquarkz merged 1 commits from dev/add-app-mode-boundaries-for-stdlib into master 2026-05-14 10:41:12 +00:00
54 changed files with 700 additions and 546 deletions
Showing only changes of commit 991863d086 - Show all commits

2
.gitignore vendored
View File

@ -13,6 +13,8 @@ build
.python-version
.venv
# IA
.junie
/debug/
!prometeu-studio/src/main/java/p/studio/workspaces/debug/
!prometeu-studio/src/main/java/p/studio/workspaces/debug/**

View File

@ -1,5 +1,6 @@
package p.studio.compiler;
import p.studio.AppMode;
import p.studio.compiler.models.FrontendSemanticToken;
import p.studio.compiler.models.FrontendSemanticTokenProvider;
import p.studio.compiler.pbs.ast.PbsAst;
@ -26,6 +27,7 @@ import java.util.Set;
public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProvider {
private static final Set<String> BUILTIN_TYPE_NAMES = Set.of("int", "float", "bool", "string", "i32", "i64", "f32", "f64");
private static final int DEFAULT_STDLIB_VERSION = 1;
private static final AppMode DEFAULT_TARGET = AppMode.Game;
private static final ResourceStdlibEnvironmentResolver STDLIB_RESOLVER = new ResourceStdlibEnvironmentResolver();
private static final Map<PbsTokenKind, PbsSemanticKind> DECLARATION_KINDS = declarationKinds();
@ -210,7 +212,7 @@ public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProv
}
private Map<String, PbsSemanticKind> resolveStdlibExportKinds(final PbsAst.ModuleRef moduleRef) {
final var stdlibEnvironment = STDLIB_RESOLVER.resolve(DEFAULT_STDLIB_VERSION);
final var stdlibEnvironment = STDLIB_RESOLVER.resolve(DEFAULT_STDLIB_VERSION, DEFAULT_TARGET);
return stdlibEnvironment.resolveModule(moduleRef.project(), moduleRef.pathSegments())
.map(this::parseStdlibVisibleKinds)
.orElseGet(Map::of);

View File

@ -1,21 +1,14 @@
package p.studio.compiler.pbs.stdlib;
import p.studio.utilities.structures.ReadOnlyList;
import p.studio.AppMode;
import java.util.Optional;
public final class EmptyStdlibEnvironmentResolver implements StdlibEnvironmentResolver {
private static final StdlibEnvironment EMPTY = new StdlibEnvironment() {
@Override
public Optional<StdlibModuleSource> resolveModule(
final String project,
final ReadOnlyList<String> pathSegments) {
return Optional.empty();
}
};
private static final StdlibEnvironment EMPTY = (project, pathSegments) -> Optional.empty();
@Override
public StdlibEnvironment resolve(final int stdlibVersion) {
public StdlibEnvironment resolve(final int stdlibVersion, final AppMode target) {
return EMPTY;
}
}

View File

@ -1,26 +1,23 @@
package p.studio.compiler.pbs.stdlib;
import p.studio.AppMode;
import p.studio.utilities.structures.ReadOnlyList;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;
public final class ResourceStdlibEnvironmentResolver implements StdlibEnvironmentResolver {
private static final String STDLIB_ROOT = "stdlib";
@Override
public StdlibEnvironment resolve(final int stdlibVersion) {
return new ResourceStdlibEnvironment(stdlibVersion);
public StdlibEnvironment resolve(final int stdlibVersion, final AppMode target) {
return new ResourceStdlibEnvironment(stdlibVersion, target);
}
private static final class ResourceStdlibEnvironment implements StdlibEnvironment {
private final int stdlibVersion;
private ResourceStdlibEnvironment(final int stdlibVersion) {
this.stdlibVersion = stdlibVersion;
}
private record ResourceStdlibEnvironment(int stdlibVersion, AppMode target) implements StdlibEnvironment {
@Override
public Optional<StdlibModuleSource> resolveModule(
@ -36,7 +33,7 @@ public final class ResourceStdlibEnvironmentResolver implements StdlibEnvironmen
return Optional.of(new StdlibModuleSource(
project,
pathSegments,
ReadOnlyList.wrap(java.util.List.of(new StdlibModuleSource.SourceFile("main.pbs", mainSource.get()))),
ReadOnlyList.wrap(List.of(new StdlibModuleSource.SourceFile("main.pbs", mainSource.get()))),
barrelSource.get()));
}
@ -44,7 +41,10 @@ public final class ResourceStdlibEnvironmentResolver implements StdlibEnvironmen
final String project,
final ReadOnlyList<String> pathSegments) {
final var pathBuilder = new StringBuilder();
pathBuilder.append(STDLIB_ROOT)
pathBuilder
.append(target.exportReferenceName().toLowerCase())
.append('/')
.append(STDLIB_ROOT)
.append('/')
.append(stdlibVersion)
.append('/')

View File

@ -1,6 +1,8 @@
package p.studio.compiler.pbs.stdlib;
import p.studio.AppMode;
public interface StdlibEnvironmentResolver {
StdlibEnvironment resolve(int stdlibVersion);
StdlibEnvironment resolve(int stdlibVersion, AppMode target);
}

View File

@ -1,5 +1,6 @@
package p.studio.compiler.services;
import p.studio.AppMode;
import p.studio.compiler.messages.BuildingIssueSink;
import p.studio.compiler.messages.FrontendPhaseContext;
import p.studio.compiler.models.IRGlobalVisibility;
@ -99,7 +100,8 @@ final class PbsModuleAssemblyService {
projectIdByName,
defaultSyntheticOwnerProjectId,
diagnostics,
ctx.stdlibVersion());
ctx.stdlibVersion(),
ctx.target());
final var modules = new ArrayList<PbsModuleVisibilityValidator.ModuleUnit>(modulesByCoordinates.size());
for (final var entry : modulesByCoordinates.entrySet()) {
@ -206,28 +208,29 @@ final class PbsModuleAssemblyService {
final Map<String, ProjectId> projectIdByName,
final ProjectId defaultSyntheticOwnerProjectId,
final DiagnosticSink diagnostics,
final int stdlibVersion) {
final var stdlibEnvironment = stdlibEnvironmentResolver.resolve(stdlibVersion);
final int stdlibVersion,
final AppMode target) {
final var stdlibEnvironment = stdlibEnvironmentResolver.resolve(stdlibVersion, target);
final var pending = new ArrayDeque<PbsModuleVisibilityValidator.ModuleCoordinates>();
final var resolved = new HashSet<ModuleId>();
enqueueReservedImportsFromKnownModules(modulesByCoordinates, pending);
while (!pending.isEmpty()) {
final var target = pending.removeFirst();
final var targetId = moduleId(moduleTable, target);
if (!resolved.add(targetId)) {
final var moduleCoordinates = pending.removeFirst();
final var moduleId = moduleId(moduleTable, moduleCoordinates);
if (!resolved.add(moduleId)) {
continue;
}
if (modulesByCoordinates.containsKey(target)) {
if (modulesByCoordinates.containsKey(moduleCoordinates)) {
continue;
}
final var moduleSource = stdlibEnvironment.resolveModule(target.project(), target.pathSegments());
final var moduleSource = stdlibEnvironment.resolveModule(moduleCoordinates.project(), moduleCoordinates.pathSegments());
if (moduleSource.isEmpty()) {
continue;
}
final var syntheticOwnerProjectId = projectIdByName.getOrDefault(target.project(), defaultSyntheticOwnerProjectId);
final var syntheticOwnerProjectId = projectIdByName.getOrDefault(moduleCoordinates.project(), defaultSyntheticOwnerProjectId);
if (syntheticOwnerProjectId == null) {
continue;
}
@ -241,15 +244,15 @@ final class PbsModuleAssemblyService {
moduleData.barrels.addAll(loadedModule.barrelFiles().asList());
modulesByCoordinates.put(loadedModule.coordinates(), moduleData);
for (final var sourceFile : loadedModule.sourceFiles()) {
moduleIdByFile.put(sourceFile.fileId(), targetId);
moduleIdByFile.put(sourceFile.fileId(), moduleId);
parsedSourceFiles.add(new PbsParsedSourceFile(
sourceFile.fileId(),
sourceFile.ast(),
targetId,
moduleId,
SourceKind.SDK_INTERFACE));
}
for (final var barrelFile : loadedModule.barrelFiles()) {
moduleIdByFile.put(barrelFile.fileId(), targetId);
moduleIdByFile.put(barrelFile.fileId(), moduleId);
}
enqueueReservedImportsFromSourceFiles(loadedModule.sourceFiles().asList(), pending);
}

View File

@ -2,6 +2,7 @@ package p.studio.compiler.pbs;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import p.studio.AppMode;
import p.studio.compiler.messages.BuildingIssueSink;
import p.studio.compiler.messages.FrontendPhaseContext;
import p.studio.compiler.models.*;
@ -460,7 +461,8 @@ class PbsGateUSdkInterfaceConformanceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
stdlibVersion);
stdlibVersion,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(

View File

@ -2,6 +2,7 @@ package p.studio.compiler.pbs;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import p.studio.AppMode;
import p.studio.compiler.messages.BuildingIssueSink;
import p.studio.compiler.messages.FrontendPhaseContext;
import p.studio.compiler.models.BuildStack;
@ -79,7 +80,8 @@ class PbsGateUStdlibCompileTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(projectIds)),
stdlibVersion);
stdlibVersion,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
new PBSFrontendPhaseService().compile(
@ -96,7 +98,7 @@ class PbsGateUStdlibCompileTest {
private Map<String, StdlibProjectFiles> discoverStdlibProjects(
final int stdlibVersion) throws Exception {
final var resourcePath = "stdlib/" + stdlibVersion;
final var resourcePath = "game/stdlib/" + stdlibVersion;
final var classLoader = PbsGateUStdlibCompileTest.class.getClassLoader();
final var resource = classLoader.getResource(resourcePath);
assertNotNull(resource, "Stdlib version " + stdlibVersion + " was not found on classpath at " + resourcePath);

View File

@ -2,16 +2,12 @@ package p.studio.compiler.services;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import p.studio.AppMode;
import p.studio.compiler.messages.Addressable;
import p.studio.compiler.messages.BuildingIssueSink;
import p.studio.compiler.messages.FESurfaceContext;
import p.studio.compiler.messages.FrontendPhaseContext;
import p.studio.compiler.models.IRGlobalVisibility;
import p.studio.compiler.models.BuildStack;
import p.studio.compiler.models.IRHiddenGlobalKind;
import p.studio.compiler.models.ProjectDescriptor;
import p.studio.compiler.models.SourceHandle;
import p.studio.compiler.models.SourceKind;
import p.studio.compiler.models.*;
import p.studio.compiler.pbs.PbsHostAdmissionErrors;
import p.studio.compiler.pbs.linking.PbsLinkErrors;
import p.studio.compiler.pbs.semantics.PbsSemanticsErrors;
@ -78,6 +74,7 @@ class PBSFrontendPhaseServiceTest {
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
1,
AppMode.Game,
p.studio.compiler.messages.HostAdmissionContext.permissiveDefault(),
new FESurfaceContext(ReadOnlyList.from(new Addressable("assets.ui.panel", 91))));
final var diagnostics = DiagnosticSink.empty();
@ -134,7 +131,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -185,7 +183,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -238,7 +237,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -308,7 +308,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -372,7 +373,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -416,7 +418,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
new PBSFrontendPhaseService().compile(
@ -469,7 +472,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -557,7 +561,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -607,7 +612,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -664,7 +670,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -728,7 +735,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
7);
7,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = frontendService.compile(
@ -779,7 +787,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
7);
7,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = frontendService.compile(
@ -826,7 +835,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
1);
1,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -879,7 +889,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
1);
1,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -932,7 +943,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
1);
1,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -991,7 +1003,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
1);
1,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -1050,7 +1063,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
1);
1,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -1121,7 +1135,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
1);
1,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -1193,7 +1208,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
1);
1,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -1256,7 +1272,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
1);
1,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = frontendService.compile(
@ -1320,7 +1337,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
1);
1,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = frontendService.compile(
@ -1401,7 +1419,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -1473,7 +1492,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
9);
9,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = frontendService.compile(
@ -1527,7 +1547,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
1);
1,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -1557,7 +1578,7 @@ class PBSFrontendPhaseServiceTest {
final var callableCalls = frameExecutable.instructions().stream()
.filter(instruction ->
instruction.kind() == p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.CALL_FUNC)
.map(instruction -> instruction.calleeCallableName())
.map(IRBackendExecutableFunction.Instruction::calleeCallableName)
.toList();
final var intrinsicCalls = frameExecutable.instructions().stream()
.filter(instruction ->
@ -1624,7 +1645,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
1);
1,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -1643,7 +1665,7 @@ class PBSFrontendPhaseServiceTest {
final var callableCalls = frameExecutable.instructions().stream()
.filter(instruction ->
instruction.kind() == p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.CALL_FUNC)
.map(instruction -> instruction.calleeCallableName())
.map(IRBackendExecutableFunction.Instruction::calleeCallableName)
.toList();
final var intrinsicCalls = frameExecutable.instructions().stream()
.filter(instruction ->
@ -1717,7 +1739,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
1);
1,
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = new PBSFrontendPhaseService().compile(
@ -1736,7 +1759,7 @@ class PBSFrontendPhaseServiceTest {
final var callableCalls = frameExecutable.instructions().stream()
.filter(instruction ->
instruction.kind() == p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.CALL_FUNC)
.map(instruction -> instruction.calleeCallableName())
.map(IRBackendExecutableFunction.Instruction::calleeCallableName)
.toList();
final var intrinsicCalls = frameExecutable.instructions().stream()
.filter(instruction ->
@ -1804,7 +1827,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
new PBSFrontendPhaseService().compile(
@ -1861,7 +1885,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
new PBSFrontendPhaseService().compile(
@ -1932,7 +1957,8 @@ class PBSFrontendPhaseServiceTest {
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
11);
11,
AppMode.Game);
final var deniedDiagnostics = DiagnosticSink.empty();
deniedFrontendService.compile(
@ -1998,7 +2024,8 @@ class PBSFrontendPhaseServiceTest {
allowedProjectTable,
allowedFileTable,
new BuildStack(ReadOnlyList.wrap(List.of(allowedProjectId))),
12);
12,
AppMode.Game);
final var allowedDiagnostics = DiagnosticSink.empty();
allowedFrontendService.compile(
@ -2056,7 +2083,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var inlineHintsByFile = PBSFrontendPhaseService.inlineHintsByFile(
@ -2113,7 +2141,8 @@ class PBSFrontendPhaseServiceTest {
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
AppMode.Game);
final var diagnostics = DiagnosticSink.empty();
final var inlineHints = PBSFrontendPhaseService.inlineHintsByFile(
@ -2148,7 +2177,7 @@ class PBSFrontendPhaseServiceTest {
for (final var module : modules) {
byModuleKey.put(moduleKey(module.project(), module.pathSegments()), module);
}
return stdlib -> {
return (stdlib, target) -> {
if (stdlib != acceptedStdlib) {
return (project, pathSegments) -> Optional.empty();
}

View File

@ -5,8 +5,8 @@ import p.studio.compiler.FrontendRegistryService;
import p.studio.compiler.messages.BuildingIssueSink;
import p.studio.compiler.messages.FrontendPhaseContext;
import p.studio.compiler.models.BuilderPipelineContext;
import p.studio.compiler.workspaces.AssetSurfaceContextLoader;
import p.studio.compiler.source.diagnostics.DiagnosticSink;
import p.studio.compiler.workspaces.AssetSurfaceContextLoader;
import p.studio.compiler.workspaces.PipelineStage;
import p.studio.utilities.logs.LogAggregator;
@ -31,6 +31,7 @@ public class FrontendPhasePipelineStage implements PipelineStage {
fileTable,
ctx.resolvedWorkspace.stack(),
ctx.resolvedWorkspace.stdlib(),
ctx.resolvedWorkspace.target(),
p.studio.compiler.messages.HostAdmissionContext.permissiveDefault(),
assetSurfaceContextLoader.load(ctx.resolvedWorkspace.mainProject().getRootPath()));
final var diagnostics = DiagnosticSink.empty();

View File

@ -2,6 +2,7 @@ package p.studio.compiler.models;
import lombok.Builder;
import lombok.Getter;
import p.studio.AppMode;
import p.studio.utilities.structures.ReadOnlyList;
import java.nio.file.Path;
@ -12,6 +13,7 @@ public final class ProjectDescriptor {
private final Path rootPath; // canon root path
private final String name; // project name
private final String version; // project version
private final AppMode target; // project target (Game or System)
private final ReadOnlyList<Path> sourceRoots; // source roots canon paths for the project
@Builder.Default
private final SourceKind sourceKind = SourceKind.PROJECT;

View File

@ -10,6 +10,7 @@ public record PrometeuManifestDTO(
String version,
String language,
String stdlib,
String target,
List<DependencyDeclaration> dependencies) {
@JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)

View File

@ -1,5 +1,6 @@
package p.studio.compiler.models;
import p.studio.AppMode;
import p.studio.compiler.exceptions.BuildException;
import p.studio.compiler.messages.DependencyConfig;
import p.studio.compiler.source.identifiers.ProjectId;
@ -23,6 +24,7 @@ public final class DependencyContext {
public Path mainProjectRootPathCanon;
public FrontendSpec frontendSpec;
public Integer rootStdlib;
public AppMode target;
public ProjectId rootProjectId;
public BuildStack stack;
@ -51,7 +53,7 @@ public final class DependencyContext {
}
final var dependenciesByProject = buildDependenciesByProject();
final var workspaceGraph = new WorkspaceGraph(projectTable, dependenciesByProject);
return new ResolvedWorkspace(rootProjectId, frontendSpec, rootStdlib, workspaceGraph, stack);
return new ResolvedWorkspace(rootProjectId, frontendSpec, rootStdlib, target, workspaceGraph, stack);
}

View File

@ -1,5 +1,6 @@
package p.studio.compiler.models;
import p.studio.AppMode;
import p.studio.compiler.workspaces.DependencyReference;
import p.studio.utilities.structures.ReadOnlyList;
@ -8,5 +9,6 @@ public record PrometeuManifest(
String version,
String language,
int stdlib,
AppMode target,
ReadOnlyList<DependencyReference> dependencies) {
}

View File

@ -1,11 +1,13 @@
package p.studio.compiler.models;
import p.studio.AppMode;
import p.studio.compiler.source.identifiers.ProjectId;
public record ResolvedWorkspace(
ProjectId mainProjectId,
FrontendSpec frontendSpec,
int stdlib,
AppMode target,
WorkspaceGraph graph,
BuildStack stack) {
public ProjectDescriptor mainProject() {

View File

@ -2,7 +2,9 @@ package p.studio.compiler.utilities;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import p.studio.AppMode;
import p.studio.compiler.FrontendRegistryService;
import p.studio.compiler.dtos.PrometeuManifestDTO;
import p.studio.compiler.messages.BuildingIssueSink;
@ -45,7 +47,18 @@ public final class PrometeuManifestUtils {
.error(true)
.message("[DEPS]: manifest missing 'version': " + manifestPathCanon));
}
if (StringUtils.isBlank(dto.target())) {
issuesLocal.report(builder -> builder
.error(true)
.message("[DEPS]: manifest missing 'target': " + manifestPathCanon));
}
final var stdlibMaybe = parseStdlib(dto.stdlib(), manifestPathCanon, issuesLocal);
final var target = EnumUtils.getEnum(AppMode.class, dto.target());
if (target == null) {
issuesLocal.report(builder -> builder
.error(true)
.message("[DEPS]: invalid 'target' \"" + dto.target() + "\": " + manifestPathCanon));
}
final var language = StringUtils.isBlank(dto.language())
? FrontendRegistryService.getDefaultFrontendSpec().getLanguageId()
: dto.language();
@ -54,7 +67,7 @@ public final class PrometeuManifestUtils {
issues.merge(issuesLocal);
return Optional.empty();
}
return Optional.of(new PrometeuManifest(dto.name(), dto.version(), language, stdlibMaybe.getAsInt(), ReadOnlyList.wrap(dependencies)));
return Optional.of(new PrometeuManifest(dto.name(), dto.version(), language, stdlibMaybe.getAsInt(), target, ReadOnlyList.wrap(dependencies)));
}
private static OptionalInt parseStdlib(

View File

@ -53,6 +53,7 @@ public class DiscoverPhase implements DependencyPhase {
}
if (rootPathCanon.equals(ctx.mainProjectRootPathCanon)) {
ctx.rootStdlib = manifest.get().stdlib();
ctx.target = manifest.get().target();
}
final var frontendSpec = FrontendRegistryService.getFrontendSpec(manifest.get().language());
// Returns empty when language is unknown

View File

@ -89,6 +89,7 @@ public final class WireProjectsPhase implements DependencyPhase {
.rootPath(projectInfo.rootDirectory)
.name(projectInfo.manifest.name())
.version(projectInfo.manifest.version())
.target(projectInfo.manifest.target())
.sourceRoots(ReadOnlyList.wrap(sourceRoots))
.build();
}

View File

@ -23,6 +23,7 @@ class PrometeuManifestUtilsTest {
"version": "1.0.0",
"language": "pbs",
"stdlib": "1",
"target": "Game",
"dependencies": []
}
""");
@ -74,6 +75,47 @@ class PrometeuManifestUtilsTest {
assertTrue(issues.asCollection().stream().anyMatch(issue -> issue.getMessage().contains("invalid 'stdlib'")));
}
@Test
void buildManifestRejectsNoTarget() throws IOException {
final var manifestPath = writeManifest("""
{
"name": "main",
"version": "1.0.0",
"language": "pbs",
"stdlib": "1",
"dependencies": []
}
""");
final var issues = BuildingIssueSink.empty();
final var manifest = PrometeuManifestUtils.buildManifest(tempDir, manifestPath, issues);
assertTrue(manifest.isEmpty());
assertTrue(issues.hasErrors());
assertTrue(issues.asCollection().stream().anyMatch(issue -> issue.getMessage().contains("missing 'target'")));
}
@Test
void buildManifestRejectsInvalidTarget() throws IOException {
final var manifestPath = writeManifest("""
{
"name": "main",
"version": "1.0.0",
"language": "pbs",
"stdlib": "1",
"target": "UnknownTarget",
"dependencies": []
}
""");
final var issues = BuildingIssueSink.empty();
final var manifest = PrometeuManifestUtils.buildManifest(tempDir, manifestPath, issues);
assertTrue(manifest.isEmpty());
assertTrue(issues.hasErrors());
assertTrue(issues.asCollection().stream().anyMatch(issue -> issue.getMessage().contains("invalid 'target'")));
}
private Path writeManifest(final String content) throws IOException {
final var manifestPath = tempDir.resolve("prometeu.json");
Files.writeString(manifestPath, content);

View File

@ -2,6 +2,7 @@ package p.studio.compiler.workspaces.phases;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import p.studio.AppMode;
import p.studio.compiler.messages.DependencyConfig;
import p.studio.compiler.models.DependencyContext;
import p.studio.compiler.models.ProjectDescriptor;
@ -66,7 +67,7 @@ class StackPhaseTest {
ctx.projectInfoTable.register(ProjectInfo.builder()
.rootDirectory(root)
.manifestPath(root.resolve("prometeu.json"))
.manifest(new PrometeuManifest(name, "1.0.0", "pbs", 1, ReadOnlyList.wrap(List.of())))
.manifest(new PrometeuManifest(name, "1.0.0", "pbs", 1, AppMode.Game, ReadOnlyList.wrap(List.of())))
.build());
}
}

View File

@ -2,6 +2,7 @@ package p.studio.compiler.workspaces.phases;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import p.studio.AppMode;
import p.studio.compiler.messages.DependencyConfig;
import p.studio.compiler.models.DependencyContext;
import p.studio.compiler.models.ProjectDescriptor;
@ -42,16 +43,17 @@ class ValidatePhaseTest {
ctx.projectInfoTable.register(ProjectInfo.builder()
.rootDirectory(rootPath)
.manifestPath(rootPath.resolve("prometeu.json"))
.manifest(new PrometeuManifest("root", "1.0.0", "pbs", 1, ReadOnlyList.wrap(List.of())))
.manifest(new PrometeuManifest("root", "1.0.0", "pbs", 1, AppMode.Game, ReadOnlyList.wrap(List.of())))
.build());
ctx.projectInfoTable.register(ProjectInfo.builder()
.rootDirectory(depPath)
.manifestPath(depPath.resolve("prometeu.json"))
.manifest(new PrometeuManifest("dep", "1.0.0", "pbs", 2, ReadOnlyList.wrap(List.of())))
.manifest(new PrometeuManifest("dep", "1.0.0", "pbs", 2, AppMode.Game, ReadOnlyList.wrap(List.of())))
.build());
ctx.rootProjectId = rootProjectId;
ctx.rootStdlib = 1;
ctx.target = AppMode.Game;
ctx.dependenciesByProject.add(List.of());
ctx.dependenciesByProject.add(List.of());
ctx.projectNameAndVersions.put("root", new java.util.HashSet<>(List.of("1.0.0")));
@ -85,16 +87,17 @@ class ValidatePhaseTest {
ctx.projectInfoTable.register(ProjectInfo.builder()
.rootDirectory(rootPath)
.manifestPath(rootPath.resolve("prometeu.json"))
.manifest(new PrometeuManifest("root", "1.0.0", "pbs", 2, ReadOnlyList.wrap(List.of())))
.manifest(new PrometeuManifest("root", "1.0.0", "pbs", 2, AppMode.Game, ReadOnlyList.wrap(List.of())))
.build());
ctx.projectInfoTable.register(ProjectInfo.builder()
.rootDirectory(depPath)
.manifestPath(depPath.resolve("prometeu.json"))
.manifest(new PrometeuManifest("dep", "1.0.0", "pbs", 1, ReadOnlyList.wrap(List.of())))
.manifest(new PrometeuManifest("dep", "1.0.0", "pbs", 1, AppMode.Game, ReadOnlyList.wrap(List.of())))
.build());
ctx.rootProjectId = rootProjectId;
ctx.rootStdlib = 2;
ctx.target = AppMode.Game;
ctx.dependenciesByProject.add(List.of());
ctx.dependenciesByProject.add(List.of());
ctx.projectNameAndVersions.put("root", new java.util.HashSet<>(List.of("1.0.0")));

View File

@ -1,5 +1,6 @@
package p.studio.compiler.messages;
import p.studio.AppMode;
import p.studio.compiler.models.BuildStack;
import p.studio.compiler.models.SourceKind;
import p.studio.compiler.source.identifiers.ProjectId;
@ -13,22 +14,16 @@ public class FrontendPhaseContext {
public final BuildStack stack;
private final NameTable nameTable;
private final int stdlibVersion;
private final AppMode target;
private final HostAdmissionContext hostAdmissionContext;
private final FESurfaceContext feSurfaceContext;
public FrontendPhaseContext(
final ProjectTableReader projectTable,
final FileTableReader fileTable,
final BuildStack stack) {
this(projectTable, fileTable, stack, 1, HostAdmissionContext.permissiveDefault(), FESurfaceContext.empty());
}
public FrontendPhaseContext(
final ProjectTableReader projectTable,
final FileTableReader fileTable,
final BuildStack stack,
final int stdlibVersion) {
this(projectTable, fileTable, stack, stdlibVersion, HostAdmissionContext.permissiveDefault(), FESurfaceContext.empty());
final AppMode target) {
this(projectTable, fileTable, stack, 1, target, HostAdmissionContext.permissiveDefault(), FESurfaceContext.empty());
}
public FrontendPhaseContext(
@ -36,8 +31,18 @@ public class FrontendPhaseContext {
final FileTableReader fileTable,
final BuildStack stack,
final int stdlibVersion,
final AppMode target) {
this(projectTable, fileTable, stack, stdlibVersion, target, HostAdmissionContext.permissiveDefault(), FESurfaceContext.empty());
}
public FrontendPhaseContext(
final ProjectTableReader projectTable,
final FileTableReader fileTable,
final BuildStack stack,
final int stdlibVersion,
final AppMode target,
final HostAdmissionContext hostAdmissionContext) {
this(projectTable, fileTable, stack, stdlibVersion, hostAdmissionContext, FESurfaceContext.empty());
this(projectTable, fileTable, stack, stdlibVersion, target, hostAdmissionContext, FESurfaceContext.empty());
}
public FrontendPhaseContext(
@ -45,6 +50,7 @@ public class FrontendPhaseContext {
final FileTableReader fileTable,
final BuildStack stack,
final int stdlibVersion,
final AppMode target,
final HostAdmissionContext hostAdmissionContext,
final FESurfaceContext feSurfaceContext) {
this.projectTable = projectTable;
@ -52,6 +58,7 @@ public class FrontendPhaseContext {
this.stack = stack;
this.nameTable = new NameTable();
this.stdlibVersion = stdlibVersion;
this.target = target;
this.hostAdmissionContext = hostAdmissionContext == null
? HostAdmissionContext.permissiveDefault()
: hostAdmissionContext;
@ -68,6 +75,10 @@ public class FrontendPhaseContext {
return stdlibVersion;
}
public AppMode target() {
return target;
}
public HostAdmissionContext hostAdmissionContext() {
return hostAdmissionContext;
}

View File

@ -0,0 +1,17 @@
package p.studio;
public enum AppMode {
Game("Game"),
System("System"),
;
private final String reference;
AppMode(final String reference) {
this.reference = reference;
}
public String exportReferenceName() {
return reference;
}
}

View File

@ -2,30 +2,14 @@ package p.studio.lsp.services.compiler;
import org.apache.commons.lang3.StringUtils;
import p.studio.compiler.FrontendRegistryService;
import p.studio.compiler.messages.BuilderPipelineConfig;
import p.studio.compiler.messages.BuildingIssueSink;
import p.studio.compiler.messages.FrontendPhaseContext;
import p.studio.compiler.messages.BuildingIssue;
import p.studio.compiler.messages.HostAdmissionContext;
import p.studio.compiler.models.AnalysisSnapshot;
import p.studio.compiler.models.BuilderPipelineContext;
import p.studio.compiler.models.FrontendEditorPaletteSpec;
import p.studio.compiler.models.FrontendHostProjectionEntrySpec;
import p.studio.compiler.models.FrontendHostProjectionSpec;
import p.studio.compiler.models.FrontendSemanticPresentationSpec;
import p.studio.compiler.models.FrontendSemanticToken;
import p.studio.compiler.models.FrontendTokenStyleSpec;
import p.studio.compiler.models.FrontendVisualThemeSpec;
import p.studio.compiler.source.identifiers.FileId;
import p.studio.compiler.messages.*;
import p.studio.compiler.models.*;
import p.studio.compiler.pbs.semantics.*;
import p.studio.compiler.services.PBSFrontendPhaseService;
import p.studio.compiler.workspaces.AssetSurfaceContextLoader;
import p.studio.compiler.source.identifiers.FileId;
import p.studio.compiler.utilities.SourceProviderFactory;
import p.studio.compiler.workspaces.AssetSurfaceContextLoader;
import p.studio.compiler.workspaces.BuilderPipelineService;
import p.studio.compiler.pbs.semantics.PbsEditorialCompletionCandidate;
import p.studio.compiler.pbs.semantics.PbsEditorialResolvedSymbol;
import p.studio.compiler.pbs.semantics.PbsEditorialSignature;
import p.studio.compiler.pbs.semantics.PbsEditorialSymbolKind;
import p.studio.compiler.pbs.semantics.PbsEditorialSupportService;
import p.studio.lsp.messages.*;
import p.studio.lsp.services.LanguageServiceBridge;
import p.studio.utilities.logs.LogAggregator;
@ -33,12 +17,7 @@ import p.studio.utilities.structures.ReadOnlyList;
import java.net.URI;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.*;
public final class CompilerLanguageServiceBridge implements LanguageServiceBridge {
private final AssetSurfaceContextLoader assetSurfaceContextLoader = new AssetSurfaceContextLoader();
@ -218,6 +197,7 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg
pipelineContext.fileTable,
pipelineContext.resolvedWorkspace.stack(),
pipelineContext.resolvedWorkspace.stdlib(),
pipelineContext.resolvedWorkspace.target(),
HostAdmissionContext.permissiveDefault(),
assetSurfaceContextLoader.load(pipelineContext.resolvedWorkspace.mainProject().getRootPath()));
final var semanticReadSurface = PBSFrontendPhaseService.semanticReadSurface(

View File

@ -2,6 +2,8 @@ package p.studio.projects;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.EnumUtils;
import p.studio.AppMode;
import p.studio.projectstate.ProjectLocalStudioSetup;
import p.studio.projectstate.ProjectLocalStudioSetupService;
@ -70,11 +72,11 @@ public final class ProjectCatalogService {
}
public ProjectReference createProject(String projectName) {
return createProject(new ProjectCreationRequest(projectName, projectsRoot, "pbs", 1, "src", 4, null));
return createProject(new ProjectCreationRequest(projectName, projectsRoot, "pbs", 1, AppMode.Game, "src", 4, null));
}
public ProjectReference createProject(String projectName, Path parentLocation) {
return createProject(new ProjectCreationRequest(projectName, parentLocation, "pbs", 1, "src", 4, null));
return createProject(new ProjectCreationRequest(projectName, parentLocation, "pbs", 1, AppMode.Game, "src", 4, null));
}
public ProjectReference createProject(ProjectCreationRequest request) {
@ -90,6 +92,9 @@ public final class ProjectCatalogService {
if (request.stdlib() <= 0) {
throw new IllegalArgumentException("project stdlib major must be positive");
}
if (request.target() == null) {
throw new IllegalArgumentException("project target must not be null");
}
if (request.indentationWidth() <= 0) {
throw new IllegalArgumentException("project indentation width must be positive");
}
@ -115,13 +120,14 @@ public final class ProjectCatalogService {
"1.0.0",
languageId,
request.stdlib(),
request.target(),
projectRoot);
Files.createDirectories(ProjectStudioPaths.studioRoot(projectReference));
Files.createDirectories(projectRoot.resolve(sourceRoot));
Files.createDirectories(projectRoot.resolve("assets"));
Files.createDirectories(projectRoot.resolve("build"));
Files.createDirectories(projectRoot.resolve("cartridge"));
Files.writeString(manifestPath(projectRoot), defaultManifest(displayName, languageId, request.stdlib()));
Files.writeString(manifestPath(projectRoot), defaultManifest(displayName, languageId, request.stdlib(), request.target()));
Files.writeString(projectRoot.resolve(".gitignore"), defaultGitIgnore());
projectLocalStudioSetupService.save(
projectReference,
@ -151,6 +157,9 @@ public final class ProjectCatalogService {
if (manifest.version() == null || manifest.version().isBlank()) {
throw new IllegalArgumentException("project manifest missing version: " + manifestPath);
}
if (manifest.target() == null || manifest.target().isBlank()) {
throw new IllegalArgumentException("project manifest missing target: " + manifestPath);
}
if (manifest.language() == null || manifest.language().isBlank()) {
throw new IllegalArgumentException("project manifest missing language: " + manifestPath);
}
@ -160,11 +169,16 @@ public final class ProjectCatalogService {
} catch (RuntimeException runtimeException) {
throw new IllegalArgumentException("project manifest invalid stdlib: " + manifestPath, runtimeException);
}
final AppMode target = EnumUtils.getEnum(AppMode.class, manifest.target());
if (target == null) {
throw new IllegalArgumentException("project manifest invalid target: " + manifestPath);
}
return new ProjectReference(
manifest.name().trim(),
manifest.version().trim(),
manifest.language().trim(),
stdlibMajor,
target,
normalizedRoot);
}
@ -188,17 +202,22 @@ public final class ProjectCatalogService {
return normalized;
}
private String defaultManifest(String projectName, String languageId, int stdlibMajor) {
private String defaultManifest(
final String projectName,
final String languageId,
final int stdlibMajor,
final AppMode target) {
return """
{
"name": "%s",
"version": "1.0.0",
"language": "%s",
"stdlib": "%d",
"target": "%s",
"dependencies": [
]
}
""".formatted(projectName, languageId, stdlibMajor);
""".formatted(projectName, languageId, stdlibMajor, target.exportReferenceName());
}
private String defaultGitIgnore() {
@ -223,7 +242,7 @@ public final class ProjectCatalogService {
}
@JsonIgnoreProperties(ignoreUnknown = true)
private record ProjectManifestSummary(String name, String version, String language, String stdlib) {
private record ProjectManifestSummary(String name, String version, String language, String stdlib, String target) {
}
private String sanitizeProjectName(String rawName) {

View File

@ -1,5 +1,7 @@
package p.studio.projects;
import p.studio.AppMode;
import java.nio.file.Path;
public record ProjectCreationRequest(
@ -7,6 +9,7 @@ public record ProjectCreationRequest(
Path parentLocation,
String languageId,
int stdlib,
AppMode target,
String sourceRoot,
int indentationWidth,
String runtimePath) {

View File

@ -2,6 +2,7 @@ package p.studio.projects;
import org.apache.commons.lang3.StringUtils;
import p.packer.messages.PackerProjectContext;
import p.studio.AppMode;
import p.studio.lsp.messages.LspProjectContext;
import java.nio.file.Path;
@ -11,6 +12,7 @@ public record ProjectReference(
String version,
String languageId,
int stdlibVersion,
AppMode target,
Path rootPath) {
@Override
public String toString() {

View File

@ -181,7 +181,7 @@ public final class StudioShipperService {
manifest.put("app_id", stableAppId(projectReference));
manifest.put("title", projectReference.name());
manifest.put("app_version", projectReference.version());
manifest.put("app_mode", "Game");
manifest.put("app_mode", projectReference.target().exportReferenceName());
manifest.set("capabilities", capabilitiesNode(buildResult));
manifest.set("asset_table", readArrayOrEmpty(projectReference.rootPath().resolve(BUILD_DIR).resolve(ASSET_TABLE_FILE)));
manifest.set("preload", readArrayOrEmpty(projectReference.rootPath().resolve(BUILD_DIR).resolve(PRELOAD_FILE)));

View File

@ -14,6 +14,7 @@ import javafx.stage.DirectoryChooser;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;
import p.studio.AppMode;
import p.studio.Container;
import p.studio.projects.*;
import p.studio.utilities.i18n.I18n;
@ -298,6 +299,7 @@ public final class NewProjectWizard {
Path.of(locationField.getText().trim()),
selectedLanguageId(),
selectedStdlib().version(),
AppMode.Game, // hardcoded for now, we can add a separate step for this if needed
selectedSourceRoot(),
selectedIndentationWidth(),
selectedRuntimePath())));

View File

@ -2,6 +2,7 @@ package p.studio.controls.shell;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import p.studio.AppMode;
import p.studio.projects.ProjectReference;
import p.studio.projects.ProjectStudioPaths;
@ -64,6 +65,6 @@ final class StudioActivityStorageServiceTest {
private ProjectReference project(String name) {
final Path projectRoot = tempDir.resolve(name);
return new ProjectReference("Main", "1.0.0", "pbs", 1, projectRoot);
return new ProjectReference("Main", "1.0.0", "pbs", 1, AppMode.Game, projectRoot);
}
}

View File

@ -1,6 +1,7 @@
package p.studio.execution;
import org.junit.jupiter.api.Test;
import p.studio.AppMode;
import p.studio.StudioBackgroundTasks;
import p.studio.debug.runtime.StudioRuntimeDebugConnectionSettings;
import p.studio.debug.runtime.StudioRuntimeHandshakeClient;
@ -183,7 +184,7 @@ final class StudioPlayStopCoordinatorTest {
}
private ProjectReference projectReference() {
return new ProjectReference("Main", "1.0.0", "pbs", 1, Path.of("/tmp/prometeu-play-stop"));
return new ProjectReference("Main", "1.0.0", "pbs", 1, AppMode.Game, Path.of("/tmp/prometeu-play-stop"));
}
private static final class RecordingHandshakeClient implements StudioRuntimeHandshakeClient {

View File

@ -2,6 +2,7 @@ package p.studio.projects;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import p.studio.AppMode;
import java.nio.file.Files;
import java.nio.file.Path;
@ -34,7 +35,7 @@ final class KnownProjectsServiceTest {
final Path projectsRoot = tempDir.resolve("projects");
Files.createDirectories(projectsRoot.resolve("alpha"));
Files.writeString(projectsRoot.resolve("alpha").resolve("prometeu.json"), manifest("Alpha Project"));
final ProjectReference alpha = new ProjectReference("Alpha Project", "1.0.0", "pbs", 1, projectsRoot.resolve("alpha"));
final ProjectReference alpha = new ProjectReference("Alpha Project", "1.0.0", "pbs", 1, AppMode.Game, projectsRoot.resolve("alpha"));
final KnownProjectsService service = new KnownProjectsService(
tempDir.resolve("known-projects.txt"),
@ -52,7 +53,7 @@ final class KnownProjectsServiceTest {
final Path projectsRoot = tempDir.resolve("projects");
Files.createDirectories(projectsRoot.resolve("alpha"));
Files.writeString(projectsRoot.resolve("alpha").resolve("prometeu.json"), manifest("Alpha Project"));
final ProjectReference alpha = new ProjectReference("Alpha Project", "1.0.0", "pbs", 1, projectsRoot.resolve("alpha"));
final ProjectReference alpha = new ProjectReference("Alpha Project", "1.0.0", "pbs", 1, AppMode.Game, projectsRoot.resolve("alpha"));
final KnownProjectsService service = new KnownProjectsService(
tempDir.resolve("known-projects.txt"),
@ -74,6 +75,7 @@ final class KnownProjectsServiceTest {
"version": "1.0.0",
"language": "pbs",
"stdlib": "1",
"target": "Game",
"dependencies": []
}
""".formatted(name);

View File

@ -2,6 +2,7 @@ package p.studio.projects;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import p.studio.AppMode;
import java.nio.file.Files;
import java.nio.file.Path;
@ -38,6 +39,7 @@ final class ProjectCatalogServiceTest {
assertEquals("1.0.0", project.version());
assertEquals("pbs", project.languageId());
assertEquals(1, project.stdlibVersion());
assertEquals(AppMode.Game, project.target());
assertTrue(Files.isDirectory(project.rootPath()));
assertTrue(Files.isRegularFile(project.rootPath().resolve("prometeu.json")));
assertTrue(Files.isRegularFile(project.rootPath().resolve(".gitignore")));
@ -84,6 +86,7 @@ final class ProjectCatalogServiceTest {
tempDir,
"pbs",
7,
AppMode.Game,
"code",
8,
"/opt/prometeu/runtime"));
@ -135,6 +138,7 @@ final class ProjectCatalogServiceTest {
"version": "1.0.0",
"language": "pbs",
"stdlib": "1",
"target": "Game",
"dependencies": []
}
""".formatted(name);

View File

@ -1,6 +1,7 @@
package p.studio.projectsessions;
import org.junit.jupiter.api.Test;
import p.studio.AppMode;
import p.studio.lsp.api.LspServerLifecycle;
import p.studio.lsp.messages.LspProjectContext;
import p.studio.lsp.messages.LspServerConfiguration;
@ -29,6 +30,7 @@ final class StudioProjectSessionFactoryTest {
"1.0.0",
"pbs",
1,
AppMode.Game,
Path.of("/tmp/example"));
final StudioProjectSession session = sessionFactory.open(projectReference);
@ -58,6 +60,7 @@ final class StudioProjectSessionFactoryTest {
"1.0.0",
"pbs",
1,
AppMode.Game,
Path.of("/tmp/example"))));
assertEquals("boom", failure.getMessage());

View File

@ -1,6 +1,7 @@
package p.studio.projectsessions;
import org.junit.jupiter.api.Test;
import p.studio.AppMode;
import p.studio.execution.StudioExecutionSessionService;
import p.studio.lsp.api.LspServerLifecycle;
import p.studio.lsp.messages.LspProjectContext;
@ -72,7 +73,7 @@ final class StudioProjectSessionTest {
}
private ProjectReference projectReference() {
return new ProjectReference("Example", "1.0.0", "pbs", 1, Path.of("/tmp/example"));
return new ProjectReference("Example", "1.0.0", "pbs", 1, AppMode.Game, Path.of("/tmp/example"));
}
private static final class RecordingProjectLocalStudioStateService extends ProjectLocalStudioStateService {

View File

@ -2,6 +2,7 @@ package p.studio.projectstate;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import p.studio.AppMode;
import p.studio.projects.ProjectReference;
import p.studio.projects.ProjectStudioPaths;
@ -75,6 +76,6 @@ final class ProjectLocalStudioSetupServiceTest {
private ProjectReference project(final String name) {
final Path projectRoot = tempDir.resolve(name);
return new ProjectReference("Main", "1.0.0", "pbs", 1, projectRoot);
return new ProjectReference("Main", "1.0.0", "pbs", 1, AppMode.Game, projectRoot);
}
}

View File

@ -2,6 +2,7 @@ package p.studio.projectstate;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import p.studio.AppMode;
import p.studio.projects.ProjectReference;
import p.studio.projects.ProjectStudioPaths;
@ -97,6 +98,6 @@ final class ProjectLocalStudioStateServiceTest {
private ProjectReference project(final String name) {
final Path projectRoot = tempDir.resolve(name);
return new ProjectReference("Main", "1.0.0", "pbs", 1, projectRoot);
return new ProjectReference("Main", "1.0.0", "pbs", 1, AppMode.Game, projectRoot);
}
}

View File

@ -10,6 +10,7 @@ import p.packer.messages.assets.AssetFamilyCatalog;
import p.packer.messages.assets.OutputCodecCatalog;
import p.packer.messages.assets.OutputFormatCatalog;
import p.packer.messages.assets.PackerCodecConfigurationFieldType;
import p.studio.AppMode;
import p.studio.projects.ProjectReference;
import p.studio.workspaces.assets.metadata.AssetStudioGlyphSpecialization;
import p.studio.workspaces.assets.metadata.AssetStudioSceneBankMetadata;
@ -118,7 +119,7 @@ final class SceneBankWorkflowServiceTest {
}
private ProjectReference projectReference() {
return new ProjectReference("main", "1", "pbs", 1, tempDir.resolve("project"));
return new ProjectReference("main", "1", "pbs", 1, AppMode.Game, tempDir.resolve("project"));
}
private AssetWorkspaceAssetDetails createValidScene(ProjectReference project) throws Exception {

View File

@ -8,13 +8,10 @@ import p.packer.messages.assets.AssetFamilyCatalog;
import p.packer.messages.assets.OutputCodecCatalog;
import p.packer.messages.assets.OutputFormatCatalog;
import p.packer.messages.assets.PackerCodecConfigurationFieldType;
import p.studio.AppMode;
import p.studio.projects.ProjectReference;
import p.studio.workspaces.assets.metadata.AssetStudioGlyphSpecialization;
import p.studio.workspaces.assets.metadata.AssetStudioMetadataService;
import p.studio.workspaces.assets.metadata.AssetStudioSceneBankMetadata;
import p.studio.workspaces.assets.metadata.AssetStudioSceneLayerBinding;
import p.studio.workspaces.assets.metadata.AssetStudioSceneTile;
import p.studio.workspaces.assets.messages.*;
import p.studio.workspaces.assets.metadata.*;
import java.nio.file.Files;
import java.nio.file.Path;
@ -45,8 +42,8 @@ final class TiledAssetGenerationServiceTest {
assertTrue(Files.isRegularFile(tsxPath));
final TiledTilesetDocument tileset = codec.readTileset(tsxPath);
assertEquals(2, tileset.tiles().size());
assertEquals("a.png", tileset.tiles().get(0).imageSource());
assertEquals("glyph_id", tileset.tiles().get(0).properties().getFirst().name());
assertEquals("a.png", tileset.tiles().getFirst().imageSource());
assertEquals("glyph_id", tileset.tiles().getFirst().properties().getFirst().name());
}
@Test
@ -70,7 +67,7 @@ final class TiledAssetGenerationServiceTest {
final Path sceneRoot = projectRoot.resolve("assets/scenes/overworld");
Files.createDirectories(sceneRoot);
final AssetWorkspaceAssetDetails details = sceneDetails(sceneRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, projectRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, AppMode.Game, projectRoot);
final TiledAssetGenerationResult result = service.exportSceneBankTmx(projectReference, details);
@ -105,7 +102,7 @@ final class TiledAssetGenerationServiceTest {
final Path sceneRoot = projectRoot.resolve("assets/scenes/overworld");
Files.createDirectories(sceneRoot);
final AssetWorkspaceAssetDetails details = sceneDetails(sceneRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, projectRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, AppMode.Game, projectRoot);
final Path tmxPath = sceneRoot.resolve("scene.tmx");
Files.writeString(tmxPath, "legacy");
@ -145,7 +142,7 @@ final class TiledAssetGenerationServiceTest {
final Path sceneRoot = projectRoot.resolve("assets/scenes/overworld");
Files.createDirectories(sceneRoot);
final AssetWorkspaceAssetDetails details = sceneDetails(sceneRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, projectRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, AppMode.Game, projectRoot);
assertTrue(service.exportSceneBankTmx(projectReference, details).success());
final Path tmxPath = sceneRoot.resolve("scene.tmx");
@ -183,7 +180,7 @@ final class TiledAssetGenerationServiceTest {
final Path sceneRoot = projectRoot.resolve("assets/scenes/overworld");
Files.createDirectories(sceneRoot);
final AssetWorkspaceAssetDetails details = sceneDetails(sceneRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, projectRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, AppMode.Game, projectRoot);
assertTrue(service.exportSceneBankTmx(projectReference, details).success());
final Path tsxPath = tilesetRoot.resolve(TiledAssetGenerationService.GENERATED_TSX_FILE);
@ -224,7 +221,7 @@ final class TiledAssetGenerationServiceTest {
final Path sceneRoot = projectRoot.resolve("assets/scenes/overworld");
Files.createDirectories(sceneRoot);
final AssetWorkspaceAssetDetails details = sceneDetails(sceneRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, projectRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, AppMode.Game, projectRoot);
assertTrue(service.exportSceneBankTmx(projectReference, details).success());
final Path tmxPath = sceneRoot.resolve("scene.tmx");
@ -290,7 +287,7 @@ final class TiledAssetGenerationServiceTest {
final Path sceneRoot = projectRoot.resolve("assets/scenes/overworld");
Files.createDirectories(sceneRoot);
final AssetWorkspaceAssetDetails details = sceneDetails(sceneRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, projectRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, AppMode.Game, projectRoot);
assertTrue(service.exportSceneBankTmx(projectReference, details).success());
final Path tmxPath = sceneRoot.resolve("scene.tmx");
@ -361,7 +358,7 @@ final class TiledAssetGenerationServiceTest {
final Path sceneRoot = projectRoot.resolve("assets/scenes/overworld");
Files.createDirectories(sceneRoot);
final AssetWorkspaceAssetDetails details = sceneDetails(sceneRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, projectRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, AppMode.Game, projectRoot);
final Path tmxPath = sceneRoot.resolve("scene.tmx");
Files.writeString(tmxPath, """
@ -398,7 +395,7 @@ final class TiledAssetGenerationServiceTest {
final Path sceneRoot = projectRoot.resolve("assets/scenes/overworld");
Files.createDirectories(sceneRoot);
final AssetWorkspaceAssetDetails details = sceneDetails(sceneRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, projectRoot);
final ProjectReference projectReference = new ProjectReference("main", "1", "pbs", 1, AppMode.Game, projectRoot);
final Path tmxPath = sceneRoot.resolve("scene.tmx");
Files.writeString(tmxPath, """

View File

@ -3,6 +3,7 @@
"version": "1.0.0",
"language": "pbs",
"stdlib": "1",
"target": "Game",
"dependencies": [
]
}

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
"version": "1.0.0",
"language": "pbs",
"stdlib": "1",
"target": "Game",
"dependencies": [
]
}