Skip to content

Commit

Permalink
Further progress on unimplemented resolve and parse
Browse files Browse the repository at this point in the history
Signed-off-by: Rob Stryker <[email protected]>
  • Loading branch information
Rob Stryker committed May 28, 2024
1 parent e46a896 commit 484ae12
Showing 1 changed file with 166 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
Expand All @@ -38,9 +38,11 @@
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.CompilationUnitResolver.IntArrayList;
import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
Expand All @@ -52,7 +54,14 @@
import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.jdt.internal.core.BinaryMember;
import org.eclipse.jdt.internal.core.BinaryModule;
import org.eclipse.jdt.internal.core.LocalVariable;
import org.eclipse.jdt.internal.core.SourceRefElement;
import org.eclipse.jdt.internal.core.util.BindingKeyParser;
import org.eclipse.jdt.internal.core.util.DOMFinder;
import org.eclipse.jdt.internal.javac.JavacProblemConverter;
import org.eclipse.jdt.internal.javac.JavacUtils;

Expand All @@ -76,24 +85,27 @@ private List<org.eclipse.jdt.internal.compiler.env.ICompilationUnit> createSourc
int length = sourceFilePaths.length;
List<org.eclipse.jdt.internal.compiler.env.ICompilationUnit> sourceUnitList = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
char[] contents = null;
String encoding = encodings != null ? encodings[i] : null;
String sourceUnitPath = sourceFilePaths[i];
try {
contents = Util.getFileCharContent(new File(sourceUnitPath), encoding);
} catch(IOException e) {
// go to the next unit
continue;
}
if (contents == null) {
// go to the next unit
continue;
}
sourceUnitList.add(new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(contents, sourceUnitPath, encoding));
org.eclipse.jdt.internal.compiler.env.ICompilationUnit obj = createSourceUnit(sourceFilePaths[i], encodings[i]);
if( obj != null )
sourceUnitList.add(obj);
}
return sourceUnitList;
}

private org.eclipse.jdt.internal.compiler.env.ICompilationUnit createSourceUnit(String sourceFilePath, String encoding) {
char[] contents = null;
try {
contents = Util.getFileCharContent(new File(sourceFilePath), encoding);
} catch(IOException e) {
return null;
}
if (contents == null) {
return null;
}
return new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(contents, sourceFilePath, encoding);
}


@Override
public void resolve(String[] sourceFilePaths, String[] encodings, String[] bindingKeys, FileASTRequestor requestor,
int apiLevel, Map<String, String> compilerOptions, List<Classpath> classpaths, int flags,
Expand Down Expand Up @@ -125,7 +137,6 @@ public void resolve(ICompilationUnit[] compilationUnits, String[] bindingKeys, A
Map<String, String> compilerOptions, IJavaProject project, WorkingCopyOwner workingCopyOwner, int flags,
IProgressMonitor monitor) {
Map<ICompilationUnit, CompilationUnit> units = parse(compilationUnits, apiLevel, compilerOptions, flags, monitor);
units.values().forEach(this::resolveBindings);
if (requestor != null) {
final JavacBindingResolver[] bindingResolver = new JavacBindingResolver[1];
bindingResolver[0] = null;
Expand All @@ -134,21 +145,26 @@ public void resolve(ICompilationUnit[] compilationUnits, String[] bindingKeys, A
bindingResolver[0] = (JavacBindingResolver)b.ast.getBindingResolver();
}
requestor.acceptAST(a,b);
resolveBindings(b, bindingKeys, requestor);
resolveBindings(b, bindingKeys, requestor, apiLevel);
});

resolveRequestedBindingKeys(bindingResolver[0], bindingKeys,
(a,b) -> requestor.acceptBinding(a,b),
new Classpath[0],
new Classpath[0], // TODO need some classpaths
new CompilerOptions(compilerOptions),
units.values(), monitor);
} else {
Iterator<CompilationUnit> it = units.values().iterator();
while(it.hasNext()) {
resolveBindings(it.next(), apiLevel);
}
}
}


