GH-1219: preparing the AST parsing for environment cleanup activities after bulk parsing to close zip files and free up memory
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2024 Broadcom
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Broadcom - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.utils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
import org.eclipse.jdt.core.dom.AST;
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.ASTParser;
|
||||
import org.eclipse.jdt.core.dom.FileASTRequestor;
|
||||
|
||||
/**
|
||||
* Wrapper around a JDT AST parser to enable cleanup functionality on the lookup environment,
|
||||
* which is otherwise hidden and not accessible from the outside
|
||||
*/
|
||||
public class ASTParserCleanupEnabled {
|
||||
|
||||
private final ASTParser parser;
|
||||
// private final INameEnvironmentWithProgress environment;
|
||||
private final Map<String, String> options;
|
||||
// private final int flags;
|
||||
// private final int apiLevel;
|
||||
|
||||
public ASTParserCleanupEnabled(String[] classpathEntries, String[] sourceEntries, boolean ignoreMethodBodies) {
|
||||
parser = ASTParser.newParser(AST.JLS21);
|
||||
options = JavaCore.getOptions();
|
||||
JavaCore.setComplianceOptions(JavaCore.VERSION_21, options);
|
||||
|
||||
parser.setCompilerOptions(options);
|
||||
parser.setKind(ASTParser.K_COMPILATION_UNIT);
|
||||
parser.setStatementsRecovery(true);
|
||||
parser.setBindingsRecovery(true);
|
||||
parser.setResolveBindings(true);
|
||||
parser.setIgnoreMethodBodies(ignoreMethodBodies);
|
||||
|
||||
parser.setEnvironment(classpathEntries, sourceEntries, null, false);
|
||||
|
||||
// List<Classpath> classpaths = CUResolver.getClasspath(parser);
|
||||
// environment = CUResolver.createLookupEnvironment(classpaths.toArray(new Classpath[classpaths.size()]));
|
||||
//
|
||||
// apiLevel = AST.JLS21;
|
||||
//
|
||||
// int flags = 0;
|
||||
// flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
|
||||
// flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
|
||||
//
|
||||
// if (ignoreMethodBodies) {
|
||||
// flags |= ICompilationUnit.IGNORE_METHOD_BODIES;
|
||||
// }
|
||||
//
|
||||
// this.flags = flags;
|
||||
|
||||
}
|
||||
|
||||
public void setUnitName(String unitName) {
|
||||
this.parser.setUnitName(unitName);
|
||||
}
|
||||
|
||||
public void setSource(char[] source) {
|
||||
this.parser.setSource(source);
|
||||
}
|
||||
|
||||
public ASTNode createAST(IProgressMonitor monitor) {
|
||||
return this.parser.createAST(monitor);
|
||||
}
|
||||
|
||||
public void createASTs(String[] sourceFilePaths, String[] encodings, String[] bindingKeys,
|
||||
FileASTRequestor requestor, IProgressMonitor monitor) {
|
||||
|
||||
// CUResolver.resolve(sourceFilePaths, encodings, bindingKeys, requestor, apiLevel, options, flags, environment);
|
||||
this.parser.createASTs(sourceFilePaths, encodings, bindingKeys, requestor, monitor);
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
// environment.cleanup();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import org.eclipse.jdt.core.JavaModelException;
|
||||
import org.eclipse.jdt.core.WorkingCopyOwner;
|
||||
import org.eclipse.jdt.core.dom.ASTParser;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.FileASTRequestor;
|
||||
import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
|
||||
import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
|
||||
import org.eclipse.jdt.internal.compiler.IProblemFactory;
|
||||
@@ -217,6 +218,27 @@ class CUResolver {
|
||||
return null;
|
||||
};
|
||||
|
||||
private static final Supplier<Method> RESOLVE_SOURCE_FILES_METHOD = () -> {
|
||||
try {
|
||||
Class<?> clazz = COMPILATION_UNIT_RESOLVER_CLASS.get();
|
||||
if (clazz != null) {
|
||||
Method resolveMethod = clazz.getDeclaredMethod("resolve",
|
||||
String[].class, // sourceCompilationUnits
|
||||
String[].class, // encodings
|
||||
String[].class, //bindingKeys
|
||||
FileASTRequestor.class, // astRequestor
|
||||
int.class, // apiLevel
|
||||
Map.class, // compilerOptions
|
||||
int.class); // flags
|
||||
resolveMethod.setAccessible(true);
|
||||
return resolveMethod;
|
||||
}
|
||||
} catch (NoSuchMethodException | SecurityException e) {
|
||||
log.error("{}", e);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
private static final Supplier<Method> CONVERT_METHOD = () -> {
|
||||
try {
|
||||
Class<?> clazz = COMPILATION_UNIT_RESOLVER_CLASS.get();
|
||||
@@ -300,6 +322,57 @@ class CUResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
static void resolve(
|
||||
String[] sourceUnits,
|
||||
String[] encodings,
|
||||
String[] bindingKeys,
|
||||
FileASTRequestor requestor,
|
||||
int apiLevel,
|
||||
Map<String, String> options,
|
||||
int flags,
|
||||
INameEnvironmentWithProgress environment) {
|
||||
|
||||
CancelableProblemFactory problemFactory = null;
|
||||
try {
|
||||
problemFactory = new CancelableProblemFactory(new NullProgressMonitor());
|
||||
|
||||
CompilerOptions compilerOptions = (CompilerOptions) GET_COMPILER_OPTIONS_METHOD.get().invoke(null, options,
|
||||
(flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
|
||||
compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
|
||||
|
||||
Object resolver = COMPILATION_UNIT_RESOLVER_CONSTRUCTOR.get().newInstance(environment,
|
||||
GET_HANDLER_POLICY_METHOD.get().invoke(null), compilerOptions,
|
||||
GET_REQUESTOR_METHOD.get().invoke(null), problemFactory, new NullProgressMonitor(), false);
|
||||
|
||||
// CompilationUnitResolver resolver =
|
||||
// new CompilationUnitResolver(
|
||||
// environment,
|
||||
// getHandlingPolicy(),
|
||||
// compilerOptions,
|
||||
// getRequestor(),
|
||||
// problemFactory,
|
||||
// subMonitor,
|
||||
// false);
|
||||
|
||||
RESOLVE_SOURCE_FILES_METHOD.get().invoke(resolver,
|
||||
sourceUnits, encodings, bindingKeys, requestor, apiLevel, options, flags);
|
||||
|
||||
// resolver.resolve(sourceUnits, encodings, bindingKeys, requestor, apiLevel, options, flags);
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("{}", e);
|
||||
}
|
||||
finally {
|
||||
if (environment != null) {
|
||||
environment.setMonitor(null); // don't hold a reference to this external object
|
||||
}
|
||||
if (problemFactory != null) {
|
||||
problemFactory.monitor = null; // don't hold a reference to this external object
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static CompilationUnitDeclaration parse(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit, Map<String, String> options, int flags) {
|
||||
try {
|
||||
return (CompilationUnitDeclaration) PARSE_METHOD.get()
|
||||
|
||||
@@ -34,9 +34,6 @@ import java.util.stream.Stream;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
import org.eclipse.jdt.core.dom.AST;
|
||||
import org.eclipse.jdt.core.dom.ASTParser;
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor;
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
@@ -264,7 +261,7 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
|
||||
private void scanFile(IJavaProject project, DocumentDescriptor updatedDoc, String content) throws Exception {
|
||||
final boolean ignoreMethodBodies = false;
|
||||
ASTParser parser = createParser(project, ignoreMethodBodies);
|
||||
ASTParserCleanupEnabled parser = createParser(project, ignoreMethodBodies);
|
||||
|
||||
String docURI = updatedDoc.getDocURI();
|
||||
long lastModified = updatedDoc.getLastModified();
|
||||
@@ -420,8 +417,9 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
|
||||
List<String[]> chunks = createChunks(javaFiles, this.scanChunkSize);
|
||||
for(int i = 0; i < chunks.size(); i++) {
|
||||
ASTParser parser = createParser(project, ignoreMethodBodies);
|
||||
ASTParserCleanupEnabled parser = createParser(project, ignoreMethodBodies);
|
||||
parser.createASTs(chunks.get(i), null, new String[0], requestor, null);
|
||||
parser.cleanup();
|
||||
}
|
||||
|
||||
EnhancedSymbolInformation[] symbols = generatedSymbols.stream().map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
|
||||
@@ -572,8 +570,9 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
}
|
||||
};
|
||||
|
||||
ASTParser parser = createParser(project, ignoreMethodBodies);
|
||||
ASTParserCleanupEnabled parser = createParser(project, ignoreMethodBodies);
|
||||
parser.createASTs(javaFiles, null, new String[0], requestor, null);
|
||||
parser.cleanup();
|
||||
|
||||
return (String[]) nextPassFiles.toArray(new String[nextPassFiles.size()]);
|
||||
}
|
||||
@@ -768,22 +767,11 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ASTParser createParser(IJavaProject project, boolean ignoreMethodBodies) throws Exception {
|
||||
public static ASTParserCleanupEnabled createParser(IJavaProject project, boolean ignoreMethodBodies) throws Exception {
|
||||
String[] classpathEntries = getClasspathEntries(project);
|
||||
String[] sourceEntries = getSourceEntries(project);
|
||||
|
||||
ASTParser parser = ASTParser.newParser(AST.JLS21);
|
||||
Map<String, String> options = JavaCore.getOptions();
|
||||
JavaCore.setComplianceOptions(JavaCore.VERSION_21, options);
|
||||
parser.setCompilerOptions(options);
|
||||
parser.setKind(ASTParser.K_COMPILATION_UNIT);
|
||||
parser.setStatementsRecovery(true);
|
||||
parser.setBindingsRecovery(true);
|
||||
parser.setResolveBindings(true);
|
||||
parser.setIgnoreMethodBodies(ignoreMethodBodies);
|
||||
|
||||
parser.setEnvironment(classpathEntries, sourceEntries, null, false);
|
||||
return parser;
|
||||
return new ASTParserCleanupEnabled(classpathEntries, sourceEntries, ignoreMethodBodies);
|
||||
}
|
||||
|
||||
private static String[] getClasspathEntries(IJavaProject project) throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user