Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show only fields from current atom constructor in the debugger #11217

Merged
merged 27 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ff97a48
Enable ignored tests
Akirathan Sep 30, 2024
c47b5f2
Atom members do not include field getters for other constructors
Akirathan Oct 6, 2024
f076972
FieldGetter node's name does not include type
Akirathan Oct 6, 2024
2f58cc1
Remove unused imports
Akirathan Oct 6, 2024
a7389a6
MethodRootNode.name is only method name without type
Akirathan Oct 6, 2024
73b1586
Field getter nodes has a base node
Akirathan Oct 6, 2024
9b55586
atom fields and methods are readable
Akirathan Oct 6, 2024
5244129
Test that atom fields and methods are readable
Akirathan Oct 6, 2024
70c9e78
Merge branch 'develop' into wip/akirathan/10675-debugger-atom-fields
Akirathan Oct 6, 2024
a4b2c68
fmt
Akirathan Oct 6, 2024
dc228b8
Revert changes to MethodRootNode name
Akirathan Oct 8, 2024
71366f1
Stream methods are hidden behind TruffleBoundary
Akirathan Oct 8, 2024
bce3e9e
Update method names in tests
Akirathan Oct 8, 2024
d979136
fmt
Akirathan Oct 8, 2024
3939783
Revert MethodRootNode qualifiedName
Akirathan Oct 8, 2024
7c1cdf7
Reorder actual and expected parameters in TypeMembersTest
Akirathan Oct 8, 2024
0b6b4e8
Atom member methods have simple name
Akirathan Oct 8, 2024
ed8c984
Instance method include those from type scope
Akirathan Oct 8, 2024
c9992bd
All readable members are invocable
Akirathan Oct 8, 2024
f9467cf
Update AtomInteropTests
Akirathan Oct 8, 2024
3ae5ba1
Update TypeMembersTest.
Akirathan Oct 8, 2024
7af209b
Fix typo in Atom.readMember.
Akirathan Oct 10, 2024
52de4dd
private methods are also readable
Akirathan Oct 11, 2024
97b411f
private members can be read
Akirathan Oct 11, 2024
1e0f1ca
Remove duplicate test
Akirathan Oct 11, 2024
ceca6d1
private fields are accessible via polyglot - update test.
Akirathan Oct 11, 2024
c902ccd
Update docs
Akirathan Oct 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;

import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import org.enso.test.utils.ContextUtils;
import org.graalvm.polyglot.Context;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

