Skip to content

Commit

Permalink
Merge pull request #4 from disneystreaming/limit-import-depth
Browse files Browse the repository at this point in the history
Fix default imports and add a test
  • Loading branch information
Baccata committed Nov 24, 2021
2 parents 79efba5 + 49f1171 commit d5d56d0
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 29 deletions.
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ repositories {
publishing {
publications {
mavenJava(MavenPublication) {
groupId = "com.disneystreaming.oss"
groupId = "com.disneystreaming.smithy"
artifactId = "smithy-language-server"

from components.java
Expand All @@ -73,6 +73,7 @@ dependencies {
implementation "org.eclipse.lsp4j:org.eclipse.lsp4j:0.9.0"
implementation "software.amazon.smithy:smithy-model:[1.0, 2.0["
implementation 'io.get-coursier:interface:1.0.4'


// Use JUnit test framework
testImplementation "junit:junit:4.13"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import java.net.URI;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
Expand Down Expand Up @@ -55,9 +55,9 @@

public class SmithyTextDocumentService implements TextDocumentService {

private List<CompletionItem> baseCompletions = new ArrayList<CompletionItem>();
private final List<CompletionItem> baseCompletions = new ArrayList<CompletionItem>();
private Optional<LanguageClient> client = Optional.empty();
private List<Location> noLocations = Arrays.asList();
private final List<Location> noLocations = Collections.emptyList();
private SmithyProject project;

/**
Expand Down Expand Up @@ -133,7 +133,7 @@ private String findToken(String path, Position p) throws IOException {
}

String line = contents.get(p.getLine());
Integer col = p.getCharacter();
int col = p.getCharacter();

String before = line.substring(0, col);
String after = line.substring(col, line.length());
Expand Down Expand Up @@ -187,11 +187,11 @@ public void didChange(DidChangeTextDocumentParams params) {
File tempFile = null;

try {
tempFile = File.createTempFile("smithy", ".smithy");
tempFile = File.createTempFile("smithy", SmithyProject.SMITHY_EXTENSION);

Files.write(tempFile.toPath(), params.getContentChanges().get(0).getText().getBytes());

} catch (Exception e) {
} catch (Exception ignored) {

}

Expand Down Expand Up @@ -242,13 +242,13 @@ public void recompile(File path, Optional<File> original) {
if (result.isBroken()) {
List<ValidationEvent> events = result.getValidationEvents();

List<Diagnostic> msgs = events.stream().map(ev -> ProtocolAdapter.toDiagnostic(ev))
List<Diagnostic> messages = events.stream().map(ProtocolAdapter::toDiagnostic)
.collect(Collectors.toList());
PublishDiagnosticsParams diagnostics = createDiagnostics(changedFileUri, msgs);
PublishDiagnosticsParams diagnostics = createDiagnostics(changedFileUri, messages);

cl.publishDiagnostics(diagnostics);
} else {
cl.publishDiagnostics(createDiagnostics(changedFileUri, Arrays.asList()));
cl.publishDiagnostics(createDiagnostics(changedFileUri, Collections.emptyList()));
}
}
});
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/software/amazon/smithy/lsp/ext/LspLog.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import software.amazon.smithy.utils.ListUtils;

/**
* This log interface buffers the messages until the server receives information
Expand All @@ -37,6 +39,23 @@ public final class LspLog {
private LspLog() {
}

/**
* Clears out the buffered messages.
*/
public static void clearBuffer() {
synchronized (buffer) {
buffer.ifPresent(c -> c.clear());
}
}

/**
* Produces a snapshot of the current log buffer.
* @return a copy of the messages currently in the buffer
*/
public static List<Object> getBuffer() {
return ListUtils.copyOf(buffer.orElse(Collections.emptyList()));
}

/**
* Sets workspace foler for the logger.
* <p>
Expand Down
54 changes: 35 additions & 19 deletions src/main/java/software/amazon/smithy/lsp/ext/SmithyProject.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,16 @@
import software.amazon.smithy.model.validation.ValidatedResult;

public final class SmithyProject {
private List<Path> imports;
private List<File> smithyFiles;
private List<File> externalJars;
// TODO: handle smithy json files
public static final String SMITHY_EXTENSION = ".smithy";

private final List<Path> imports;
private final List<File> smithyFiles;
private final List<File> externalJars;
private Map<String, List<Location>> locations = Collections.emptyMap();
private ValidatedResult<Model> model;
private File root;
private final File root;


private SmithyProject(List<Path> imports, List<File> smithyFiles, List<File> externalJars, File root,
ValidatedResult<Model> model) {
Expand All @@ -65,16 +69,20 @@ private SmithyProject(List<Path> imports, List<File> smithyFiles, List<File> ext
* @return either an error, or a loaded project
*/
public Either<Exception, SmithyProject> recompile(File file) {

// We aggressively re-build the model with only existing files
// it's simpler than trying to manage which file was added/removed/closed etc.
List<File> newFiles = new ArrayList<File>();
newFiles.addAll(onlyExistingFiles(this.smithyFiles));
List<File> newFiles = new ArrayList<File>(onlyExistingFiles(this.smithyFiles));

if (file.isFile()) {
newFiles.add(file);
}

return load(this.imports, this.smithyFiles, this.externalJars, this.root);
if (!newFiles.equals(this.smithyFiles)) {
LspLog.println("Recompilation changed the list of files: " + this.smithyFiles + " --> "
+ onlyExistingFiles(this.smithyFiles));
}
return load(this.imports, newFiles, this.externalJars, this.root);
}

public ValidatedResult<Model> getModel() {
Expand Down Expand Up @@ -109,7 +117,7 @@ public static Either<Exception, SmithyProject> load(SmithyBuildExtensions config
List<Path> imports = config.getImports().stream().map(p -> Paths.get(root.getAbsolutePath(), p).normalize())
.collect(Collectors.toList());

if (!imports.contains(Paths.get("."))) {
if (imports.isEmpty()) {
imports.add(root.toPath());
}

Expand Down Expand Up @@ -172,21 +180,29 @@ private static Map<String, List<Location>> collectLocations(Model model) {
return locations;
}

private static Boolean isValidSmithyFile(Path file) {
String fName = file.getFileName().toString();
return fName.endsWith(SMITHY_EXTENSION);
}

private static List<File> walkSmithyFolder(Path path, File root) {

try (Stream<Path> walk = Files.walk(path)) {
return walk.filter(Files::isRegularFile).filter(SmithyProject::isValidSmithyFile).map(Path::toFile)
.collect(Collectors.toList());
} catch (IOException e) {
LspLog.println("Failed to walk import '" + path + "' from root " + root + ": " + e);
return new ArrayList<>();
}
}

private static List<File> discoverSmithyFiles(List<Path> imports, File root) {
List<File> smithyFiles = new ArrayList<>();

imports.forEach(path -> {
if (Files.isDirectory(path)) {

try (Stream<Path> walk = Files.walk(path)) {
smithyFiles.addAll(walk.filter(Files::isRegularFile).filter(p -> {
String fName = p.getFileName().toString();
return fName.endsWith(".smithy");
}).map(f -> f.toFile()).collect(Collectors.toList()));
} catch (IOException e) {
LspLog.println("Failed to walk import '" + path + "' from root " + root + ": " + e);
}
} else if (path.getFileName().toString().endsWith(".smithy")) {
smithyFiles.addAll(walkSmithyFolder(path, root));
} else if (isValidSmithyFile(path)) {
smithyFiles.add(path.resolve(root.toPath()).toFile());
}
});
Expand All @@ -203,6 +219,6 @@ private static List<File> downloadExternalDependencies(SmithyBuildExtensions ext
}

private static List<File> onlyExistingFiles(Collection<File> files) {
return files.stream().filter(f -> f.isFile()).collect(Collectors.toList());
return files.stream().filter(File::isFile).collect(Collectors.toList());
}
}
84 changes: 84 additions & 0 deletions src/test/java/software/amazon/smithy/lsp/ext/Harness.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package software.amazon.smithy.lsp.ext;

import java.io.File;
import java.io.FileWriter;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Map.Entry;

import com.google.common.io.Files;

import org.eclipse.lsp4j.jsonrpc.messages.Either;

public class Harness implements AutoCloseable {
private File root;
private SmithyProject project;

private Harness(File root, SmithyProject project) {
this.root = root;
this.project = project;
}

public File getRoot() {
return this.root;
}

public SmithyProject getProject() {
return this.project;
}

private static File safeCreateFile(String path, String contents, File root) throws Exception {
File f = Paths.get(root.getAbsolutePath(), path).toFile();
new File(f.getParent()).mkdirs();
try (FileWriter fw = new FileWriter(f)) {
fw.write(contents);
fw.flush();
}

return f;
}

public File addFile(String path, String contents) throws Exception {
File f = safeCreateFile(path, contents, this.root);
Either<Exception, SmithyProject> loaded = this.project.recompile(f);
if (loaded.isRight())
this.project = loaded.getRight();
else
throw loaded.getLeft();

return f;
}

public File file(String path) throws Exception {
return Paths.get(root.getAbsolutePath(), path).toFile();
}

@Override
public void close() throws Exception {
root.deleteOnExit();
}

public static Harness create(SmithyBuildExtensions ext) throws Exception {
// TODO: How to make this safe?
File hs = Files.createTempDir();
Either<Exception, SmithyProject> loaded = SmithyProject.load(ext, hs);
if (loaded.isRight())
return new Harness(hs, loaded.getRight());
else
throw loaded.getLeft();
}

public static Harness create(SmithyBuildExtensions ext, Map<String, String> files) throws Exception {
// TODO: How to make this safe?
File hs = Files.createTempDir();
for (Entry<String, String> entry : files.entrySet()) {
safeCreateFile(entry.getKey(), entry.getValue(), hs);
}
Either<Exception, SmithyProject> loaded = SmithyProject.load(ext, hs);
if (loaded.isRight())
return new Harness(hs, loaded.getRight());
else
throw loaded.getLeft();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package software.amazon.smithy.lsp.ext;

import static org.junit.Assert.assertEquals;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.junit.Test;

import software.amazon.smithy.utils.ListUtils;
import software.amazon.smithy.utils.MapUtils;

public class SmithyProjectTest {

final Path DUMMY_PATH = Paths.get("smithy-build.json");

@Test
public void walkingImports() throws Exception {
List<String> imports = Arrays.asList("bla", "foo");
Map<String, String> files = MapUtils.ofEntries(MapUtils.entry("test.smithy", "namespace testRoot"),
MapUtils.entry("bar/test.smithy", "namespace testBar"),
MapUtils.entry("foo/test.smithy", "namespace testFoo"),
MapUtils.entry("bla/test.smithy", "namespace testBla"));

try (Harness hs = Harness.create(SmithyBuildExtensions.builder().imports(imports).build(), files)) {
File inFoo = hs.file("foo/test.smithy");
File inBla = hs.file("bla/test.smithy");

List<File> smithyFiles = hs.getProject().getSmithyFiles();

assertEquals(ListUtils.of(inBla, inFoo), smithyFiles);
}

}
}

0 comments on commit d5d56d0

Please sign in to comment.