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

Validate all open buffers on changes #288

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
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,9 @@ public void setContents(String contents) {
((ISynchronizable)fDocument).setLockObject(lock);
}
}
fDocument.set(contents);
if (!contents.equals(fDocument.get())) {
fDocument.set(contents);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package org.eclipse.jdt.ls.core.internal;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Paths;
Expand Down Expand Up @@ -186,7 +187,7 @@ public static String getPackageName(IJavaProject javaProject, URI uri) {
//FIXME need to determine actual charset from file
String content = Files.toString(file, Charsets.UTF_8);
return getPackageName(javaProject, content);
} catch (Exception e) {
} catch (IOException e) {
JavaLanguageServerPlugin.logException("Failed to read package name from "+uri, e);
}
return "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,7 @@ public IBuffer createBuffer(ICompilationUnit workingCopy) {
* @see org.eclipse.jdt.core.WorkingCopyOwner#getProblemRequestor(org.eclipse.jdt.core.ICompilationUnit)
*/
@Override
public IProblemRequestor getProblemRequestor(ICompilationUnit workingCopy) {
final IResource resource = workingCopy.getPrimary().getResource();
return new DiagnosticsHandler(connection,
resource,
resource.getProject().equals(JavaLanguageServerPlugin.getProjectsManager().getDefaultProject()));
public IProblemRequestor getProblemRequestor(ICompilationUnit cu) {
return new DiagnosticsHandler(connection, cu);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
*******************************************************************************/
package org.eclipse.jdt.ls.core.internal;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

Expand All @@ -21,28 +25,31 @@
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTRequestor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;

/**
* AST provider that caches the AST generated for
* files that are known to be open.
*
* @author Gorkem Ercan
*
* AST provider that caches the AST generated for files that are known to be
* open.
*/
@SuppressWarnings("restriction")
public final class SharedASTProvider {

private ConcurrentMap<String, CompilationUnit> cache = new ConcurrentHashMap<>();
private static SharedASTProvider instance = new SharedASTProvider();

private SharedASTProvider(){
private ConcurrentMap<String, CompilationUnit> cache = new ConcurrentHashMap<>();
private int astCreationCount; // to testing purposes


private SharedASTProvider() {
astCreationCount = 0;
}

public void dispose() {
Expand All @@ -65,10 +72,61 @@ public CompilationUnit getAST(final ITypeRoot input, IProgressMonitor progressMo
final String identifier = input.getHandleIdentifier();
return cache.computeIfAbsent(identifier, k -> {
JavaLanguageServerPlugin.logInfo("Caching AST for " + input.getPath().toString());
return createAST(input, progressMonitor);
CompilationUnit astRoot = createAST(input, progressMonitor);
astCreationCount++;
return astRoot;
});
}

public List<CompilationUnit> getASTs(List<ICompilationUnit> inputs, IProgressMonitor progressMonitor) {
if (progressMonitor != null && progressMonitor.isCanceled() || inputs.isEmpty()) {
return Collections.emptyList();
}
HashMap<IJavaProject, List<ICompilationUnit>> cuByProject = new HashMap<>();
List<CompilationUnit> result = new ArrayList<>();

for (ICompilationUnit input : inputs) {
final String identifier = input.getHandleIdentifier();
CompilationUnit cu = cache.get(identifier);
if (cu != null) {
result.add(cu);
} else {
IJavaProject project = input.getJavaProject();
List<ICompilationUnit> list = cuByProject.get(project);
if (list == null) {
list = new ArrayList<>();
cuByProject.put(project, list);
}
list.add(input);
}
}

for (IJavaProject project: cuByProject.keySet()) {
final ASTParser parser = newASTParser();
parser.setProject(project);

List<ICompilationUnit> cus = cuByProject.get(project);

ASTRequestor requestor = new ASTRequestor() {
@Override
public void acceptAST(ICompilationUnit cu, CompilationUnit astRoot) {
result.add(astRoot);
setAST(astRoot);
}
};
parser.createASTs(cus.toArray(new ICompilationUnit[cus.size()]), new String[0], requestor, progressMonitor);
astCreationCount += cus.size();
}
return result;
}

public void setAST(CompilationUnit astRoot) {
ITypeRoot typeRoot = astRoot.getTypeRoot();
if (shouldCache(typeRoot)) {
cache.put(typeRoot.getHandleIdentifier(), astRoot);
}
}

/**
* Only cache ASTs for compilation units in working copy mode (open in a
* buffer)
Expand Down Expand Up @@ -111,16 +169,9 @@ private static CompilationUnit createAST(final ITypeRoot input, final IProgressM
return null;
}

final ASTParser parser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
parser.setResolveBindings(true);
parser.setStatementsRecovery(IASTSharedValues.SHARED_AST_STATEMENT_RECOVERY);
parser.setBindingsRecovery(IASTSharedValues.SHARED_BINDING_RECOVERY);
final ASTParser parser = newASTParser();
parser.setSource(input);

if (progressMonitor != null && progressMonitor.isCanceled()) {
return null;
}

final CompilationUnit root[]= new CompilationUnit[1];

SafeRunner.run(new ISafeRunnable() {
Expand All @@ -130,7 +181,7 @@ public void run() {
if (progressMonitor != null && progressMonitor.isCanceled()) {
return;
}
root[0]= (CompilationUnit)parser.createAST(progressMonitor);
root[0] = (CompilationUnit) parser.createAST(progressMonitor);

//mark as unmodifiable
ASTNodes.setFlagsToAST(root[0], ASTNode.PROTECT);
Expand All @@ -147,6 +198,14 @@ public void handleException(Throwable ex) {
return root[0];
}

public static ASTParser newASTParser() {
final ASTParser parser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
parser.setResolveBindings(true);
parser.setStatementsRecovery(IASTSharedValues.SHARED_AST_STATEMENT_RECOVERY);
parser.setBindingsRecovery(IASTSharedValues.SHARED_BINDING_RECOVERY);
return parser;
}

/**
* Checks whether the given Java element has accessible source.
*
Expand All @@ -167,5 +226,31 @@ private static boolean hasSource(ITypeRoot je) {
return false;
}

/**
* For testing purposes
*
* @return the number of elements currently in the cache
*/
public int getCacheSize() {
return cache.size();
}

/**
* For testing purposes
*
* @return the number of ASTs created
*/
public int getASTCreationCount() {
return astCreationCount;
}

/**
* For testing purposes
*
* Sets the counter for ASTs created to 0
*/
public void clearASTCreationCount() {
astCreationCount = 0;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IProblemRequestor;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
Expand All @@ -31,15 +31,15 @@
public class DiagnosticsHandler implements IProblemRequestor {

private final List<IProblem> problems;
private final IResource resource;
private final String uri;
private final JavaClientConnection connection;
private boolean reportAllErrors = true;

public DiagnosticsHandler(JavaClientConnection conn, IResource resource, boolean reportOnlySyntaxErrors) {
public DiagnosticsHandler(JavaClientConnection conn, ICompilationUnit cu) {
problems = new ArrayList<>();
this.resource = resource;
this.uri = JDTUtils.getFileURI(cu);
this.connection = conn;
this.reportAllErrors = !reportOnlySyntaxErrors;
this.reportAllErrors = !cu.getJavaProject().getProject().equals(JavaLanguageServerPlugin.getProjectsManager().getDefaultProject());
}

@Override
Expand Down Expand Up @@ -98,14 +98,13 @@ private String getError(IProblem problem) {

@Override
public void beginReporting() {
JavaLanguageServerPlugin.logInfo("begin problem for " + this.resource.getName());
JavaLanguageServerPlugin.logInfo("begin problem for " + this.uri.substring(this.uri.lastIndexOf('/')));
problems.clear();
}

@Override
public void endReporting() {
JavaLanguageServerPlugin.logInfo("end reporting for "+ this.resource.getName());
String uri = JDTUtils.getFileURI(this.resource);
JavaLanguageServerPlugin.logInfo(problems.size() + " problems reported for " + this.uri.substring(this.uri.lastIndexOf('/')));
PublishDiagnosticsParams $ = new PublishDiagnosticsParams(uri, toDiagnosticsArray(problems));
this.connection.publishDiagnostics($);
}
Expand Down
Loading