/**
Expand Down Expand Up @@ -90,7 +95,6 @@ public void typeHasAnyAsSuperType() {
assertThat(anyType.getMetaSimpleName(), is("Any"));
}

@Ignore("https://github.com/enso-org/enso/issues/10675")
@Test
public void atomMembersAreConstructorFields_ManyConstructors() {
var myTypeAtom =
Expand All @@ -110,6 +114,242 @@ public void atomMembersAreConstructorFields_ManyConstructors() {
containsInAnyOrder("g1", "g2", "g3"));
}

@Test
public void methodIsAtomMember() {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
type My_Type
Cons a b
method self = 42

main = My_Type.Cons "a" "b"
""");
assertThat("Method is a member of the atom", myTypeAtom.getMemberKeys(), hasItem("method"));
assertThat("method is an invokable member", myTypeAtom.canInvokeMember("method"), is(true));
}

@Test
public void methodIsAtomMember_InteropLibrary() {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
type My_Type
Cons a b
method self = 42

main = My_Type.Cons "a" "b"
""");
var atom = ContextUtils.unwrapValue(ctx, myTypeAtom);
var interop = InteropLibrary.getUncached();
assertThat("Atom has members", interop.hasMembers(atom), is(true));
assertThat("Method is readable", interop.isMemberReadable(atom, "method"), is(true));
assertThat("Method is invocable", interop.isMemberInvocable(atom, "method"), is(true));
assertThat("Field is readable", interop.isMemberReadable(atom, "a"), is(true));
}

@Test
public void fieldsFromPrivateConstructorAreInternalMembers() {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
type My_Type
private Cons a

main = My_Type.Cons "a"
""");
var atom = ContextUtils.unwrapValue(ctx, myTypeAtom);
var interop = InteropLibrary.getUncached();
assertThat("field a is internal", interop.isMemberInternal(atom, "a"), is(true));
}

@Test
public void fieldFromPrivateConstructorIsReadable() {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
type My_Type
private Cons a

main = My_Type.Cons "a"
""");
ContextUtils.executeInContext(
ctx,
() -> {
var atom = ContextUtils.unwrapValue(ctx, myTypeAtom);
var interop = InteropLibrary.getUncached();
assertThat(
"Field from private constructor is readable",
interop.isMemberReadable(atom, "a"),
is(true));
assertThat(
"Field from private constructor is invocable",
interop.isMemberInvocable(atom, "a"),
is(true));
assertThat(
"Field from private constructor can be read",
interop.asString(interop.readMember(atom, "a")),
is("a"));
assertThat(
"Field from private constructor can be invoked",
interop.asString(interop.invokeMember(atom, "a")),
is("a"));
return null;
});
}

@Test
public void allMethodsAreInternalMembers() {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
type My_Type
Cons a
pub_method self = 42
private priv_method self = 42

main = My_Type.Cons "a"
""");
var atom = ContextUtils.unwrapValue(ctx, myTypeAtom);
var interop = InteropLibrary.getUncached();
assertThat(
"public method is internal member", interop.isMemberInternal(atom, "pub_method"), is(true));
assertThat(
"private method is internal member",
interop.isMemberInternal(atom, "priv_method"),
is(true));
}

@Test
public void allMembersAreReadableAndInvocable()
throws UnsupportedMessageException, InvalidArrayIndexException {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
type My_Type
Cons a
pub_method self = 42
private priv_method self = 42

main = My_Type.Cons "a"
""");
var atom = ContextUtils.unwrapValue(ctx, myTypeAtom);
var interop = InteropLibrary.getUncached();
var members = interop.getMembers(atom, true);
for (long i = 0; i < interop.getArraySize(members); i++) {
var memberName = interop.asString(interop.readArrayElement(members, i));
assertThat(
"Member " + memberName + " should be readable",
interop.isMemberReadable(atom, memberName),
is(true));
assertThat(
"Member " + memberName + " should be invocable",
interop.isMemberInvocable(atom, memberName),
is(true));
}
}

@Test
public void constructorIsNotAtomMember() {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
type My_Type
Cons a b
method self = 42

main = My_Type.Cons "a" "b"
""");
assertThat("Cons is not atom member", myTypeAtom.getMemberKeys(), not(hasItem("Cons")));
}

@Test
public void fieldIsInvocable() {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
type My_Type
Cons a b

main = My_Type.Cons 1 2
""");
ContextUtils.executeInContext(
ctx,
() -> {
var atom = ContextUtils.unwrapValue(ctx, myTypeAtom);
var interop = InteropLibrary.getUncached();
assertThat("Field a is invocable", interop.isMemberInvocable(atom, "a"), is(true));
var aField = interop.invokeMember(atom, "a");
assertThat("Field is a number", interop.asInt(aField), is(1));
assertThat("Field b is invocable", interop.isMemberInvocable(atom, "b"), is(true));
return null;
});
}

@Test
public void fieldIsReadable() {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
type My_Type
Cons a

main = My_Type.Cons 1
""");
ContextUtils.executeInContext(
ctx,
() -> {
var atom = ContextUtils.unwrapValue(ctx, myTypeAtom);
var interop = InteropLibrary.getUncached();
assertThat("Field a is readable", interop.isMemberReadable(atom, "a"), is(true));
return null;
});
}

@Test
public void staticMethodIsNotAtomMember() {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
type My_Type
Cons
static_method = 42

main = My_Type.Cons
""");
assertThat(
"Static method is not atom member",
myTypeAtom.getMemberKeys(),
not(hasItem(containsString("static_method"))));
}

@Test
public void constructorIsNotAtomMember_InteropLibrary() {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
type My_Type
Cons a b
method self = 42

main = My_Type.Cons "a" "b"
""");
var atom = ContextUtils.unwrapValue(ctx, myTypeAtom);
var interop = InteropLibrary.getUncached();
assertThat("Cons is not atom member", interop.isMemberExisting(atom, "Cons"), is(false));
}

@Test
public void typeMembersAreConstructors() {
var myType =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

public class DebuggingEnsoTest {
Expand Down Expand Up @@ -483,7 +482,6 @@ public void testAtomFieldsAreReadable() {
}
}

@Ignore("https://github.com/enso-org/enso/issues/10675")
@Test
public void testAtomFieldAreReadable_MultipleConstructors() {
var fooFunc =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.net.URI;
import java.util.Set;
import org.enso.test.utils.ContextUtils;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.PolyglotException;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;
import org.junit.After;
Expand Down Expand Up @@ -78,10 +76,9 @@ public void checkAtomMembers() throws Exception {
assertEquals("seven check", 7, seven.asInt());
assertEquals("three check", 3, three.asInt());

assertMembers("Keys in list1", false, headAtom, "head", "tail", "is_empty");
assertMembers("Keys in list2", false, endAtom, "head", "tail", "is_empty");
assertMembers("Keys in list1", false, headAtom, "h", "t");
assertMembers("Keys in list2", true, endAtom, "h", "t");
assertMembers("Keys in list1", headAtom, "head", "tail", "is_empty");
assertMembers("Keys in list2", endAtom, "head", "tail", "is_empty");
assertMembers("Keys in list1", headAtom, "h", "t");
}

@Test
Expand All @@ -105,24 +102,15 @@ public void ensureNonBuiltinMembersArePresent() throws Exception {

var module = ctx.eval(src);
var compileError = module.invokeMember("eval_expression", "v");
assertEquals("all members", compileError.getMemberKeys(), Set.of("to_display_text", "message"));
assertEquals("all members", Set.of("to_display_text", "message"), compileError.getMemberKeys());
}

private static void assertMembers(String msg, boolean invokeFails, Value v, String... keys) {
private static void assertMembers(String msg, Value v, String... keys) {
var realKeys = v.getMemberKeys();
for (var k : keys) {
assertTrue(msg + " - found " + k + " in " + realKeys, realKeys.contains(k));
assertTrue(msg + " - has member " + k, v.hasMember(k));
if (invokeFails) {
try {
v.invokeMember(k);
fail("Invoking " + k + " on " + v + " shall fail");
} catch (PolyglotException ex) {
assertEquals("Field `" + k + "` of IntList could not be found.", ex.getMessage());
}
} else {
assertNotNull(msg + " - can be invoked", v.invokeMember(k));
}
assertNotNull(msg + " - can be invoked", v.invokeMember(k));
}
}
}
Loading
Loading