SimpleNameExpr.java
/*******************************************************************************
* Copyright (c) 2026 Carsten Hammer.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Carsten Hammer
*******************************************************************************/
package org.sandbox.ast.api.expr;
import java.util.Optional;
import org.sandbox.ast.api.info.MethodInfo;
import org.sandbox.ast.api.info.TypeInfo;
import org.sandbox.ast.api.info.VariableInfo;
/**
* Immutable record representing a simple name expression.
* Provides type-safe binding resolution for variables, methods, and types.
*
* <p>Example usage:</p>
* <pre>
* // Old style:
* if (node instanceof SimpleName) {
* SimpleName name = (SimpleName) node;
* IBinding binding = name.resolveBinding();
* if (binding instanceof IVariableBinding) {
* IVariableBinding varBinding = (IVariableBinding) binding;
* // ...
* }
* }
*
* // New style:
* expr.asSimpleName()
* .flatMap(SimpleNameExpr::resolveVariable)
* .filter(var -> var.hasType("java.util.List"))
* .ifPresent(var -> { });
* </pre>
*/
public record SimpleNameExpr(
String identifier,
Optional<VariableInfo> variableBinding,
Optional<MethodInfo> methodBinding,
Optional<TypeInfo> typeBinding,
Optional<TypeInfo> type
) implements ASTExpr {
/**
* Creates a SimpleNameExpr record.
*
* @param identifier the name identifier
* @param variableBinding the resolved variable binding
* @param methodBinding the resolved method binding
* @param typeBinding the resolved type binding
* @param type the expression type
*/
public SimpleNameExpr {
if (identifier == null) {
throw new IllegalArgumentException("Identifier cannot be null");
}
if (identifier.isEmpty()) {
throw new IllegalArgumentException("Identifier cannot be empty");
}
variableBinding = variableBinding == null ? Optional.empty() : variableBinding;
methodBinding = methodBinding == null ? Optional.empty() : methodBinding;
typeBinding = typeBinding == null ? Optional.empty() : typeBinding;
type = type == null ? Optional.empty() : type;
}
/**
* Resolves this name as a variable.
*
* @return the variable binding, or empty if not a variable
*/
public Optional<VariableInfo> resolveVariable() {
return variableBinding;
}
/**
* Resolves this name as a method.
*
* @return the method binding, or empty if not a method
*/
public Optional<MethodInfo> resolveMethod() {
return methodBinding;
}
/**
* Resolves this name as a type.
*
* @return the type binding, or empty if not a type
*/
public Optional<TypeInfo> resolveType() {
return typeBinding;
}
/**
* Checks if this name refers to a variable.
*
* @return true if variable binding is present
*/
public boolean isVariable() {
return variableBinding.isPresent();
}
/**
* Checks if this name refers to a method.
*
* @return true if method binding is present
*/
public boolean isMethod() {
return methodBinding.isPresent();
}
/**
* Checks if this name refers to a type.
*
* @return true if type binding is present
*/
public boolean isType() {
return typeBinding.isPresent();
}
/**
* Checks if this name refers to a final variable.
*
* @return true if variable is final
*/
public boolean isFinalVariable() {
return variableBinding.map(VariableInfo::isFinal).orElse(false);
}
/**
* Checks if this name refers to a static variable.
*
* @return true if variable is static
*/
public boolean isStaticVariable() {
return variableBinding.map(VariableInfo::isStatic).orElse(false);
}
/**
* Checks if this name refers to a field.
*
* @return true if variable is a field
*/
public boolean isField() {
return variableBinding.map(VariableInfo::isField).orElse(false);
}
/**
* Checks if this name refers to a parameter.
*
* @return true if variable is a parameter
*/
public boolean isParameter() {
return variableBinding.map(VariableInfo::isParameter).orElse(false);
}
/**
* Checks if this name refers to a record component.
*
* @return true if variable is a record component
*/
public boolean isRecordComponent() {
return variableBinding.map(VariableInfo::isRecordComponent).orElse(false);
}
/**
* Checks if this name refers to a local variable (not field, not parameter, not record component).
*
* @return true if variable is a local variable
*/
public boolean isLocalVariable() {
return variableBinding.map(VariableInfo::isLocalVariable).orElse(false);
}
/**
* Checks if the variable has a specific type.
*
* @param qualifiedTypeName the fully qualified type name
* @return true if variable has this type
*/
public boolean variableHasType(String qualifiedTypeName) {
return variableBinding.map(v -> v.hasType(qualifiedTypeName)).orElse(false);
}
/**
* Builder for creating SimpleNameExpr instances.
*/
public static class Builder {
private String identifier;
private Optional<VariableInfo> variableBinding = Optional.empty();
private Optional<MethodInfo> methodBinding = Optional.empty();
private Optional<TypeInfo> typeBinding = Optional.empty();
private Optional<TypeInfo> type = Optional.empty();
/**
* Sets the identifier.
*
* @param identifier the identifier
* @return this builder
*/
public Builder identifier(String identifier) {
this.identifier = identifier;
return this;
}
/**
* Sets the variable binding.
*
* @param variableBinding the variable binding
* @return this builder
*/
public Builder variableBinding(VariableInfo variableBinding) {
this.variableBinding = Optional.ofNullable(variableBinding);
return this;
}
/**
* Sets the method binding.
*
* @param methodBinding the method binding
* @return this builder
*/
public Builder methodBinding(MethodInfo methodBinding) {
this.methodBinding = Optional.ofNullable(methodBinding);
return this;
}
/**
* Sets the type binding.
*
* @param typeBinding the type binding
* @return this builder
*/
public Builder typeBinding(TypeInfo typeBinding) {
this.typeBinding = Optional.ofNullable(typeBinding);
return this;
}
/**
* Sets the type.
*
* @param type the type
* @return this builder
*/
public Builder type(TypeInfo type) {
this.type = Optional.ofNullable(type);
return this;
}
/**
* Builds the SimpleNameExpr.
*
* @return the simple name expression
*/
public SimpleNameExpr build() {
return new SimpleNameExpr(identifier, variableBinding, methodBinding, typeBinding, type);
}
}
/**
* Creates a new builder.
*
* @return a new builder
*/
public static Builder builder() {
return new Builder();
}
/**
* Creates a simple name with just an identifier.
*
* @param identifier the identifier
* @return a new simple name expression
*/
public static SimpleNameExpr of(String identifier) {
return new SimpleNameExpr(identifier, Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty());
}
}