Skip to content

Commit

Permalink
Added asynchrone Eclipse workspace validation.
Browse files Browse the repository at this point in the history
  • Loading branch information
ylussaud committed Dec 20, 2023
1 parent 8694fbb commit 356e9f4
Show file tree
Hide file tree
Showing 12 changed files with 214 additions and 79 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2020 Obeo.
* Copyright (c) 2020, 2023 Obeo.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand All @@ -16,7 +16,7 @@
import java.net.InetAddress;
import java.net.Socket;

import org.eclipse.acceleo.aql.ls.AcceleoLanguageServerContext;
import org.eclipse.acceleo.aql.ls.IAcceleoLanguageServerContext;
import org.eclipse.acceleo.aql.ls.AcceleoSocketServer;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.lsp4e.server.StreamConnectionProvider;
Expand Down Expand Up @@ -48,7 +48,7 @@ public class AcceleoConnectionProvider implements StreamConnectionProvider {
* Constructor.
*/
public AcceleoConnectionProvider() {
AcceleoLanguageServerContext acceleoContext = new EclipseAcceleoLanguageServerContext(ResourcesPlugin
IAcceleoLanguageServerContext acceleoContext = new EclipseAcceleoLanguageServerContext(ResourcesPlugin
.getWorkspace());
this.acceleoSocketServer = new AcceleoSocketServer(acceleoContext);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import java.util.Objects;

import org.eclipse.acceleo.aql.ide.AcceleoPlugin;
import org.eclipse.acceleo.aql.ls.AcceleoLanguageServerContext;
import org.eclipse.acceleo.aql.ls.IAcceleoLanguageServerContext;
import org.eclipse.acceleo.aql.ls.services.workspace.AcceleoProject;
import org.eclipse.acceleo.aql.ls.services.workspace.AcceleoWorkspace;
import org.eclipse.acceleo.aql.parser.AcceleoParser;
Expand All @@ -38,11 +38,11 @@
import org.eclipse.core.runtime.Status;

/**
* Eclipse-specific implementation of {@link AcceleoLanguageServerContext}.
* Eclipse-specific implementation of {@link IAcceleoLanguageServerContext}.
*
* @author Florent Latombe
*/
public class EclipseAcceleoLanguageServerContext implements AcceleoLanguageServerContext {
public class EclipseAcceleoLanguageServerContext implements IAcceleoLanguageServerContext {

/**
* the {@link Synchronizer} for Acceleo.
Expand Down Expand Up @@ -131,6 +131,28 @@ public String getResourceContents(URI resource) {
return null;
}

@Override
public AcceleoProject getProject(AcceleoWorkspace workspace, URI resource) {
final AcceleoProject res;

final AcceleSynchronizer synchoniser = synchronizers.get(workspace);
synchronized(synchoniser) {

final IFile file = clientWorkspace.getRoot().getFileForLocation(new Path(resource.getPath()
.toString()));
final IProject eclipseProject = file.getProject();
final AcceleoProject existingProject = synchoniser.getProject(eclipseProject);
if (existingProject != null) {
res = existingProject;
} else {
synchoniser.add(file.getProject());
res = synchoniser.getProject(eclipseProject);
}
}

return res;
}

@Override
public IQueryWorkspaceQualifiedNameResolver createResolver(AcceleoProject acceleoProject) {
Objects.nonNull(acceleoProject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ public class AcceleoLanguageServer implements LanguageServer, LanguageClientAwar
private final AcceleoWorkspaceService workspaceService;

/**
* The root {@link AcceleoLanguageServerContext} of this server.
* The root {@link IAcceleoLanguageServerContext} of this server.
*/
private final AcceleoLanguageServerContext acceleoLanguageServerContext;
private final IAcceleoLanguageServerContext acceleoLanguageServerContext;

/**
* The {@link Instant} at which this server was created.
Expand All @@ -68,9 +68,9 @@ public class AcceleoLanguageServer implements LanguageServer, LanguageClientAwar
* Creates a new {@link AcceleoLanguageServer}.
*
* @param acceleoLanguageServerContext
* the (non-{@code null}) root {@link AcceleoLanguageServerContext} for this server.
* the (non-{@code null}) root {@link IAcceleoLanguageServerContext} for this server.
*/
public AcceleoLanguageServer(AcceleoLanguageServerContext acceleoLanguageServerContext) {
public AcceleoLanguageServer(IAcceleoLanguageServerContext acceleoLanguageServerContext) {
this.creationTimestamp = Instant.now();
this.acceleoLanguageServerContext = Objects.requireNonNull(acceleoLanguageServerContext);

Expand Down Expand Up @@ -99,12 +99,12 @@ public AcceleoWorkspace createWorkspace() {
}

/**
* Valides all {@link AcceleoTextDocument} in the workspace of this server.
* Publishes all {@link AcceleoTextDocument} validation result in the workspace of this server.
*/
private void validateAll() {
private void publishAll() {
if (this.getWorkspace() != null) {
this.getWorkspace().getAllTextDocuments().forEach(textDocument -> textDocument
.validateAndPublishResults());
this.getWorkspace().getAllTextDocuments().forEach(textDocument -> textDocumentService
.publishValidationResults(textDocument));
}
}

Expand All @@ -116,7 +116,7 @@ public void connect(LanguageClient newLanguageClient) {

// The client just changed, re-validate all documents so they publish the validation results to the
// client.
this.validateAll();
this.publishAll();

newLanguageClient.logMessage(new MessageParams(MessageType.Info,
"Connected to the Acceleo Language Server, relying on Acceleo Workspace " + this
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2020 Obeo.
* Copyright (c) 2020, 2023 Obeo.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -33,9 +33,9 @@ public class AcceleoSocketServer {
private static final int BACKLOG = 50;

/**
* The {@link AcceleoLanguageServerContext} of this server.
* The {@link IAcceleoLanguageServerContext} of this server.
*/
private final AcceleoLanguageServerContext acceleoLanguageServerContext;
private final IAcceleoLanguageServerContext acceleoLanguageServerContext;

/**
* The {@link ServerSocket}.
Expand All @@ -51,9 +51,9 @@ public class AcceleoSocketServer {
* Constructor.
*
* @param acceleoLanguageServerContext
* the (non-{@code null}) root {@link AcceleoLanguageServerContext} of this server.
* the (non-{@code null}) root {@link IAcceleoLanguageServerContext} of this server.
*/
public AcceleoSocketServer(AcceleoLanguageServerContext acceleoLanguageServerContext) {
public AcceleoSocketServer(IAcceleoLanguageServerContext acceleoLanguageServerContext) {
this.acceleoLanguageServerContext = acceleoLanguageServerContext;

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
*
* @author Florent Latombe
*/
public interface AcceleoLanguageServerContext {
public interface IAcceleoLanguageServerContext {

/**
* Creates an {@link AcceleoWorkspace}.
Expand All @@ -52,6 +52,16 @@ public interface AcceleoLanguageServerContext {
*/
String getResourceContents(URI resource);

/**
* Gets the {@link AcceleoProject} containing the given resource {@link URI}.
*
* @param resource
* the resource {@link URI}
* @return the {@link AcceleoProject} containing the given resource {@link URI} if any, <code>null</code>
* otherwise
*/
AcceleoProject getProject(AcceleoWorkspace workspace, URI resource);

/**
* Creates the {@link IQueryWorkspaceQualifiedNameResolver} for the given {@link AcceleoProject}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,9 @@ public AcceleoTextDocumentService getTextDocumentService() {
* Validates this document and publishes the validation results.
*/
public void validateAndPublishResults() {
this.validateContents();
final AcceleoTextDocumentService service = this.getTextDocumentService();
if (service != null) {
this.validateContents();
service.publishValidationResults(this);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@
import org.eclipse.acceleo.aql.ls.common.AcceleoLanguageServerPositionUtils;
import org.eclipse.acceleo.aql.ls.common.AcceleoLanguageServerServicesUtils;
import org.eclipse.acceleo.aql.ls.services.exceptions.LanguageServerProtocolException;
import org.eclipse.acceleo.aql.ls.services.workspace.AcceleoProject;
import org.eclipse.acceleo.aql.ls.services.workspace.AcceleoWorkspace;
import org.eclipse.acceleo.aql.outline.AcceleoOutliner;
import org.eclipse.acceleo.aql.outline.AcceleoSymbol;
import org.eclipse.acceleo.aql.validation.IAcceleoValidationResult;
import org.eclipse.acceleo.query.runtime.namespace.workspace.IQueryWorkspaceQualifiedNameResolver;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionContext;
import org.eclipse.lsp4j.CodeActionParams;
Expand Down Expand Up @@ -109,19 +112,38 @@ public void connect(LanguageClient newLanguageClient) {
// Mandatory TextDocumentService API.
@Override
public void didOpen(DidOpenTextDocumentParams params) {
final URI openedDocumentUri = AcceleoLanguageServerServicesUtils.toUri(params.getTextDocument()
.getUri());
final AcceleoTextDocument openedAcceleoTextDocument = this.server.getWorkspace().getDocument(
openedDocumentUri);
if (openedAcceleoTextDocument == null) {
throw new IllegalStateException("Could not find the Acceleo Text Document at URI "
+ openedDocumentUri);
} else {
this.openedDocumentsIndex.put(openedDocumentUri, openedAcceleoTextDocument);
openedAcceleoTextDocument.open(params.getTextDocument().getText());
final AcceleoWorkspace workspace = server.getWorkspace();
synchronized(workspace) {
final URI openedDocumentUri = AcceleoLanguageServerServicesUtils.toUri(params.getTextDocument()
.getUri());
AcceleoTextDocument openedAcceleoTextDocument = this.server.getWorkspace().getDocument(
openedDocumentUri);
// the workspace might not be synchronized yet, try to add the document
if (openedAcceleoTextDocument == null) {
final AcceleoProject project = workspace.getProject(openedDocumentUri);
final IQueryWorkspaceQualifiedNameResolver resolver = workspace.getResolver(project);
final URI binaryURI = resolver.getBinaryURI(openedDocumentUri);
workspace.addResource(project, binaryURI);
openedAcceleoTextDocument = workspace.getDocument(openedDocumentUri);
}
if (openedAcceleoTextDocument == null) {
throw new IllegalStateException("Could not find the Acceleo Text Document at URI "
+ openedDocumentUri);
} else {
open(openedDocumentUri, openedAcceleoTextDocument);
openedAcceleoTextDocument.open(params.getTextDocument().getText());
}
}
}

public void open(URI openedDocumentUri, AcceleoTextDocument acceleoTextDocument) {
this.openedDocumentsIndex.put(openedDocumentUri, acceleoTextDocument);
}

public void close(URI closedDocumentUri) {
this.openedDocumentsIndex.remove(closedDocumentUri);
}

@Override
public void didChange(DidChangeTextDocumentParams params) {
final URI changedDocumentUri = AcceleoLanguageServerServicesUtils.toUri(params.getTextDocument()
Expand All @@ -140,15 +162,15 @@ public void didClose(DidCloseTextDocumentParams params) {
final URI closedDocumentUri = AcceleoLanguageServerServicesUtils.toUri(params.getTextDocument()
.getUri());
checkDocumentIsOpened(closedDocumentUri);
final AcceleoTextDocument openedAcceleoTextDocument = this.server.getWorkspace().getDocument(
final AcceleoTextDocument closedAcceleoTextDocument = this.server.getWorkspace().getDocument(
closedDocumentUri);
if (openedAcceleoTextDocument == null) {
if (closedAcceleoTextDocument == null) {
throw new IllegalStateException("Could not find the Acceleo Text Document at URI "
+ closedDocumentUri);
} else {
openedAcceleoTextDocument.close();
closedAcceleoTextDocument.close();
close(closedDocumentUri);
}
this.openedDocumentsIndex.remove(closedDocumentUri);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import org.eclipse.acceleo.Module;
import org.eclipse.acceleo.aql.ls.AcceleoLanguageServer;
import org.eclipse.acceleo.aql.ls.AcceleoLanguageServerContext;
import org.eclipse.acceleo.aql.ls.IAcceleoLanguageServerContext;
import org.eclipse.acceleo.aql.ls.services.textdocument.AcceleoTextDocument;
import org.eclipse.acceleo.query.runtime.impl.namespace.workspace.QueryWorkspace;
import org.eclipse.acceleo.query.runtime.namespace.IQualifiedNameLookupEngine;
Expand All @@ -34,11 +34,6 @@
*/
public class AcceleoWorkspace extends QueryWorkspace<AcceleoProject> {

/**
* The name of this workspace.
*/
private final String name;

/**
* The owner {@link AcceleoLanguageServer} of this workspace.
*/
Expand All @@ -50,30 +45,21 @@ public class AcceleoWorkspace extends QueryWorkspace<AcceleoProject> {
private final Map<URI, AcceleoTextDocument> uriToDocuments = new LinkedHashMap<>();

/**
* The {@link AcceleoLanguageServerContext}.
* The {@link IAcceleoLanguageServerContext}.
*/
private AcceleoLanguageServerContext context;
private IAcceleoLanguageServerContext context;

/**
* Creates a new {@link AcceleoWorkspace}.
*
* @param name
* the (non-{@code null}) name of the {@link AcceleoWorkspace}.
*/
public AcceleoWorkspace(String name, AcceleoLanguageServerContext context) {
this.name = Objects.requireNonNull(name);
public AcceleoWorkspace(String name, IAcceleoLanguageServerContext context) {
super(name);
this.context = Objects.requireNonNull(context);
}

/**
* Provides the name of this {@link AcceleoWorkspace}.
*
* @return the (non-{@code null}) name of this {@link AcceleoWorkspace}.
*/
public String getName() {
return this.name;
}

/**
* Sets the given {@link AcceleoLanguageServer} as the owner of this {@link AcceleoWorkspace}.
*
Expand All @@ -94,7 +80,12 @@ public AcceleoLanguageServer getOwner() {
}

@Override
public String addResource(AcceleoProject project, URI resource) {
public synchronized void addProject(AcceleoProject project) {
super.addProject(project);
}

@Override
public synchronized String addResource(AcceleoProject project, URI resource) {
final IQueryWorkspaceQualifiedNameResolver resolver = getResolver(project);
final String qualifiedName = resolver.getQualifiedName(resource);
if (qualifiedName != null) {
Expand All @@ -105,7 +96,15 @@ public String addResource(AcceleoProject project, URI resource) {
final String textDocumentContents = context.getResourceContents(resource);
final AcceleoTextDocument acceleoTextDocument = new AcceleoTextDocument(project, resource,
qualifiedName, textDocumentContents, (Module)resolved);
uriToDocuments.put(resource, acceleoTextDocument);
final AcceleoTextDocument oldAcceleoTextDocument = uriToDocuments.put(resource,
acceleoTextDocument);
if (oldAcceleoTextDocument != null && oldAcceleoTextDocument.isOpened()) {
final URI sourceURI = resolver.getSourceURI(qualifiedName);
getOwner().getTextDocumentService().close(sourceURI);
getOwner().getTextDocumentService().open(sourceURI, acceleoTextDocument);
acceleoTextDocument.open(textDocumentContents);
}

final URI sourceURI = resolver.getSourceURI(qualifiedName);
if (sourceURI != null) {
uriToDocuments.put(sourceURI, acceleoTextDocument);
Expand Down Expand Up @@ -215,4 +214,16 @@ public Set<AcceleoTextDocument> getAllTextDocuments() {
return new LinkedHashSet<>(uriToDocuments.values());
}

/**
* Gets the {@link AcceleoProject} containing the given resource {@link URI}.
*
* @param resource
* the resource {@link URI}
* @return the {@link AcceleoProject} containing the given resource {@link URI} if any, <code>null</code>
* otherwise
*/
public AcceleoProject getProject(URI resource) {
return context.getProject(this, resource);
}

}
Loading

0 comments on commit 356e9f4

Please sign in to comment.