Skip to content

Commit

Permalink
Refactor Project to have its ProjectConfig
Browse files Browse the repository at this point in the history
Also adds some test cases for moving around detached and/or broken
files.
  • Loading branch information
milesziemer committed Jun 9, 2024
1 parent 5862d57 commit c9193ad
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 45 deletions.
50 changes: 19 additions & 31 deletions src/main/java/software/amazon/smithy/lsp/project/Project.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
public final class Project {
private static final Logger LOGGER = Logger.getLogger(Project.class.getName());
private final Path root;
private final List<Path> sources;
private final List<Path> imports;
private final ProjectConfig config;
private final List<Path> dependencies;
private final Map<String, SmithyFile> smithyFiles;
private final Supplier<ModelAssembler> assemblerFactory;
Expand All @@ -45,8 +44,7 @@ public final class Project {

private Project(Builder builder) {
this.root = Objects.requireNonNull(builder.root);
this.sources = builder.sources;
this.imports = builder.imports;
this.config = Objects.requireNonNull(builder.config);
this.dependencies = builder.dependencies;
this.smithyFiles = builder.smithyFiles;
this.modelResult = builder.modelResult;
Expand Down Expand Up @@ -75,19 +73,27 @@ public Path getRoot() {
}

/**
* @return The paths of all Smithy sources, exactly as they were specified
* in this project's smithy build configuration files
* @return The paths of all Smithy sources specified
* in this project's smithy build configuration files,
* normalized and resolved against {@link #getRoot()}.
*/
public List<Path> getSources() {
return sources;
return config.getSources().stream()
.map(root::resolve)
.map(Path::normalize)
.collect(Collectors.toList());
}

/**
* @return The paths of all imports, exactly as they were specified in this
* project's smithy build configuration files
* @return The paths of all Smithy imports specified
* in this project's smithy build configuration files,
* normalized and resolved against {@link #getRoot()}.
*/
public List<Path> getImports() {
return imports;
return config.getImports().stream()
.map(root::resolve)
.map(Path::normalize)
.collect(Collectors.toList());
}

/**
Expand Down Expand Up @@ -309,8 +315,7 @@ static Builder builder() {

static final class Builder {
private Path root;
private final List<Path> sources = new ArrayList<>();
private final List<Path> imports = new ArrayList<>();
private ProjectConfig config;
private final List<Path> dependencies = new ArrayList<>();
private final Map<String, SmithyFile> smithyFiles = new HashMap<>();
private ValidatedResult<Model> modelResult;
Expand All @@ -325,25 +330,8 @@ public Builder root(Path root) {
return this;
}

public Builder sources(List<Path> paths) {
this.sources.clear();
this.sources.addAll(paths);
return this;
}

public Builder addSource(Path path) {
this.sources.add(path);
return this;
}

public Builder imports(List<Path> paths) {
this.imports.clear();
this.imports.addAll(paths);
return this;
}

public Builder addImport(Path path) {
this.imports.add(path);
public Builder config(ProjectConfig config) {
this.config = config;
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ private ProjectLoader() {
* Loads a detached (single-file) {@link Project} with the given file.
*
* <p>Unlike {@link #load(Path, ProjectManager, Set)}, this method isn't
* fallible since it doesn't do any IO.
* fallible since it doesn't do any IO that we would want to recover an
* error from.
*
* @param uri URI of the file to load into a project
* @param text Text of the file to load into a project
Expand All @@ -75,7 +76,9 @@ public static Project loadDetached(String uri, String text) {

Project.Builder builder = Project.builder()
.root(path.getParent())
.sources(sources)
.config(ProjectConfig.builder()
.sources(Collections.singletonList(asPath))
.build())
.modelResult(modelResult);

Map<String, SmithyFile> smithyFiles = computeSmithyFiles(sources, modelResult, (filePath) -> {
Expand Down Expand Up @@ -176,19 +179,9 @@ public static Result<Project, List<Exception>> load(

ValidatedResult<Model> modelResult = loadModelResult.unwrap();

List<Path> sources = config.getSources().stream()
.map(root::resolve)
.map(Path::normalize)
.collect(Collectors.toList());
List<Path> imports = config.getImports().stream()
.map(root::resolve)
.map(Path::normalize)
.collect(Collectors.toList());

Project.Builder projectBuilder = Project.builder()
.root(root)
.sources(sources)
.imports(imports)
.config(config)
.dependencies(dependencies)
.modelResult(modelResult)
.assemblerFactory(assemblerFactory);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
import static software.amazon.smithy.lsp.LspMatchers.hasText;
import static software.amazon.smithy.lsp.LspMatchers.makesEditedDocument;
import static software.amazon.smithy.lsp.SmithyMatchers.eventWithMessage;
import static software.amazon.smithy.lsp.SmithyMatchers.hasValue;
import static software.amazon.smithy.lsp.SmithyMatchers.hasShapeWithId;
import static software.amazon.smithy.lsp.SmithyMatchers.hasShapeWithIdAndTraits;
import static software.amazon.smithy.lsp.SmithyMatchers.hasValue;

import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
Expand Down Expand Up @@ -1202,6 +1202,45 @@ public void addingOpenedDetachedFile() throws Exception {
assertThat(server.getProject().getModelResult().unwrap(), hasShapeWithId("com.foo#Bar"));
}

@Test
public void detachingOpenedFile() throws Exception {
String modelText = "$version: \"2\"\n"
+ "namespace com.foo\n"
+ "string Foo\n";
TestWorkspace workspace = TestWorkspace.singleModel(modelText);
SmithyLanguageServer server = initFromWorkspace(workspace);

String uri = workspace.getUri("main.smithy");

server.didOpen(RequestBuilders.didOpen()
.uri(uri)
.text(modelText)
.build());
server.didChange(RequestBuilders.didChange()
.uri(uri)
.range(RangeAdapter.point(3, 0))
.text("string Bar\n")
.build());

workspace.updateConfig(workspace.getConfig()
.toBuilder()
.sources(new ArrayList<>())
.build());

server.didChangeWatchedFiles(RequestBuilders.didChangeWatchedFiles()
.event(workspace.getUri("smithy-build.json"), FileChangeType.Changed)
.build());

server.getLifecycleManager().waitForAllTasks();

assertThat(server.getLifecycleManager().getManagedDocuments(), hasItem(uri));
assertThat(server.getProjects().isDetached(uri), is(true));
assertThat(server.getProjects().getProject(uri), notNullValue());
assertThat(server.getProjects().getProject(uri).getSmithyFile(uri), notNullValue());
assertThat(server.getProjects().getProject(uri).getModelResult(), hasValue(hasShapeWithId("com.foo#Foo")));
assertThat(server.getProjects().getProject(uri).getModelResult(), hasValue(hasShapeWithId("com.foo#Bar")));
}

@Test
public void movingDetachedFile() throws Exception {
TestWorkspace workspace = TestWorkspace.emptyWithDirSource();
Expand Down Expand Up @@ -1356,6 +1395,62 @@ public void invalidSyntaxDetachedProjectBecomesValid() throws Exception {
assertThat(server.getProjects().getProject(uri).getModelResult().unwrap(), hasShapeWithId("com.foo#Foo"));
}

@Test
public void addingDetachedFileWithInvalidSyntax() throws Exception {
TestWorkspace workspace = TestWorkspace.emptyWithDirSource();
SmithyLanguageServer server = initFromWorkspace(workspace);

String filename = "main.smithy";
workspace.addModel(filename, "");

String uri = workspace.getUri(filename);

server.didOpen(RequestBuilders.didOpen()
.uri(uri)
.text("")
.build());

server.getLifecycleManager().waitForAllTasks();

assertThat(server.getProjects().isDetached(uri), is(true));
assertThat(server.getProjects().getProject(uri), notNullValue());
assertThat(server.getProjects().getProject(uri).getSmithyFile(uri), notNullValue());

List<String> updatedSources = new ArrayList<>(workspace.getConfig().getSources());
updatedSources.add(filename);
workspace.updateConfig(workspace.getConfig()
.toBuilder()
.sources(updatedSources)
.build());

server.didChangeWatchedFiles(RequestBuilders.didChangeWatchedFiles()
.event(workspace.getUri("smithy-build.json"), FileChangeType.Changed)
.build());

server.didChange(RequestBuilders.didChange()
.uri(uri)
.text("$version: \"2\"\n")
.range(RangeAdapter.origin())
.build());
server.didChange(RequestBuilders.didChange()
.uri(uri)
.text("namespace com.foo\n")
.range(RangeAdapter.point(1, 0))
.build());
server.didChange(RequestBuilders.didChange()
.uri(uri)
.text("string Foo\n")
.range(RangeAdapter.point(2, 0))
.build());

server.getLifecycleManager().waitForAllTasks();

assertThat(server.getProjects().isDetached(uri), is(false));
assertThat(server.getProjects().getDetachedProjects().keySet(), empty());
assertThat(server.getProject().getSmithyFile(uri), notNullValue());
assertThat(server.getProject().getModelResult(), hasValue(hasShapeWithId("com.foo#Foo")));
}

@Test
@Disabled
public void todoCheckApplysInPartialLoad() throws Exception {
Expand Down

0 comments on commit c9193ad

Please sign in to comment.