Expose collected superclass properties/methods in pkl:reflect (#1106)

This commit is contained in:
Jen Basch
2025-09-19 12:23:57 -07:00
committed by GitHub
parent d1171db3d5
commit 63f89fb679
7 changed files with 2997 additions and 16 deletions

View File

@@ -16,6 +16,7 @@
package org.pkl.core.ast.member;
import com.oracle.truffle.api.source.SourceSection;
import java.util.ArrayList;
import java.util.List;
import org.pkl.core.Member.SourceLocation;
import org.pkl.core.PClass;
@@ -67,8 +68,44 @@ public final class ClassProperty extends ClassMember {
return name.toString();
}
public VmTyped getMirror() {
return MirrorFactories.propertyFactory.create(this);
public static final class Mirror {
private final ClassProperty prop;
private final VmClass clazz;
Mirror(ClassProperty prop, VmClass clazz) {
this.prop = prop;
this.clazz = clazz;
}
public ClassProperty getProperty() {
return prop;
}
public List<VmTyped> getAllAnnotations() {
var annotations = new ArrayList<VmTyped>();
for (var klazz = clazz; klazz != null; klazz = klazz.getSuperclass()) {
var p = klazz.getDeclaredProperty(prop.getName());
if (p != null) {
annotations.addAll(p.getAnnotations());
}
}
return annotations;
}
public VmSet getAllModifierMirrors() {
var mods = 0;
for (var klazz = clazz; klazz != null; klazz = klazz.getSuperclass()) {
var parent = klazz.getDeclaredProperty(prop.getName());
if (parent != null) {
mods |= parent.getModifiers();
}
}
return VmModifier.getMirrors(mods, false);
}
}
public VmTyped getMirror(VmClass clazz) {
return MirrorFactories.propertyFactory.create(new Mirror(this, clazz));
}
public VmSet getModifierMirrors() {

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ public final class MirrorFactories {
public static final VmObjectFactory<VmTypeAlias> typeAliasFactory =
new VmObjectFactory<>(ReflectModule::getTypeAliasClass);
public static final VmObjectFactory<ClassProperty> propertyFactory =
public static final VmObjectFactory<ClassProperty.Mirror> propertyFactory =
new VmObjectFactory<>(ReflectModule::getPropertyClass);
public static final VmObjectFactory<ClassMethod> methodFactory =
@@ -146,8 +146,10 @@ public final class MirrorFactories {
.addProperty("superclass", VmClass::getSuperclassMirror)
.addProperty("supertype", VmClass::getSupertypeMirror)
.addMapProperty("properties", VmClass::getPropertyMirrors)
.addMapProperty("allProperties", VmClass::getAllPropertyMirrors)
.addTypedProperty("enclosingDeclaration", VmClass::getModuleMirror)
.addMapProperty("methods", VmClass::getMethodMirrors);
.addMapProperty("methods", VmClass::getMethodMirrors)
.addMapProperty("allMethods", VmClass::getAllMethodMirrors);
typeAliasFactory
.addTypedProperty(
@@ -164,24 +166,30 @@ public final class MirrorFactories {
propertyFactory
.addTypedProperty(
"location", property -> sourceLocationFactory.create(property.getHeaderSection()))
"location",
property -> sourceLocationFactory.create(property.getProperty().getHeaderSection()))
.addProperty(
"docComment",
property -> VmNull.lift(VmUtils.exportDocComment(property.getDocComment())))
.addListProperty("annotations", property -> VmList.create(property.getAnnotations()))
.addSetProperty("modifiers", ClassProperty::getModifierMirrors)
.addStringProperty("name", property -> property.getName().toString())
.addTypedProperty("type", ClassProperty::getTypeMirror)
property ->
VmNull.lift(VmUtils.exportDocComment(property.getProperty().getDocComment())))
.addListProperty(
"annotations", property -> VmList.create(property.getProperty().getAnnotations()))
.addListProperty("allAnnotations", property -> VmList.create(property.getAllAnnotations()))
.addSetProperty("modifiers", property -> property.getProperty().getModifierMirrors())
.addSetProperty("allModifiers", ClassProperty.Mirror::getAllModifierMirrors)
.addStringProperty("name", property -> property.getProperty().getName().toString())
.addTypedProperty("type", property -> property.getProperty().getTypeMirror())
.addProperty(
"defaultValue",
property ->
property.isAbstract()
|| property.isExternal()
|| property.getInitializer().isUndefined()
property.getProperty().isAbstract()
|| property.getProperty().isExternal()
|| property.getProperty().getInitializer().isUndefined()
? VmNull.withoutDefault()
:
// get default from prototype because it's cached there
VmUtils.readMember(property.getOwner(), property.getName()));
VmUtils.readMember(
property.getProperty().getOwner(), property.getProperty().getName()));
methodFactory
.addTypedProperty(

View File

@@ -575,7 +575,16 @@ public final class VmClass extends VmValue {
var builder = VmMap.builder();
for (var property : declaredProperties.getValues()) {
if (property.isLocal()) continue;
builder.add(property.getName().toString(), property.getMirror());
builder.add(property.getName().toString(), property.getMirror(this));
}
return builder.build();
}
public VmMap getAllPropertyMirrors() {
var builder = VmMap.builder();
for (var property : getAllProperties().getValues()) {
if (property.isLocal()) continue;
builder.add(property.getName().toString(), property.getMirror(this));
}
return builder.build();
}
@@ -589,6 +598,15 @@ public final class VmClass extends VmValue {
return builder.build();
}
public VmMap getAllMethodMirrors() {
var builder = VmMap.builder();
for (var method : getAllMethods().getValues()) {
if (method.isLocal()) continue;
builder.add(method.getName().toString(), method.getMirror());
}
return builder.build();
}
@Override
@TruffleBoundary
public PClass export() {