private void resolveRequestedBindingKeys(JavacBindingResolver bindingResolver, String[] bindingKeys, GenericRequestor requestor,
Classpath[] cp,CompilerOptions opts,
Collection<CompilationUnit> res,
Collection<CompilationUnit> units,
IProgressMonitor monitor) {
if (bindingResolver == null) {
var compiler = ToolProvider.getSystemJavaCompiler();
Expand All @@ -158,7 +174,7 @@ private void resolveRequestedBindingKeys(JavacBindingResolver bindingResolver, S
}

HashMap<String, IBinding> bindingMap = new HashMap<>();
for (CompilationUnit cu : res) {
for (CompilationUnit cu : units) {
cu.accept(new BindingBuilder(bindingMap));
}

Expand Down Expand Up @@ -193,36 +209,132 @@ public void accept(ISourceType[] sourceType, PackageBinding packageBinding,
// from parsed files
requestor.acceptBinding(bindingKey, bindingFromMap);
} else {
// from ECJ
char[] charArrayFQN = Signature.toCharArray(bindingKey.toCharArray());
char[][] twoDimensionalCharArrayFQN = Stream.of(new String(charArrayFQN).split("/")) //
.map(myString -> myString.toCharArray()) //
.toArray(char[][]::new);

NameEnvironmentAnswer answer = environment.findType(twoDimensionalCharArrayFQN);
IBinaryType binaryType = answer.getBinaryType();
if (binaryType != null) {
BinaryTypeBinding binding = lu.cacheBinaryType(binaryType, null);
requestor.acceptBinding(bindingKey, new TypeBinding(bindingResolver, binding));

CustomBindingKeyParser bkp = new CustomBindingKeyParser(bindingKey);
bkp.parse(true);
char[][] name = bkp.compoundName;

// // from ECJ
// char[] charArrayFQN = Signature.toCharArray(bindingKey.toCharArray());
// char[][] twoDimensionalCharArrayFQN = Stream.of(new String(charArrayFQN).split("/")) //
// .map(myString -> myString.toCharArray()) //
// .toArray(char[][]::new);
// char[][] twoDimensionalCharArrayFQN = new char[][] {};
NameEnvironmentAnswer answer = environment.findType(name);
if( answer != null ) {
IBinaryType binaryType = answer.getBinaryType();
if (binaryType != null) {
BinaryTypeBinding binding = lu.cacheBinaryType(binaryType, null);
requestor.acceptBinding(bindingKey, new TypeBinding(bindingResolver, binding));
}
}
}

}

}

private static class CustomBindingKeyParser extends BindingKeyParser {

private char[] secondarySimpleName;
private char[][] compoundName;

public CustomBindingKeyParser(String key) {
super(key);
}

@Override
public void consumeSecondaryType(char[] simpleTypeName) {
this.secondarySimpleName = simpleTypeName;
}

@Override
public void consumeFullyQualifiedName(char[] fullyQualifiedName) {
this.compoundName = CharOperation.splitOn('/', fullyQualifiedName);
}
}

@Override
public IBinding[] resolve(IJavaElement[] elements, int apiLevel, Map<String, String> compilerOptions,
IJavaProject project, WorkingCopyOwner workingCopyOwner, int flags, IProgressMonitor monitor) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'resolve'");
IJavaProject javaProject, WorkingCopyOwner owner, int flags, IProgressMonitor monitor) {
// Logic copied entirely from ECJCompilationUnitResolver
final int length = elements.length;
final HashMap sourceElementPositions = new HashMap(); // a map from ICompilationUnit to int[] (positions in elements)
int cuNumber = 0;
final HashtableOfObjectToInt binaryElementPositions = new HashtableOfObjectToInt(); // a map from String (binding key) to int (position in elements)
for (int i = 0; i < length; i++) {
IJavaElement element = elements[i];
if (!(element instanceof SourceRefElement))
throw new IllegalStateException(element + " is not part of a compilation unit or class file"); //$NON-NLS-1$
Object cu = element.getAncestor(IJavaElement.COMPILATION_UNIT);
if (cu != null) {
// source member
IntArrayList intList = (IntArrayList) sourceElementPositions.get(cu);
if (intList == null) {
sourceElementPositions.put(cu, intList = new IntArrayList());
cuNumber++;
}
intList.add(i);
} else {
// binary member or method argument
try {
String key;
if (element instanceof BinaryMember)
key = ((BinaryMember) element).getKey(true/*open to get resolved info*/);
else if (element instanceof LocalVariable)
key = ((LocalVariable) element).getKey(true/*open to get resolved info*/);
else if (element instanceof org.eclipse.jdt.internal.core.TypeParameter)
key = ((org.eclipse.jdt.internal.core.TypeParameter) element).getKey(true/*open to get resolved info*/);
else if (element instanceof BinaryModule)
key = ((BinaryModule) element).getKey(true);
else
throw new IllegalArgumentException(element + " has an unexpected type"); //$NON-NLS-1$
binaryElementPositions.put(key, i);
} catch (JavaModelException e) {
throw new IllegalArgumentException(element + " does not exist", e); //$NON-NLS-1$
}
}
}
ICompilationUnit[] cus = new ICompilationUnit[cuNumber];
sourceElementPositions.keySet().toArray(cus);

int bindingKeyNumber = binaryElementPositions.size();
String[] bindingKeys = new String[bindingKeyNumber];
binaryElementPositions.keysToArray(bindingKeys);

class Requestor extends ASTRequestor {
IBinding[] bindings = new IBinding[length];
@Override
public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
// TODO (jerome) optimize to visit the AST only once
IntArrayList intList = (IntArrayList) sourceElementPositions.get(source);
for (int i = 0; i < intList.length; i++) {
final int index = intList.list[i];
SourceRefElement element = (SourceRefElement) elements[index];
DOMFinder finder = new DOMFinder(ast, element, true/*resolve binding*/);
try {
finder.search();
} catch (JavaModelException e) {
throw new IllegalArgumentException(element + " does not exist", e); //$NON-NLS-1$
}
this.bindings[index] = finder.foundBinding;
}
}
@Override
public void acceptBinding(String bindingKey, IBinding binding) {
int index = binaryElementPositions.get(bindingKey);
this.bindings[index] = binding;
}
}
Requestor requestor = new Requestor();
resolve(cus, bindingKeys, requestor, apiLevel, compilerOptions, javaProject, owner, flags, monitor);
return requestor.bindings;
}


