Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.strobel.decompiler.languages.java.ast.JavaNameResolver Maven / Gradle / Ivy
/*
* JavaNameResolver.java
*
* Copyright (c) 2014 Mike Strobel
*
* This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain;
* and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0.
* A copy of the license can be found in the License.html file at the root of this distribution.
* By using this source code in any fashion, you are agreeing to be bound by the terms of the
* Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*/
package com.strobel.decompiler.languages.java.ast;
import com.strobel.assembler.metadata.*;
import com.strobel.core.Predicates;
import com.strobel.core.ReadOnlyList;
import com.strobel.core.StringUtilities;
import com.strobel.core.VerifyArgument;
import com.strobel.decompiler.ast.Variable;
import com.strobel.decompiler.patterns.Pattern;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import static com.strobel.core.CollectionUtilities.any;
public final class JavaNameResolver {
public static NameResolveResult resolve(final String name, final AstNode node) {
return new Result(
NameResolveMode.EXPRESSION,
resolveCore(node, name, NameResolveMode.EXPRESSION)
);
}
public static NameResolveResult resolveAsType(final String name, final AstNode node) {
return new Result(
NameResolveMode.TYPE,
resolveCore(node, name, NameResolveMode.TYPE)
);
}
private static List resolveCore(
final AstNode location,
final String name,
final NameResolveMode mode) {
final Set results = FindDeclarationVisitor.resolveName(location, name, mode);
if (results.isEmpty()) {
return ReadOnlyList.emptyList();
}
return new ReadOnlyList<>(Object.class, results);
}
private final static class FindDeclarationVisitor implements IAstVisitor> {
private final NameResolveMode _mode;
private boolean _isStaticContext = false;
FindDeclarationVisitor(final NameResolveMode mode, final boolean isStaticContext) {
_mode = VerifyArgument.notNull(mode, "mode");
_isStaticContext = isStaticContext;
}
static Set resolveName(final AstNode node, final String name, final NameResolveMode mode) {
VerifyArgument.notNull(node, "node");
VerifyArgument.notNull(name, "name");
VerifyArgument.notNull(mode, "mode");
AstNode n = node;
Set results = null;
while (n instanceof Expression) {
n = n.getParent();
}
if (n == null || n.isNull()) {
return Collections.emptySet();
}
TypeDeclaration lastTypeDeclaration = null;
final FindDeclarationVisitor visitor = new FindDeclarationVisitor(mode, isStaticContext(node));
while (n != null && !n.isNull()) {
if (n instanceof CompilationUnit) {
final Set unitResults = n.acceptVisitor(visitor, name);
if (!unitResults.isEmpty()) {
if (results == null) {
return unitResults;
}
results.addAll(unitResults);
}
}
AstNode parent = n.getParent();
if (n instanceof MethodDeclaration) {
final Set methodResults = n.acceptVisitor(visitor, name);
if (!methodResults.isEmpty()) {
if (results == null) {
results = new LinkedHashSet<>();
}
results.addAll(methodResults);
}
final MethodDefinition method = n.getUserData(Keys.METHOD_DEFINITION);
if (method != null) {
visitor._isStaticContext = method.isStatic();
}
}
else if (n instanceof TypeDeclaration) {
final Set typeResults = n.acceptVisitor(visitor, name);
if (!typeResults.isEmpty()) {
if (results == null) {
results = new LinkedHashSet<>();
}
results.addAll(typeResults);
return results;
}
if (parent instanceof TypeDeclaration) {
final TypeDefinition type = n.getUserData(Keys.TYPE_DEFINITION);
if (type != null) {
visitor._isStaticContext = type.isStatic();
}
}
else if (parent instanceof LocalTypeDeclarationStatement) {
n = ((LocalTypeDeclarationStatement) parent).getTypeDeclaration();
parent = n.getParent();
}
lastTypeDeclaration = (TypeDeclaration) n;
}
else if (n instanceof Statement) {
final Statement s = (Statement) n;
final Set statementResults = s.acceptVisitor(visitor, name);
if (!statementResults.isEmpty()) {
if (results == null) {
results = new LinkedHashSet<>();
}
results.addAll(statementResults);
if (mode == NameResolveMode.EXPRESSION ||
mode == NameResolveMode.TYPE && any(results, Predicates.instanceOf(TypeReference.class))) {
return results;
}
}
final Statement previousStatement = ((Statement) n).getPreviousStatement();
if (previousStatement != null) {
n = previousStatement;
continue;
}
}
n = parent;
}
if (results != null) {
return results;
}
if (lastTypeDeclaration != null) {
return visitor.searchUpScope(
name,
lastTypeDeclaration.getUserData(Keys.TYPE_DEFINITION),
new LinkedHashSet(),
true
);
}
return Collections.emptySet();
}
private Set searchUpScope(
final String name,
final TypeDefinition type,
final Set visitedTypes,
final boolean searchGenericParameters) {
if (type == null || visitedTypes.contains(type.getInternalName())) {
return Collections.emptySet();
}
Set results = null;
if (_mode == NameResolveMode.EXPRESSION) {
for (final FieldDefinition f : type.getDeclaredFields()) {
if (StringUtilities.equals(f.getName(), name) && (!_isStaticContext || f.isStatic())) {
return Collections.singleton(f);
}
}
}
if (StringUtilities.equals(type.getSimpleName(), name)) {
results = new LinkedHashSet<>();
results.add(type);
}
if (searchGenericParameters) {
for (final GenericParameter gp : type.getGenericParameters()) {
if (StringUtilities.equals(gp.getName(), name)) {
if (results == null) {
results = new LinkedHashSet<>();
}
results.add(gp);
}
}
}
for (final TypeDefinition declaredType : type.getDeclaredTypes()) {
if (StringUtilities.equals(declaredType.getSimpleName(), name)) {
if (results == null) {
results = new LinkedHashSet<>();
}
results.add(declaredType);
}
}
if (results != null && !results.isEmpty()) {
return results;
}
final TypeReference baseType = type.getBaseType();
if (baseType != null) {
final TypeDefinition resolvedBaseType = baseType.resolve();
if (resolvedBaseType != null) {
final Set baseTypeResults = searchUpScope(name, resolvedBaseType, visitedTypes, false);
if (baseTypeResults != null && !baseTypeResults.isEmpty()) {
if (results == null) {
results = baseTypeResults instanceof LinkedHashSet> ? baseTypeResults
: new LinkedHashSet<>(baseTypeResults);
}
else {
results.addAll(baseTypeResults);
}
}
}
}
for (final TypeReference ifType : MetadataHelper.getInterfaces(type)) {
final TypeDefinition resultIfType = ifType.resolve();
if (resultIfType != null) {
final Set ifTypeResults = searchUpScope(name, resultIfType, visitedTypes, false);
if (ifTypeResults != null && !ifTypeResults.isEmpty()) {
if (results == null) {
results = ifTypeResults instanceof LinkedHashSet> ? ifTypeResults
: new LinkedHashSet<>(ifTypeResults);
}
else {
results.addAll(ifTypeResults);
}
}
}
}
final MethodReference declaringMethod = type.getDeclaringMethod();
if (declaringMethod != null) {
final TypeReference declaringType = declaringMethod.getDeclaringType();
if (declaringType != null) {
final TypeDefinition resolvedType = declaringType.resolve();
if (resolvedType != null) {
final Set declaringTypeResults = searchUpScope(name, resolvedType, visitedTypes, true);
if (declaringTypeResults != null && !declaringTypeResults.isEmpty()) {
if (results == null) {
results = declaringTypeResults instanceof LinkedHashSet> ? declaringTypeResults
: new LinkedHashSet<>(declaringTypeResults);
}
else {
results.addAll(declaringTypeResults);
}
}
}
else if (StringUtilities.equals(declaringType.getSimpleName(), name)) {
if (results == null) {
results = new LinkedHashSet<>();
}
results.add(declaringType);
}
}
}
final TypeReference declaringType = type.getDeclaringType();
if (declaringType != null) {
final TypeDefinition resolvedType = declaringType.resolve();
if (resolvedType != null) {
final Set declaringTypeResults = searchUpScope(name, resolvedType, visitedTypes, true);
if (declaringTypeResults != null && !declaringTypeResults.isEmpty()) {
if (results == null) {
results = declaringTypeResults instanceof LinkedHashSet> ? declaringTypeResults
: new LinkedHashSet<>(declaringTypeResults);
}
else {
results.addAll(declaringTypeResults);
}
}
}
else if (StringUtilities.equals(declaringType.getSimpleName(), name)) {
if (results == null) {
results = new LinkedHashSet<>();
}
results.add(declaringType);
}
}
if (results != null) {
return results;
}
return Collections.emptySet();
}
private static boolean isStaticContext(final AstNode node) {
for (AstNode n = node;
n != null && !n.isNull();
n = n.getParent()) {
if (n instanceof MethodDeclaration) {
final MethodDefinition method = n.getUserData(Keys.METHOD_DEFINITION);
if (method != null) {
return method.isStatic();
}
}
if (n instanceof TypeDeclaration) {
final TypeDefinition type = n.getUserData(Keys.TYPE_DEFINITION);
if (type != null) {
return type.isStatic();
}
}
}
return false;
}
@Override
public Set visitComment(final Comment node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitPatternPlaceholder(final AstNode node, final Pattern pattern, final String name) {
return Collections.emptySet();
}
@Override
public Set visitInvocationExpression(final InvocationExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitTypeReference(final TypeReferenceExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitJavaTokenNode(final JavaTokenNode node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitMemberReferenceExpression(final MemberReferenceExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitIdentifier(final Identifier node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitNullReferenceExpression(final NullReferenceExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitThisReferenceExpression(final ThisReferenceExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitSuperReferenceExpression(final SuperReferenceExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitClassOfExpression(final ClassOfExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitBlockStatement(final BlockStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitExpressionStatement(final ExpressionStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitBreakStatement(final BreakStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitContinueStatement(final ContinueStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitDoWhileStatement(final DoWhileStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitEmptyStatement(final EmptyStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitIfElseStatement(final IfElseStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitLabelStatement(final LabelStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitLabeledStatement(final LabeledStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitReturnStatement(final ReturnStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitSwitchStatement(final SwitchStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitSwitchSection(final SwitchSection node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitCaseLabel(final CaseLabel node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitThrowStatement(final ThrowStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitCatchClause(final CatchClause node, final String name) {
if (_mode == NameResolveMode.EXPRESSION && StringUtilities.equals(node.getVariableName(), name)) {
final Variable exceptionVariable = node.getUserData(Keys.VARIABLE);
if (exceptionVariable != null) {
return Collections.singleton(exceptionVariable);
}
}
return Collections.emptySet();
}
@Override
public Set visitAnnotation(final Annotation node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitNewLine(final NewLineNode node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitVariableDeclaration(final VariableDeclarationStatement node, final String name) {
if (_mode == NameResolveMode.EXPRESSION) {
final VariableInitializer v = node.getVariable(name);
if (v != null) {
final Variable variable = v.getUserData(Keys.VARIABLE);
if (variable != null) {
return Collections.singleton(variable);
}
}
}
return Collections.emptySet();
}
@Override
public Set visitVariableInitializer(final VariableInitializer node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitText(final TextNode node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitImportDeclaration(final ImportDeclaration node, final String name) {
final TypeReference importedType = node.getUserData(Keys.TYPE_REFERENCE);
if (importedType != null && StringUtilities.equals(importedType.getSimpleName(), name)) {
return Collections.singleton(importedType);
}
return Collections.emptySet();
}
@Override
public Set visitSimpleType(final SimpleType node, final String name) {
if (StringUtilities.equals(node.getIdentifier(), name)) {
return Collections.singleton(node.toTypeReference());
}
return Collections.emptySet();
}
@Override
public Set visitMethodDeclaration(final MethodDeclaration node, final String name) {
Set results = null;
if (_mode == NameResolveMode.EXPRESSION) {
for (final ParameterDeclaration p : node.getParameters()) {
if (StringUtilities.equals(p.getName(), name)) {
final ParameterDefinition pd = p.getUserData(Keys.PARAMETER_DEFINITION);
if (pd == null) {
continue;
}
if (results == null) {
results = new LinkedHashSet<>();
}
results.add(pd);
}
}
}
for (final TypeParameterDeclaration tp : node.getTypeParameters()) {
final TypeDefinition gp = tp.getUserData(Keys.TYPE_DEFINITION);
if (gp != null && StringUtilities.equals(gp.getName(), name)) {
if (results == null) {
results = new LinkedHashSet<>();
}
results.add(gp);
}
}
if (results != null) {
return results;
}
return Collections.emptySet();
}
@Override
public Set visitInitializerBlock(final InstanceInitializer node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitConstructorDeclaration(final ConstructorDeclaration node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitTypeParameterDeclaration(final TypeParameterDeclaration node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitParameterDeclaration(final ParameterDeclaration node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitFieldDeclaration(final FieldDeclaration node, final String name) {
if (_mode == NameResolveMode.EXPRESSION) {
if (StringUtilities.equals(node.getName(), name)) {
final FieldDefinition f = node.getUserData(Keys.FIELD_DEFINITION);
if (f != null && (!_isStaticContext || f.isStatic())) {
return Collections.singleton(f);
}
}
}
return Collections.emptySet();
}
@Override
public Set visitTypeDeclaration(final TypeDeclaration node, final String name) {
Set results = null;
if (_mode == NameResolveMode.EXPRESSION) {
for (final EntityDeclaration member : node.getMembers()) {
if (member instanceof FieldDeclaration) {
final Set fieldResults = member.acceptVisitor(this, name);
if (fieldResults.isEmpty()) {
continue;
}
return fieldResults;
}
}
}
if (StringUtilities.equals(node.getName(), name)) {
final TypeDefinition typeDefinition = node.getUserData(Keys.TYPE_DEFINITION);
if (typeDefinition != null) {
results = new LinkedHashSet<>();
results.add(typeDefinition);
}
}
for (final EntityDeclaration member : node.getMembers()) {
if (member instanceof TypeDeclaration) {
final TypeDeclaration td = (TypeDeclaration) member;
if (StringUtilities.equals(td.getName(), name)) {
final TypeDefinition t = td.getUserData(Keys.TYPE_DEFINITION);
if (t == null) {
continue;
}
if (results == null) {
results = new LinkedHashSet<>();
}
results.add(t);
}
}
}
if (_mode == NameResolveMode.TYPE && results != null && !results.isEmpty()) {
return results;
}
for (final TypeParameterDeclaration tp : node.getTypeParameters()) {
final TypeDefinition gp = tp.getUserData(Keys.TYPE_DEFINITION);
if (gp != null && StringUtilities.equals(gp.getName(), name)) {
if (results == null) {
results = new LinkedHashSet<>();
}
results.add(gp);
}
}
if (results != null && !results.isEmpty()) {
return results;
}
return searchUpScope(
name,
node.getUserData(Keys.TYPE_DEFINITION),
new LinkedHashSet(),
true
);
}
@Override
public Set visitLocalTypeDeclarationStatement(final LocalTypeDeclarationStatement node, final String name) {
final TypeDeclaration typeDeclaration = node.getTypeDeclaration();
if (typeDeclaration.isNull()) {
return Collections.emptySet();
}
if (StringUtilities.equals(typeDeclaration.getName(), name)) {
final TypeDefinition type = typeDeclaration.getUserData(Keys.TYPE_DEFINITION);
if (type != null) {
return Collections.singleton(type);
}
}
return searchUpScope(
name,
typeDeclaration.getUserData(Keys.TYPE_DEFINITION),
new LinkedHashSet(),
true
);
}
@Override
public Set visitCompilationUnit(final CompilationUnit node, final String name) {
Set results = null;
for (final TypeDeclaration typeDeclaration : node.getTypes()) {
final Set typeResults = typeDeclaration.acceptVisitor(this, name);
if (typeResults.isEmpty()) {
continue;
}
if (results == null) {
results = new LinkedHashSet<>();
}
results.addAll(typeResults);
}
for (final ImportDeclaration typeImport : node.getImports()) {
final Set importResults = typeImport.acceptVisitor(this, name);
if (importResults.isEmpty()) {
continue;
}
if (results == null) {
results = new LinkedHashSet<>();
}
results.addAll(importResults);
}
if (results != null) {
return results;
}
return Collections.emptySet();
}
@Override
public Set visitPackageDeclaration(final PackageDeclaration node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitArraySpecifier(final ArraySpecifier node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitComposedType(final ComposedType node, final String name) {
return node.getBaseType().acceptVisitor(this, name);
}
@Override
public Set visitWhileStatement(final WhileStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitPrimitiveExpression(final PrimitiveExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitCastExpression(final CastExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitBinaryOperatorExpression(final BinaryOperatorExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitInstanceOfExpression(final InstanceOfExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitIndexerExpression(final IndexerExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitIdentifierExpression(final IdentifierExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitUnaryOperatorExpression(final UnaryOperatorExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitConditionalExpression(final ConditionalExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitArrayInitializerExpression(final ArrayInitializerExpression arrayInitializerExpression, final String name) {
return Collections.emptySet();
}
@Override
public Set visitObjectCreationExpression(final ObjectCreationExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitArrayCreationExpression(final ArrayCreationExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitAssignmentExpression(final AssignmentExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitForStatement(final ForStatement node, final String name) {
if (_mode == NameResolveMode.EXPRESSION) {
Set results = null;
for (final Statement initializer : node.getInitializers()) {
final Set initializerResults = initializer.acceptVisitor(this, name);
if (node.getInitializers().isEmpty()) {
continue;
}
if (results == null) {
results = new LinkedHashSet<>();
}
results.addAll(initializerResults);
}
}
return Collections.emptySet();
}
@Override
public Set visitForEachStatement(final ForEachStatement node, final String name) {
if (_mode == NameResolveMode.EXPRESSION) {
if (StringUtilities.equals(node.getVariableName(), name)) {
final Variable v = node.getUserData(Keys.VARIABLE);
if (v != null) {
return Collections.singleton(v);
}
}
}
return Collections.emptySet();
}
@Override
public Set visitTryCatchStatement(final TryCatchStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitGotoStatement(final GotoStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitParenthesizedExpression(final ParenthesizedExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitSynchronizedStatement(final SynchronizedStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitAnonymousObjectCreationExpression(final AnonymousObjectCreationExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitWildcardType(final WildcardType node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitMethodGroupExpression(final MethodGroupExpression node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitEnumValueDeclaration(final EnumValueDeclaration node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitAssertStatement(final AssertStatement node, final String name) {
return Collections.emptySet();
}
@Override
public Set visitLambdaExpression(final LambdaExpression node, final String name) {
if (_mode == NameResolveMode.EXPRESSION) {
Set results = null;
for (final ParameterDeclaration pd : node.getParameters()) {
if (StringUtilities.equals(pd.getName(), name)) {
final ParameterDefinition p = pd.getUserData(Keys.PARAMETER_DEFINITION);
if (p != null) {
if (results == null) {
results = new LinkedHashSet<>();
}
results.add(p);
}
}
}
if (results != null) {
return results;
}
}
return Collections.emptySet();
}
}
private final static class Result extends NameResolveResult {
private final NameResolveMode _mode;
private final List _candidates;
Result(final NameResolveMode mode, final List candidates) {
_mode = mode;
_candidates = candidates;
}
@Override
public final List getCandidates() {
return _candidates;
}
@Override
public final NameResolveMode getMode() {
return _mode;
}
}
}