frontend spec by workspace instead
This commit is contained in:
parent
f627914c9f
commit
9170104a12
@ -1,11 +1,9 @@
|
|||||||
package p.studio.compiler.workspaces;
|
package p.studio.compiler.workspaces;
|
||||||
|
|
||||||
import p.studio.compiler.messages.BuildingIssue;
|
import p.studio.compiler.messages.BuildingIssueSink;
|
||||||
import p.studio.compiler.messages.BuildingIssues;
|
|
||||||
import p.studio.compiler.models.BuilderPipelineContext;
|
import p.studio.compiler.models.BuilderPipelineContext;
|
||||||
import p.studio.utilities.logs.LogAggregator;
|
import p.studio.utilities.logs.LogAggregator;
|
||||||
import p.studio.utilities.structures.ReadOnlyCollection;
|
|
||||||
|
|
||||||
public interface PipelineStage {
|
public interface PipelineStage {
|
||||||
BuildingIssues run(BuilderPipelineContext ctx, LogAggregator logs);
|
BuildingIssueSink run(BuilderPipelineContext ctx, LogAggregator logs);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package p.studio.compiler.workspaces.stages;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import p.studio.compiler.messages.BuildingIssues;
|
import p.studio.compiler.messages.BuildingIssueSink;
|
||||||
import p.studio.compiler.models.BuilderPipelineContext;
|
import p.studio.compiler.models.BuilderPipelineContext;
|
||||||
import p.studio.compiler.models.SourceHandle;
|
import p.studio.compiler.models.SourceHandle;
|
||||||
import p.studio.compiler.workspaces.PipelineStage;
|
import p.studio.compiler.workspaces.PipelineStage;
|
||||||
@ -26,15 +26,15 @@ import java.util.stream.Collectors;
|
|||||||
public class LoadPipelineStage implements PipelineStage {
|
public class LoadPipelineStage implements PipelineStage {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuildingIssues run(final BuilderPipelineContext ctx, final LogAggregator logs) {
|
public BuildingIssueSink run(final BuilderPipelineContext ctx, final LogAggregator logs) {
|
||||||
final var issues = BuildingIssues.empty();
|
final var issues = BuildingIssueSink.empty();
|
||||||
|
|
||||||
// Iterates projects; "loads sources"; registers files
|
// Iterates projects; "loads sources"; registers files
|
||||||
ctx.resolvedWorkspace.topologicalOrder().forEach(pId -> {
|
ctx.resolvedWorkspace.topologicalOrder().forEach(pId -> {
|
||||||
final var pd = ctx.resolvedWorkspace.graph().projectTable().get(pId);
|
final var pd = ctx.resolvedWorkspace.graph().projectTable().get(pId);
|
||||||
logs.using(log).info("Project [ " + pd.getName() + " ] source loading...");
|
logs.using(log).info("Project [ " + pd.getName() + " ] source loading...");
|
||||||
|
|
||||||
final var allowedExtensions = normalize(pd.getFrontendSpec().getAllowedExtensions());
|
final var allowedExtensions = normalize(ctx.resolvedWorkspace.frontendSpec().getAllowedExtensions());
|
||||||
for (final var sourceRootPath : pd.getSourceRoots()) {
|
for (final var sourceRootPath : pd.getSourceRoots()) {
|
||||||
logs.using(log).debug("Walking source root [ " + sourceRootPath + " ]");
|
logs.using(log).debug("Walking source root [ " + sourceRootPath + " ]");
|
||||||
|
|
||||||
@ -52,14 +52,14 @@ public class LoadPipelineStage implements PipelineStage {
|
|||||||
var fileId = ctx.fileTable.register(rawFile);
|
var fileId = ctx.fileTable.register(rawFile);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
issues.add(builder -> builder
|
issues.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("Failed to load project [ " + pd.getName() + " ]")
|
.message("Failed to load project [ " + pd.getName() + " ]")
|
||||||
.exception(e));
|
.exception(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return BuildingIssues.empty();
|
return BuildingIssueSink.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ReadOnlySet<String> normalize(final ReadOnlySet<String> extensions) {
|
private static ReadOnlySet<String> normalize(final ReadOnlySet<String> extensions) {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package p.studio.compiler.workspaces.stages;
|
package p.studio.compiler.workspaces.stages;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import p.studio.compiler.messages.BuildingIssues;
|
import p.studio.compiler.messages.BuildingIssueSink;
|
||||||
import p.studio.compiler.messages.DependencyConfig;
|
import p.studio.compiler.messages.DependencyConfig;
|
||||||
import p.studio.compiler.models.BuilderPipelineContext;
|
import p.studio.compiler.models.BuilderPipelineContext;
|
||||||
import p.studio.compiler.workspaces.DependencyService;
|
import p.studio.compiler.workspaces.DependencyService;
|
||||||
@ -14,18 +14,18 @@ import java.nio.file.Paths;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class ResolvePipelineStage implements PipelineStage {
|
public class ResolvePipelineStage implements PipelineStage {
|
||||||
@Override
|
@Override
|
||||||
public BuildingIssues run(final BuilderPipelineContext ctx, LogAggregator logs) {
|
public BuildingIssueSink run(final BuilderPipelineContext ctx, LogAggregator logs) {
|
||||||
try {
|
try {
|
||||||
ctx.rootProjectPathCanon = Paths.get(ctx.config.rootProjectPath()).toRealPath();
|
ctx.rootProjectPathCanon = Paths.get(ctx.config.rootProjectPath()).toRealPath();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return BuildingIssues.empty()
|
return BuildingIssueSink.empty()
|
||||||
.add(builder -> builder
|
.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("[BUILD]: root project directory no found: " + ctx.config.rootProjectPath())
|
.message("[BUILD]: root project directory no found: " + ctx.config.rootProjectPath())
|
||||||
.exception(e));
|
.exception(e));
|
||||||
}
|
}
|
||||||
final var dependencyConfig = new DependencyConfig(ctx.config.explain(), ctx.rootProjectPathCanon);
|
final var dependencyConfig = new DependencyConfig(ctx.config.explain(), ctx.rootProjectPathCanon);
|
||||||
ctx.resolvedWorkspace = DependencyService.INSTANCE.run(dependencyConfig, logs);
|
ctx.resolvedWorkspace = DependencyService.INSTANCE.run(dependencyConfig, logs);
|
||||||
return BuildingIssues.empty();
|
return BuildingIssueSink.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,18 +5,18 @@ import p.studio.utilities.structures.ReadOnlyCollection;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class BuildingIssues extends ReadOnlyCollection<BuildingIssue> {
|
public class BuildingIssueSink extends ReadOnlyCollection<BuildingIssue> {
|
||||||
private boolean hasErrors = false;
|
private boolean hasErrors = false;
|
||||||
|
|
||||||
protected BuildingIssues() {
|
protected BuildingIssueSink() {
|
||||||
super(new ArrayList<>());
|
super(new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BuildingIssues empty() {
|
public static BuildingIssueSink empty() {
|
||||||
return new BuildingIssues();
|
return new BuildingIssueSink();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BuildingIssues add(final Consumer<BuildingIssue.BuildingIssueBuilder> consumer) {
|
public BuildingIssueSink report(final Consumer<BuildingIssue.BuildingIssueBuilder> consumer) {
|
||||||
final var builder = BuildingIssue.builder();
|
final var builder = BuildingIssue.builder();
|
||||||
consumer.accept(builder);
|
consumer.accept(builder);
|
||||||
final var issue = builder.build();
|
final var issue = builder.build();
|
||||||
@ -25,7 +25,7 @@ public class BuildingIssues extends ReadOnlyCollection<BuildingIssue> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BuildingIssues add(final BuildingIssues issues) {
|
public BuildingIssueSink report(final BuildingIssueSink issues) {
|
||||||
hasErrors |= issues.hasErrors();
|
hasErrors |= issues.hasErrors();
|
||||||
collection.addAll(issues.collection);
|
collection.addAll(issues.collection);
|
||||||
return this;
|
return this;
|
||||||
@ -11,4 +11,8 @@ public class FrontendSpec {
|
|||||||
private final ReadOnlySet<String> allowedExtensions;
|
private final ReadOnlySet<String> allowedExtensions;
|
||||||
private final ReadOnlySet<String> sourceRoots;
|
private final ReadOnlySet<String> sourceRoots;
|
||||||
private final boolean caseSensitive;
|
private final boolean caseSensitive;
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return String.format("FrontendSpec(language=%s)", languageId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,5 @@ public final class ProjectDescriptor {
|
|||||||
private final Path rootPath; // canon root path
|
private final Path rootPath; // canon root path
|
||||||
private final String name; // project name
|
private final String name; // project name
|
||||||
private final String version; // project version
|
private final String version; // project version
|
||||||
private final ReadOnlyList<Path> sourceRoots;
|
private final ReadOnlyList<Path> sourceRoots; // source roots canon paths for the project
|
||||||
private final FrontendSpec frontendSpec;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package p.studio.compiler.source.diagnostics;
|
package p.studio.compiler.source.diagnostics;
|
||||||
|
|
||||||
public class DiagnosticBundle {
|
public class DiagnosticSink {
|
||||||
}
|
}
|
||||||
@ -10,21 +10,18 @@ import java.nio.file.Path;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public final class DependencyContext {
|
public final class DependencyContext {
|
||||||
private final DependencyConfig config;
|
public final DependencyConfig config;
|
||||||
|
|
||||||
// Internal state mirroring Rust ResolverState
|
|
||||||
public Path mainProjectRootPathCanon;
|
|
||||||
|
|
||||||
// Phase 1 (Discover)
|
|
||||||
public final Deque<Path> pending = new ArrayDeque<>();
|
public final Deque<Path> pending = new ArrayDeque<>();
|
||||||
public final ProjectInfoTable projectInfoTable = new ProjectInfoTable();
|
|
||||||
|
|
||||||
|
public final ProjectInfoTable projectInfoTable = new ProjectInfoTable();
|
||||||
public final ProjectTable projectTable = new ProjectTable();
|
public final ProjectTable projectTable = new ProjectTable();
|
||||||
|
|
||||||
public final Map<String, Set<String>> projectNameAndVersions = new HashMap<>();
|
public final Map<String, Set<String>> projectNameAndVersions = new HashMap<>();
|
||||||
public final List<ProjectId> projectIds = new ArrayList<>();
|
public final List<ProjectId> projectIds = new ArrayList<>();
|
||||||
public final List<List<ProjectId>> dependenciesByProject = new ArrayList<>();
|
public final List<List<ProjectId>> dependenciesByProject = new ArrayList<>();
|
||||||
|
|
||||||
|
public Path mainProjectRootPathCanon;
|
||||||
|
public FrontendSpec frontendSpec;
|
||||||
public ProjectId rootProjectId;
|
public ProjectId rootProjectId;
|
||||||
public BuildStack stack;
|
public BuildStack stack;
|
||||||
|
|
||||||
@ -36,10 +33,6 @@ public final class DependencyContext {
|
|||||||
return new DependencyContext(config);
|
return new DependencyContext(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DependencyConfig config() {
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ReadOnlyList<ReadOnlyList<ProjectId>> buildDependenciesByProject() {
|
private ReadOnlyList<ReadOnlyList<ProjectId>> buildDependenciesByProject() {
|
||||||
return ReadOnlyList.wrap(this
|
return ReadOnlyList.wrap(this
|
||||||
.dependenciesByProject
|
.dependenciesByProject
|
||||||
@ -54,7 +47,7 @@ public final class DependencyContext {
|
|||||||
}
|
}
|
||||||
final var dependenciesByProject = buildDependenciesByProject();
|
final var dependenciesByProject = buildDependenciesByProject();
|
||||||
final var workspaceGraph = new WorkspaceGraph(projectTable, dependenciesByProject);
|
final var workspaceGraph = new WorkspaceGraph(projectTable, dependenciesByProject);
|
||||||
return new ResolvedWorkspace(rootProjectId, workspaceGraph, stack);
|
return new ResolvedWorkspace(rootProjectId, frontendSpec, workspaceGraph, stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -11,5 +11,4 @@ public final class ProjectInfo {
|
|||||||
public final Path rootDirectory;
|
public final Path rootDirectory;
|
||||||
public final Path manifestPath;
|
public final Path manifestPath;
|
||||||
public final PrometeuManifest manifest;
|
public final PrometeuManifest manifest;
|
||||||
public final FrontendSpec frontendSpec;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import java.util.stream.Stream;
|
|||||||
|
|
||||||
public record ResolvedWorkspace(
|
public record ResolvedWorkspace(
|
||||||
ProjectId projectId,
|
ProjectId projectId,
|
||||||
|
FrontendSpec frontendSpec,
|
||||||
WorkspaceGraph graph,
|
WorkspaceGraph graph,
|
||||||
BuildStack stack) {
|
BuildStack stack) {
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
package p.studio.compiler.workspaces;
|
package p.studio.compiler.workspaces;
|
||||||
|
|
||||||
import p.studio.compiler.messages.BuildingIssues;
|
import p.studio.compiler.messages.BuildingIssueSink;
|
||||||
import p.studio.compiler.models.DependencyContext;
|
import p.studio.compiler.models.DependencyContext;
|
||||||
|
|
||||||
public interface DependencyPhase {
|
public interface DependencyPhase {
|
||||||
BuildingIssues run(DependencyContext state);
|
BuildingIssueSink run(DependencyContext state);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import org.apache.commons.collections4.CollectionUtils;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import p.studio.compiler.FrontendRegistryService;
|
import p.studio.compiler.FrontendRegistryService;
|
||||||
import p.studio.compiler.dtos.PrometeuManifestDTO;
|
import p.studio.compiler.dtos.PrometeuManifestDTO;
|
||||||
import p.studio.compiler.messages.BuildingIssues;
|
import p.studio.compiler.messages.BuildingIssueSink;
|
||||||
import p.studio.compiler.models.DependencyContext;
|
import p.studio.compiler.models.DependencyContext;
|
||||||
import p.studio.compiler.models.ProjectInfo;
|
import p.studio.compiler.models.ProjectInfo;
|
||||||
import p.studio.compiler.models.ProjectInfoId;
|
import p.studio.compiler.models.ProjectInfoId;
|
||||||
@ -25,9 +25,9 @@ import java.util.*;
|
|||||||
|
|
||||||
public class DiscoverPhase implements DependencyPhase {
|
public class DiscoverPhase implements DependencyPhase {
|
||||||
@Override
|
@Override
|
||||||
public BuildingIssues run(final DependencyContext ctx) {
|
public BuildingIssueSink run(final DependencyContext ctx) {
|
||||||
final Map<Path, ProjectInfoId> projectIndexByDirectory = new HashMap<>();
|
final Map<Path, ProjectInfoId> projectIndexByDirectory = new HashMap<>();
|
||||||
final BuildingIssues issues = BuildingIssues.empty();
|
final BuildingIssueSink issues = BuildingIssueSink.empty();
|
||||||
// Discovers projects; registers them; adds dependencies to queue
|
// Discovers projects; registers them; adds dependencies to queue
|
||||||
while (!ctx.pending.isEmpty()) {
|
while (!ctx.pending.isEmpty()) {
|
||||||
final var rootPathCanon = ctx.pending.pollFirst();
|
final var rootPathCanon = ctx.pending.pollFirst();
|
||||||
@ -40,14 +40,14 @@ public class DiscoverPhase implements DependencyPhase {
|
|||||||
try {
|
try {
|
||||||
manifestPathCanon = rootPathCanon.resolve("prometeu.json").toRealPath();
|
manifestPathCanon = rootPathCanon.resolve("prometeu.json").toRealPath();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
issues.add(builder -> builder
|
issues.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("[DEPS]: manifest canonPath does not exist: " + rootPathCanon)
|
.message("[DEPS]: manifest canonPath does not exist: " + rootPathCanon)
|
||||||
.exception(e));
|
.exception(e));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!Files.exists(manifestPathCanon) || !Files.isRegularFile(manifestPathCanon)) {
|
if (!Files.exists(manifestPathCanon) || !Files.isRegularFile(manifestPathCanon)) {
|
||||||
issues.add(builder -> builder
|
issues.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("[DEPS]: manifest not found: expected a file " + manifestPathCanon));
|
.message("[DEPS]: manifest not found: expected a file " + manifestPathCanon));
|
||||||
continue;
|
continue;
|
||||||
@ -64,18 +64,27 @@ public class DiscoverPhase implements DependencyPhase {
|
|||||||
|
|
||||||
final var frontendSpec = FrontendRegistryService.getFrontendSpec(manifest.language());
|
final var frontendSpec = FrontendRegistryService.getFrontendSpec(manifest.language());
|
||||||
if (frontendSpec.isEmpty()) {
|
if (frontendSpec.isEmpty()) {
|
||||||
issues.add(builder -> builder
|
issues.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("[DEPS]: unknown language " + manifest.language() + " for project " + manifest.name()));
|
.message("[DEPS]: unknown language " + manifest.language() + " for project " + manifest.name()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Objects.isNull(ctx.frontendSpec)) {
|
||||||
|
ctx.frontendSpec = frontendSpec.get();
|
||||||
|
} else if (!ctx.frontendSpec.getLanguageId().equals(frontendSpec.get().getLanguageId())) {
|
||||||
|
issues.report(builder -> builder
|
||||||
|
.error(true)
|
||||||
|
.message(String.format("[DEPS]: inconsistent language: [ %s ] has \"%s\" but should be \"%s\"",
|
||||||
|
manifest.name(), frontendSpec.get().getLanguageId(), ctx.frontendSpec.getLanguageId())));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
final var projectInfo = ProjectInfo
|
final var projectInfo = ProjectInfo
|
||||||
.builder()
|
.builder()
|
||||||
.rootDirectory(rootPathCanon)
|
.rootDirectory(rootPathCanon)
|
||||||
.manifestPath(manifestPathCanon)
|
.manifestPath(manifestPathCanon)
|
||||||
.manifest(manifest)
|
.manifest(manifest)
|
||||||
.frontendSpec(frontendSpec.get())
|
|
||||||
.build();
|
.build();
|
||||||
final var projectInfoId = ctx.projectInfoTable.register(projectInfo);
|
final var projectInfoId = ctx.projectInfoTable.register(projectInfo);
|
||||||
projectIndexByDirectory.put(rootPathCanon, projectInfoId);
|
projectIndexByDirectory.put(rootPathCanon, projectInfoId);
|
||||||
@ -91,16 +100,16 @@ public class DiscoverPhase implements DependencyPhase {
|
|||||||
public static Optional<PrometeuManifest> map(
|
public static Optional<PrometeuManifest> map(
|
||||||
final Path rootPath,
|
final Path rootPath,
|
||||||
final PrometeuManifestDTO dto,
|
final PrometeuManifestDTO dto,
|
||||||
final BuildingIssues issues) {
|
final BuildingIssueSink issues) {
|
||||||
|
|
||||||
if (StringUtils.isBlank(dto.name())) {
|
if (StringUtils.isBlank(dto.name())) {
|
||||||
issues.add(builder -> builder
|
issues.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("[DEPS]: manifest missing 'name': " + rootPath));
|
.message("[DEPS]: manifest missing 'name': " + rootPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isBlank(dto.version())) {
|
if (StringUtils.isBlank(dto.version())) {
|
||||||
issues.add(builder -> builder
|
issues.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("[DEPS]: manifest missing 'version': " + rootPath));
|
.message("[DEPS]: manifest missing 'version': " + rootPath));
|
||||||
}
|
}
|
||||||
@ -121,14 +130,14 @@ public class DiscoverPhase implements DependencyPhase {
|
|||||||
private static List<DependencyReference> resolveDependencies(
|
private static List<DependencyReference> resolveDependencies(
|
||||||
final Path rootProjectCanonPath,
|
final Path rootProjectCanonPath,
|
||||||
final List<PrometeuManifestDTO.DependencyDeclaration> dependencies,
|
final List<PrometeuManifestDTO.DependencyDeclaration> dependencies,
|
||||||
final BuildingIssues issues) {
|
final BuildingIssueSink issues) {
|
||||||
if (CollectionUtils.isEmpty(dependencies)) {
|
if (CollectionUtils.isEmpty(dependencies)) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
final var registryMaybe = RegistryStore.INSTANCE.load(rootProjectCanonPath);
|
final var registryMaybe = RegistryStore.INSTANCE.load(rootProjectCanonPath);
|
||||||
if (registryMaybe.isEmpty()) {
|
if (registryMaybe.isEmpty()) {
|
||||||
issues.add(builder -> builder
|
issues.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("[DEPS]: failed to load registry from " + rootProjectCanonPath));
|
.message("[DEPS]: failed to load registry from " + rootProjectCanonPath));
|
||||||
return List.of();
|
return List.of();
|
||||||
@ -148,7 +157,7 @@ public class DiscoverPhase implements DependencyPhase {
|
|||||||
final Path pathCanon = pathResolve.toRealPath();
|
final Path pathCanon = pathResolve.toRealPath();
|
||||||
deps.add(new DependencyReference(pathCanon));
|
deps.add(new DependencyReference(pathCanon));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
issues.add(builder -> builder
|
issues.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("[DEPS]: failed to canonicalize dependency path: " + pathResolve)
|
.message("[DEPS]: failed to canonicalize dependency path: " + pathResolve)
|
||||||
.exception(e));
|
.exception(e));
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package p.studio.compiler.workspaces.phases;
|
package p.studio.compiler.workspaces.phases;
|
||||||
|
|
||||||
import p.studio.compiler.messages.BuildingIssues;
|
import p.studio.compiler.messages.BuildingIssueSink;
|
||||||
import p.studio.compiler.models.DependencyContext;
|
import p.studio.compiler.models.DependencyContext;
|
||||||
import p.studio.compiler.workspaces.DependencyPhase;
|
import p.studio.compiler.workspaces.DependencyPhase;
|
||||||
|
|
||||||
@ -8,19 +8,19 @@ import java.io.IOException;
|
|||||||
|
|
||||||
public final class SeedPhase implements DependencyPhase {
|
public final class SeedPhase implements DependencyPhase {
|
||||||
@Override
|
@Override
|
||||||
public BuildingIssues run(final DependencyContext ctx) {
|
public BuildingIssueSink run(final DependencyContext ctx) {
|
||||||
try {
|
try {
|
||||||
ctx.mainProjectRootPathCanon = ctx.config().cacheDir().toRealPath();
|
ctx.mainProjectRootPathCanon = ctx.config.cacheDir().toRealPath();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return BuildingIssues.empty()
|
return BuildingIssueSink.empty()
|
||||||
.add(builder -> builder
|
.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("[DEPS]: failed to canonicalize rootProjectId directory: " + ctx.config().cacheDir())
|
.message("[DEPS]: failed to canonicalize rootProjectId directory: " + ctx.config.cacheDir())
|
||||||
.exception(e));
|
.exception(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.pending.add(ctx.mainProjectRootPathCanon);
|
ctx.pending.add(ctx.mainProjectRootPathCanon);
|
||||||
|
|
||||||
return BuildingIssues.empty();
|
return BuildingIssueSink.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package p.studio.compiler.workspaces.phases;
|
package p.studio.compiler.workspaces.phases;
|
||||||
|
|
||||||
import p.studio.compiler.messages.BuildingIssues;
|
import p.studio.compiler.messages.BuildingIssueSink;
|
||||||
import p.studio.compiler.models.BuildStack;
|
import p.studio.compiler.models.BuildStack;
|
||||||
import p.studio.compiler.models.DependencyContext;
|
import p.studio.compiler.models.DependencyContext;
|
||||||
import p.studio.compiler.models.ProjectInfoId;
|
import p.studio.compiler.models.ProjectInfoId;
|
||||||
@ -20,7 +20,7 @@ public final class StackPhase implements DependencyPhase {
|
|||||||
* Implements topological sort; detects dependency cycles; sets build stack
|
* Implements topological sort; detects dependency cycles; sets build stack
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public BuildingIssues run(final DependencyContext ctx) {
|
public BuildingIssueSink run(final DependencyContext ctx) {
|
||||||
final int n = ctx.projectTable.size();
|
final int n = ctx.projectTable.size();
|
||||||
final int[] indeg = new int[n];
|
final int[] indeg = new int[n];
|
||||||
for (int from = 0; from < n; from++) {
|
for (int from = 0; from < n; from++) {
|
||||||
@ -83,13 +83,13 @@ public final class StackPhase implements DependencyPhase {
|
|||||||
)
|
)
|
||||||
.collect(joining("\n"));
|
.collect(joining("\n"));
|
||||||
|
|
||||||
return BuildingIssues.empty()
|
return BuildingIssueSink.empty()
|
||||||
.add(builder -> builder.error(true).message(msg));
|
.report(builder -> builder.error(true).message(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.stack = new BuildStack(ReadOnlyList.wrap(travesalOrder));
|
ctx.stack = new BuildStack(ReadOnlyList.wrap(travesalOrder));
|
||||||
|
|
||||||
return BuildingIssues.empty();
|
return BuildingIssueSink.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class TarjanScc {
|
static final class TarjanScc {
|
||||||
|
|||||||
@ -1,24 +1,24 @@
|
|||||||
package p.studio.compiler.workspaces.phases;
|
package p.studio.compiler.workspaces.phases;
|
||||||
|
|
||||||
import p.studio.compiler.messages.BuildingIssues;
|
import p.studio.compiler.messages.BuildingIssueSink;
|
||||||
import p.studio.compiler.models.DependencyContext;
|
import p.studio.compiler.models.DependencyContext;
|
||||||
import p.studio.compiler.workspaces.DependencyPhase;
|
import p.studio.compiler.workspaces.DependencyPhase;
|
||||||
|
|
||||||
public final class ValidatePhase implements DependencyPhase {
|
public final class ValidatePhase implements DependencyPhase {
|
||||||
@Override
|
@Override
|
||||||
public BuildingIssues run(final DependencyContext ctx) {
|
public BuildingIssueSink run(final DependencyContext ctx) {
|
||||||
// ensure rootProjectId is set
|
// ensure rootProjectId is set
|
||||||
if (ctx.rootProjectId == null) {
|
if (ctx.rootProjectId == null) {
|
||||||
return BuildingIssues.empty()
|
return BuildingIssueSink.empty()
|
||||||
.add(builder -> builder
|
.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("[DEPS]: rootProjectId ProjectId not set"));
|
.message("[DEPS]: rootProjectId ProjectId not set"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure the dependenciesByProject matches the number of projectDescriptors
|
// ensure the dependenciesByProject matches the number of projectDescriptors
|
||||||
if (ctx.dependenciesByProject.size() != ctx.projectTable.size()) {
|
if (ctx.dependenciesByProject.size() != ctx.projectTable.size()) {
|
||||||
return BuildingIssues.empty()
|
return BuildingIssueSink.empty()
|
||||||
.add(builder -> builder
|
.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("[DEPS]: internal error: dependenciesByProject and projectDescriptors size mismatch"));
|
.message("[DEPS]: internal error: dependenciesByProject and projectDescriptors size mismatch"));
|
||||||
}
|
}
|
||||||
@ -28,8 +28,8 @@ public final class ValidatePhase implements DependencyPhase {
|
|||||||
final var name = entry.getKey();
|
final var name = entry.getKey();
|
||||||
final var versions = entry.getValue();
|
final var versions = entry.getValue();
|
||||||
if (versions.size() > 1) {
|
if (versions.size() > 1) {
|
||||||
return BuildingIssues.empty()
|
return BuildingIssueSink.empty()
|
||||||
.add(builder -> builder
|
.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("[DEPS]: inconsistent version for project: " + name + " (" + versions + ")"));
|
.message("[DEPS]: inconsistent version for project: " + name + " (" + versions + ")"));
|
||||||
}
|
}
|
||||||
@ -37,6 +37,6 @@ public final class ValidatePhase implements DependencyPhase {
|
|||||||
|
|
||||||
// run check over source policy (if any) from here (FrontedSpec)
|
// run check over source policy (if any) from here (FrontedSpec)
|
||||||
|
|
||||||
return BuildingIssues.empty();
|
return BuildingIssueSink.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package p.studio.compiler.workspaces.phases;
|
package p.studio.compiler.workspaces.phases;
|
||||||
|
|
||||||
import p.studio.compiler.messages.BuildingIssues;
|
import p.studio.compiler.messages.BuildingIssueSink;
|
||||||
import p.studio.compiler.models.DependencyContext;
|
import p.studio.compiler.models.DependencyContext;
|
||||||
import p.studio.compiler.models.ProjectDescriptor;
|
import p.studio.compiler.models.ProjectDescriptor;
|
||||||
import p.studio.compiler.models.ProjectInfo;
|
import p.studio.compiler.models.ProjectInfo;
|
||||||
@ -16,25 +16,25 @@ import java.util.List;
|
|||||||
|
|
||||||
public final class WireProjectsPhase implements DependencyPhase {
|
public final class WireProjectsPhase implements DependencyPhase {
|
||||||
@Override
|
@Override
|
||||||
public BuildingIssues run(final DependencyContext ctx) {
|
public BuildingIssueSink run(final DependencyContext ctx) {
|
||||||
// to start all over again, we will re-populate the project nodes and dependenciesByProjectId based on the project infos
|
// to start all over again, we will re-populate the project nodes and dependenciesByProjectId based on the project infos
|
||||||
ctx.rootProjectId = null;
|
ctx.rootProjectId = null;
|
||||||
ctx.projectIds.clear();
|
ctx.projectIds.clear();
|
||||||
ctx.projectTable.clear();
|
ctx.projectTable.clear();
|
||||||
ctx.dependenciesByProject.clear();
|
ctx.dependenciesByProject.clear();
|
||||||
|
|
||||||
final BuildingIssues issues = BuildingIssues.empty();
|
final BuildingIssueSink issues = BuildingIssueSink.empty();
|
||||||
|
|
||||||
for (int index = 0; index < ctx.projectInfoTable.size(); index++) {
|
for (int index = 0; index < ctx.projectInfoTable.size(); index++) {
|
||||||
final var projectInfo = ctx.projectInfoTable.get(new ProjectInfoId(index));
|
final var projectInfo = ctx.projectInfoTable.get(new ProjectInfoId(index));
|
||||||
final var projectDescriptor = buildProjectDescriptor(projectInfo, issues);
|
final var projectDescriptor = buildProjectDescriptor(ctx, projectInfo, issues);
|
||||||
final var projectId = ctx.projectTable.register(projectDescriptor);
|
final var projectId = ctx.projectTable.register(projectDescriptor);
|
||||||
ctx.projectIds.add(projectId);
|
ctx.projectIds.add(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
final var rootProjectId = ctx.projectTable.optionalId(ctx.mainProjectRootPathCanon);
|
final var rootProjectId = ctx.projectTable.optionalId(ctx.mainProjectRootPathCanon);
|
||||||
if (rootProjectId.isEmpty()) {
|
if (rootProjectId.isEmpty()) {
|
||||||
return issues.add(builder -> builder
|
return issues.report(builder -> builder
|
||||||
.message("[DEPS]: rootProjectId project dir " + ctx.mainProjectRootPathCanon + " was not discovered/materialized"));
|
.message("[DEPS]: rootProjectId project dir " + ctx.mainProjectRootPathCanon + " was not discovered/materialized"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ public final class WireProjectsPhase implements DependencyPhase {
|
|||||||
final var dependencyCanonPath = dependency.canonPath();
|
final var dependencyCanonPath = dependency.canonPath();
|
||||||
final var projectId = ctx.projectTable.optionalId(dependencyCanonPath);
|
final var projectId = ctx.projectTable.optionalId(dependencyCanonPath);
|
||||||
if (projectId.isEmpty()) {
|
if (projectId.isEmpty()) {
|
||||||
issues.add(builder -> builder
|
issues.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("[DEPS]: dependency not found: " + dependencyCanonPath));
|
.message("[DEPS]: dependency not found: " + dependencyCanonPath));
|
||||||
continue;
|
continue;
|
||||||
@ -63,25 +63,26 @@ public final class WireProjectsPhase implements DependencyPhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static ProjectDescriptor buildProjectDescriptor(
|
private static ProjectDescriptor buildProjectDescriptor(
|
||||||
|
final DependencyContext ctx,
|
||||||
final ProjectInfo projectInfo,
|
final ProjectInfo projectInfo,
|
||||||
final BuildingIssues issues) {
|
final BuildingIssueSink issues) {
|
||||||
final BuildingIssues sourceRootIssues = BuildingIssues.empty();
|
final BuildingIssueSink sourceRootIssues = BuildingIssueSink.empty();
|
||||||
final List<Path> sourceRoots = new ArrayList<>();
|
final List<Path> sourceRoots = new ArrayList<>();
|
||||||
for (final var sourceRoot : projectInfo.getFrontendSpec().getSourceRoots()) {
|
for (final var sourceRoot : ctx.frontendSpec.getSourceRoots()) {
|
||||||
final var sourceRootPath = projectInfo.rootDirectory.resolve(sourceRoot);
|
final var sourceRootPath = projectInfo.rootDirectory.resolve(sourceRoot);
|
||||||
try {
|
try {
|
||||||
final var sourceRootPathCanon = sourceRootPath.toRealPath();
|
final var sourceRootPathCanon = sourceRootPath.toRealPath();
|
||||||
sourceRoots.add(sourceRootPathCanon);
|
sourceRoots.add(sourceRootPathCanon);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
sourceRootIssues.add(builder -> builder
|
sourceRootIssues.report(builder -> builder
|
||||||
.error(true)
|
.error(true)
|
||||||
.message("[DEPS]: source project canonPath does not exist: " + sourceRootPath + " (from " + projectInfo.rootDirectory + ")")
|
.message("[DEPS]: source project canonPath does not exist: " + sourceRootPath + " (from " + projectInfo.rootDirectory + ")")
|
||||||
.exception(e));
|
.exception(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sourceRootIssues.size() == projectInfo.getFrontendSpec().getSourceRoots().size()) {
|
if (sourceRootIssues.size() == ctx.frontendSpec.getSourceRoots().size()) {
|
||||||
// no source roots were found at all
|
// no source roots were found at all
|
||||||
issues.add(sourceRootIssues);
|
issues.report(sourceRootIssues);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ProjectDescriptor
|
return ProjectDescriptor
|
||||||
@ -89,7 +90,6 @@ public final class WireProjectsPhase implements DependencyPhase {
|
|||||||
.rootPath(projectInfo.rootDirectory)
|
.rootPath(projectInfo.rootDirectory)
|
||||||
.name(projectInfo.manifest.name())
|
.name(projectInfo.manifest.name())
|
||||||
.version(projectInfo.manifest.version())
|
.version(projectInfo.manifest.version())
|
||||||
.frontendSpec(projectInfo.getFrontendSpec())
|
|
||||||
.sourceRoots(ReadOnlyList.wrap(sourceRoots))
|
.sourceRoots(ReadOnlyList.wrap(sourceRoots))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import java.util.Optional;
|
|||||||
|
|
||||||
public class FrontendRegistryService {
|
public class FrontendRegistryService {
|
||||||
private static final FrontendSpec[] FRONTEND_SPECS = {
|
private static final FrontendSpec[] FRONTEND_SPECS = {
|
||||||
PBSDefinitions.PBS,
|
PBSDefinitions.PBS,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final Map<String, FrontendSpec> FRONTENDS = new HashMap<>();
|
private static final Map<String, FrontendSpec> FRONTENDS = new HashMap<>();
|
||||||
@ -17,7 +17,8 @@ public class FrontendRegistryService {
|
|||||||
for (final var frontendSpec : FRONTEND_SPECS) {
|
for (final var frontendSpec : FRONTEND_SPECS) {
|
||||||
FRONTENDS.put(frontendSpec.getLanguageId(), frontendSpec);
|
FRONTENDS.put(frontendSpec.getLanguageId(), frontendSpec);
|
||||||
}
|
}
|
||||||
if (FRONTENDS.size() != FRONTEND_SPECS.length) throw new IllegalStateException("Duplicate frontend specs found");
|
if (FRONTENDS.size() != FRONTEND_SPECS.length)
|
||||||
|
throw new IllegalStateException("Duplicate frontend specs found");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FrontendSpec getDefaultFrontendSpec() {
|
public static FrontendSpec getDefaultFrontendSpec() {
|
||||||
@ -27,4 +28,4 @@ public class FrontendRegistryService {
|
|||||||
public static Optional<FrontendSpec> getFrontendSpec(final String languageId) {
|
public static Optional<FrontendSpec> getFrontendSpec(final String languageId) {
|
||||||
return Optional.ofNullable(FRONTENDS.get(languageId));
|
return Optional.ofNullable(FRONTENDS.get(languageId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user