Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix rebuilding when SourceLocation is NONE #196

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions src/main/java/software/amazon/smithy/lsp/project/Project.java
Original file line number Diff line number Diff line change
Expand Up @@ -345,13 +345,15 @@ private void removeFileForReload(
// those traits.

// This shape's dependencies files will be removed and re-loaded
this.rebuildIndex.getDependenciesFiles(toShapeId).forEach((depPath) ->
removeFileForReload(assembler, builder, depPath, visited));
for (String depPath : this.rebuildIndex.getDependenciesFiles(toShapeId)) {
removeFileForReload(assembler, builder, depPath, visited);
}

// Traits applied in other files are re-added to the assembler so if/when the shape
// is reloaded, it will have those traits
this.rebuildIndex.getTraitsAppliedInOtherFiles(toShapeId).forEach((trait) ->
assembler.addTrait(toShapeId.toShapeId(), trait));
for (Trait trait : this.rebuildIndex.getTraitsAppliedInOtherFiles(toShapeId)) {
assembler.addTrait(toShapeId.toShapeId(), trait);
}
}
}

Expand Down Expand Up @@ -507,8 +509,9 @@ RebuildIndex recompute(ValidatedResult<Model> modelResult) {
Node traitNode = traitApplication.toNode();
if (traitNode.isArrayNode()) {
for (Node element : traitNode.expectArrayNode()) {
String elementSourceFilename = element.getSourceLocation().getFilename();
if (!elementSourceFilename.equals(shapeSourceFilename)) {
SourceLocation elementSourceLocation = element.getSourceLocation();
String elementSourceFilename = elementSourceLocation.getFilename();
if (!isNone(elementSourceLocation) && !elementSourceFilename.equals(shapeSourceFilename)) {
newIndex.filesToDependentFiles
.computeIfAbsent(elementSourceFilename, (f) -> new HashSet<>())
.add(shapeSourceFilename);
Expand All @@ -518,8 +521,9 @@ RebuildIndex recompute(ValidatedResult<Model> modelResult) {
}
}
} else {
String traitSourceFilename = traitApplication.getSourceLocation().getFilename();
if (!traitSourceFilename.equals(shapeSourceFilename)) {
SourceLocation traitSourceLocation = traitNode.getSourceLocation();
String traitSourceFilename = traitSourceLocation.getFilename();
if (!isNone(traitSourceLocation) && !traitSourceFilename.equals(shapeSourceFilename)) {
newIndex.shapesToAppliedTraitsInOtherFiles
.computeIfAbsent(shape.getId(), (i) -> new ArrayList<>())
.add(traitApplication);
Expand All @@ -534,5 +538,9 @@ RebuildIndex recompute(ValidatedResult<Model> modelResult) {

return newIndex;
}

private static boolean isNone(SourceLocation sourceLocation) {
return sourceLocation.equals(SourceLocation.NONE);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,32 @@
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.empty;
import static software.amazon.smithy.lsp.UtilMatchers.anOptionalOf;

import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
import software.amazon.smithy.lsp.ServerState;
import software.amazon.smithy.lsp.SmithyMatchers;
import software.amazon.smithy.lsp.TestWorkspace;
import software.amazon.smithy.lsp.document.Document;
import software.amazon.smithy.lsp.protocol.LspAdapter;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.SourceLocation;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.shapes.StringShape;
import software.amazon.smithy.model.traits.LengthTrait;
import software.amazon.smithy.model.traits.PatternTrait;
import software.amazon.smithy.model.traits.TagsTrait;
import software.amazon.smithy.model.validation.ValidatedResult;

public class ProjectTest {
@Test
Expand Down Expand Up @@ -426,6 +435,56 @@ public void loadsEmptyProjectWhenThereAreNoConfigFiles() throws Exception {
assertThat(project.type(), equalTo(Project.Type.EMPTY));
}

@Test
public void changingTraitWithSourceLocationNone() {
// Manually construct a Project with a model containing a trait with SourceLocation.NONE,
// since this test can't rely on any specific trait always having SourceLocation.NONE, as
// it may be fixed upstream.
Path root = Path.of("foo").toAbsolutePath();
String fooPath = root.resolve("foo.smithy").toString();
SmithyFile fooSmithyFile = SmithyFile.create(fooPath, Document.of("""
$version: "2"
namespace com.foo
@length(max: 10)
string Foo
"""));
Map<String, SmithyFile> smithyFiles = new HashMap<>();
smithyFiles.put(fooPath, fooSmithyFile);
Model model = Model.builder()
.addShape(StringShape.builder()
.id("com.foo#Foo")
.source(fooPath, 4, 1)
.addTrait(LengthTrait.builder()
.sourceLocation(SourceLocation.NONE)
.min(1L)
.build())
.build())
.build();
ValidatedResult<Model> modelResult = ValidatedResult.fromValue(model);
Project.RebuildIndex rebuildIndex = Project.RebuildIndex.create(modelResult);

Project project = new Project(
root,
ProjectConfig.empty(),
BuildFiles.of(List.of()),
smithyFiles,
Model::assembler,
Project.Type.DETACHED,
modelResult,
rebuildIndex,
List.of()
);

assertThat(project.modelResult(), SmithyMatchers.hasValue(SmithyMatchers.hasShapeWithId("com.foo#Foo")));
assertThat(project.modelResult().getValidationEvents(), empty());

String fooUri = LspAdapter.toUri(fooPath);
project.updateModelWithoutValidating(fooUri);

assertThat(project.modelResult(), SmithyMatchers.hasValue(SmithyMatchers.hasShapeWithId("com.foo#Foo")));
assertThat(project.modelResult().getValidationEvents(), empty());
}

public static Project load(Path root) {
try {
return ProjectLoader.load(root, new ServerState());
Expand Down