@Override
public void parse(ICompilationUnit[] compilationUnits, ASTRequestor requestor, int apiLevel,
Map<String, String> compilerOptions, int flags, IProgressMonitor monitor) {
var units = parse(compilationUnits, apiLevel, compilerOptions, flags, monitor);
Map<ICompilationUnit, CompilationUnit> units = parse(compilationUnits, apiLevel, compilerOptions, flags, monitor);
if (requestor != null) {
units.forEach(requestor::acceptAST);
}
Expand Down Expand Up @@ -255,8 +367,14 @@ private Map<ICompilationUnit, CompilationUnit> parse(ICompilationUnit[] compilat
@Override
public void parse(String[] sourceFilePaths, String[] encodings, FileASTRequestor requestor, int apiLevel,
Map<String, String> compilerOptions, int flags, IProgressMonitor monitor) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'parse'");

for( int i = 0; i < sourceFilePaths.length; i++ ) {
org.eclipse.jdt.internal.compiler.env.ICompilationUnit ast = createSourceUnit(sourceFilePaths[i], encodings[i]);
Map<org.eclipse.jdt.internal.compiler.env.ICompilationUnit, CompilationUnit> res =
parse(new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] {ast}, apiLevel, compilerOptions, flags, (IJavaProject)null, monitor);
CompilationUnit result = res.get(ast);
requestor.acceptAST(sourceFilePaths[i], result);
}
}


Expand All @@ -269,10 +387,10 @@ private void respondBinding(IBinding binding, List<String> bindingKeys, ASTReque
}
}

private void resolveBindings(CompilationUnit unit) {
resolveBindings(unit, new String[0], null);
private void resolveBindings(CompilationUnit unit, int apiLevel) {
resolveBindings(unit, new String[0], null, apiLevel);
}
private void resolveBindings(CompilationUnit unit, String[] bindingKeys, ASTRequestor requestor) {
private void resolveBindings(CompilationUnit unit, String[] bindingKeys, ASTRequestor requestor, int apiLevel) {
List<String> keys = Arrays.asList(bindingKeys);

if (unit.getPackage() != null) {
Expand All @@ -286,9 +404,11 @@ private void resolveBindings(CompilationUnit unit, String[] bindingKeys, ASTRequ
respondBinding(tb, keys, requestor);
}
}
if (unit.getModule() != null) {
IModuleBinding mb = unit.getModule().resolveBinding();
respondBinding(mb, keys, requestor);
if( apiLevel >= AST.JLS9_INTERNAL) {
if (unit.getModule() != null) {
IModuleBinding mb = unit.getModule().resolveBinding();
respondBinding(mb, keys, requestor);
}
}
}

Expand All @@ -302,7 +422,7 @@ public CompilationUnit toCompilationUnit(org.eclipse.jdt.internal.compiler.env.I
apiLevel, compilerOptions, flags, project, monitor).get(sourceUnit);
if (initialNeedsToResolveBinding) {
((JavacBindingResolver)res.ast.getBindingResolver()).isRecoveringBindings = (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0;
resolveBindings(res);
resolveBindings(res, apiLevel);
}
// For comparison
// CompilationUnit res2 = CompilationUnitResolver.FACADE.toCompilationUnit(sourceUnit, initialNeedsToResolveBinding, project, classpaths, nodeSearcher, apiLevel, compilerOptions, typeRootWorkingCopyOwner, typeRootWorkingCopyOwner, flags, monitor);
Expand Down

0 comments on commit 484ae12

Please sign in to comment.