Skip to content
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
22 changes: 3 additions & 19 deletions server/src/main/java/LJDiagnosticsHandler.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand All @@ -17,10 +16,10 @@
import liquidjava.diagnostics.LJDiagnostic;
import liquidjava.diagnostics.errors.LJError;
import liquidjava.diagnostics.warnings.LJWarning;
import utils.PathUtils;

public class LJDiagnosticsHandler {

private static final String FILE_PREFIX = "file://";
private static final String SOURCE = "liquidjava";

/**
Expand All @@ -29,7 +28,7 @@ public class LJDiagnosticsHandler {
* @param path the file path
* @return LJDiagnostics
*/
public static LJDiagnostics getLJDiagnostics(String uri, String path) {
public static LJDiagnostics getLJDiagnostics(String path) {
List<LJError> errors = new ArrayList<>();
List<LJWarning> warnings = new ArrayList<>();

Expand Down Expand Up @@ -69,7 +68,7 @@ public static List<PublishDiagnosticsParams> getDiagnostics(List<LJDiagnostic> d
// group diagnostics by file
Map<String, List<Diagnostic>> diagnosticsByFile = diagnostics.stream()
.collect(Collectors.groupingBy(
d -> toFileUri(d.getFile()),
d -> PathUtils.toFileUri(d.getFile()),
Collectors.mapping(d -> {
Range range = getRangeFromErrorPosition(d.getPosition());
String message = String.format("%s: %s", d.getTitle(), d.getMessage());
Expand All @@ -83,21 +82,6 @@ public static List<PublishDiagnosticsParams> getDiagnostics(List<LJDiagnostic> d
.toList();
}

/**
* Converts a file path to a file:// URI
* @param filePath the file path
* @return the file URI
*/
private static String toFileUri(String filePath) {
String normalized = filePath.replace("\\", "/");
// Windows (C:/path)
if (!normalized.isEmpty() && normalized.charAt(1) == ':') {
return FILE_PREFIX + "/" + normalized;
}
// Unix (/path)
return FILE_PREFIX + normalized;
}

/**
* Generates empty diagnostics for the given URI
* @param uri the uri used for the verification
Expand Down
47 changes: 10 additions & 37 deletions server/src/main/java/LJDiagnosticsService.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import java.io.File;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand All @@ -18,38 +16,27 @@

import dtos.DiagnosticConverter;
import liquidjava.diagnostics.LJDiagnostic;
import utils.PathUtils;

public class LJDiagnosticsService implements TextDocumentService, WorkspaceService {

private LJLanguageClient client;
private String sourcePath;
private String workspaceRoot;

/**
* Sets the language client
* @param client the language client
*/
public void setClient(LJLanguageClient client) {
this.client = client;
}

/**
* Sets the source path
* Uses workspaceRoot + "/src/main/java" if it exists, otherwise uses workspaceRoot
* @param workspaceRoot the workspace root URI
*/
public void setSourcePath(String workspaceRoot) {
Path workspaceRootPath = Paths.get(URI.create(workspaceRoot));
Path srcMainJava = workspaceRootPath.resolve("src/main/java");
this.sourcePath = srcMainJava.toFile().isDirectory() ? srcMainJava.toString() : workspaceRootPath.toString();
public void setWorkspaceRoot(String workspaceRoot) {
this.workspaceRoot = workspaceRoot;
}

/**
* Sends diagnostics notification to the client
* @param diagnostics the diagnostics to send
*/
public void sendDiagnosticsNotification(List<LJDiagnostic> diagnostics) {
if (this.client == null)
return;
if (this.client == null) return;

System.out.println("Sending diagnostics notification with " + diagnostics.size() + " diagnostics");
List<Object> dtos = diagnostics.stream()
Expand All @@ -63,7 +50,8 @@ public void sendDiagnosticsNotification(List<LJDiagnostic> diagnostics) {
* @param uri the URI of the document
*/
public void generateDiagnostics(String uri) {
LJDiagnostics ljDiagnostics = LJDiagnosticsHandler.getLJDiagnostics(uri, sourcePath);
String path = PathUtils.extractBasePath(uri);
LJDiagnostics ljDiagnostics = LJDiagnosticsHandler.getLJDiagnostics(path);
List<PublishDiagnosticsParams> nativeDiagnostics = LJDiagnosticsHandler.getNativeDiagnostics(ljDiagnostics, uri);
nativeDiagnostics.forEach(params -> {
this.client.publishDiagnostics(params);
Expand All @@ -72,21 +60,6 @@ public void generateDiagnostics(String uri) {
sendDiagnosticsNotification(diagnostics);
}

/**
* Checks if a file URI is within the source path
* @param uri the file URI
* @return true if the file is within sourcePath, false otherwise
*/
private boolean isFileInSourcePath(String uri) {
try {
Path filePath = Paths.get(new URI(uri));
Path sourcePathObj = Paths.get(sourcePath);
return filePath.startsWith(sourcePathObj);
} catch (Exception e) {
return false;
}
}

/**
* Clear a diagnostic for a specific URI
* @param uri the URI of the document
Expand All @@ -104,7 +77,7 @@ public void clearDiagnostic(String uri) {
@Override
public void didOpen(DidOpenTextDocumentParams params) {
String uri = params.getTextDocument().getUri();
if (!isFileInSourcePath(uri)) return;
if (!PathUtils.isFileInDirectory(uri, workspaceRoot)) return;
System.out.println("Document opened — checking diagnostics");
generateDiagnostics(uri);
}
Expand All @@ -116,7 +89,7 @@ public void didOpen(DidOpenTextDocumentParams params) {
@Override
public void didSave(DidSaveTextDocumentParams params) {
String uri = params.getTextDocument().getUri();
if (!isFileInSourcePath(uri)) return;
if (!PathUtils.isFileInDirectory(uri, workspaceRoot)) return;
System.out.println("Document saved — checking diagnostics");
clearDiagnostic(uri);
generateDiagnostics(uri);
Expand All @@ -129,7 +102,7 @@ public void didSave(DidSaveTextDocumentParams params) {
@Override
public void didClose(DidCloseTextDocumentParams params) {
String uri = params.getTextDocument().getUri();
if (!isFileInSourcePath(uri)) return;
if (!PathUtils.isFileInDirectory(uri, workspaceRoot)) return;
try {
// check if the file still exists on disk
File file = new File(new URI(uri));
Expand Down
2 changes: 1 addition & 1 deletion server/src/main/java/LJLanguageServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
// extract workspace root from initialization params
if (params.getWorkspaceFolders() != null && !params.getWorkspaceFolders().isEmpty()) {
String workspaceRoot = params.getWorkspaceFolders().get(0).getUri();
diagnosticsService.setSourcePath(workspaceRoot);
diagnosticsService.setWorkspaceRoot(workspaceRoot);
}

// set options
Expand Down
59 changes: 59 additions & 0 deletions server/src/main/java/utils/PathUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package utils;

import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
* Utility class for path operations
*/
public class PathUtils {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets explain why we need this class, is mostly for handling paths for different OS and find the directories where liquidjava should be used right?

private static final String FILE_PREFIX = "file://";
private static final String SRC_SUFFIX = "/src/";

/**
* Checks if a file is in a given directory
* @param fileUri the file URI
* @param directoryUri the directory URI
* @return true if the file is in the directory, false otherwise
*/
public static boolean isFileInDirectory(String fileUri, String directoryUri) {
try {
Path filePath = Paths.get(new URI(fileUri));
Path directoryPath = Paths.get(new URI(directoryUri));
return filePath.startsWith(directoryPath);
} catch (Exception e) {
return false;
}
}

/**
* Extracts the base path from the given full path
* e.g. file://path/to/project/src/main/path/to/File.java => /path/to/project/src/main
* @param fullPath the full path
* @return base path
*/
public static String extractBasePath(String fullPath) {
fullPath = fullPath.replace(FILE_PREFIX, "");
int suffixIndex = fullPath.indexOf(SRC_SUFFIX);
int nextSlashIndex = fullPath.indexOf("/", suffixIndex + SRC_SUFFIX.length());
if (suffixIndex == -1 || nextSlashIndex == -1)
return fullPath; // cannot extract base path
return fullPath.substring(0, nextSlashIndex); // up to and including the next slash after /src/
}

/**
* Converts a file path to a file:// URI
* @param filePath the file path
* @return the file URI
*/
public static String toFileUri(String filePath) {
String normalized = filePath.replace("\\", "/");
// Windows (C:/path)
if (!normalized.isEmpty() && normalized.charAt(1) == ':') {
return FILE_PREFIX + "/" + normalized;
}
// Unix (/path)
return FILE_PREFIX + normalized;
}
}