Merge pull request #631 from cincheo/feature/613_Optional_support_jsweet2

fix #613 Optional support
This commit is contained in:
Louis Grignon 2020-11-27 15:13:15 +01:00 committed by GitHub
commit b61de98c5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 2039 additions and 1869 deletions

View File

@ -48,6 +48,7 @@ import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
@ -68,6 +69,7 @@ import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Types;
@ -1562,30 +1564,6 @@ public class JSweetContext extends Context {
return defaultValue;
}
// /**
// * Gets the value of the given annotation property.
// *
// * @param annotation
// * the annotation
// * @param propertyName
// * the name of the annotation property to get the value of
// * @param defaultValue
// * the value to return if not found
// */
// @SuppressWarnings("unchecked")
// private static <T> T getAnnotationValue(AnnotationMirror annotation,
// String propertyName, T defaultValue) {
// for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue>
// annoProperty : annotation
// .getElementValues().entrySet()) {
// if
// (annoProperty.getKey().getSimpleName().toString().equals(propertyName)) {
// return (T) annoProperty.getValue().getValue();
// }
// }
// return defaultValue;
// }
/**
* Gets the symbol's annotation that correspond to the given annotation type
* name if exists.
@ -1599,19 +1577,6 @@ public class JSweetContext extends Context {
return null;
}
// /**
// * Gets the annotation tree that matches the given type name.
// */
// private static JCAnnotation getAnnotation(List<JCAnnotation> annotations,
// String annotationType) {
// for (JCAnnotation a : annotations) {
// if (annotationType.equals(a.type.toString())) {
// return a;
// }
// }
// return null;
// }
/**
* Grabs the names of all the support interfaces in the class and interface
* hierarchy.
@ -1947,4 +1912,7 @@ public class JSweetContext extends Context {
}
}
public Elements elements() {
return JavacElements.instance(this);
}
}

View File

@ -1315,11 +1315,8 @@ public class Java2TypeScriptAdapter extends PrinterAdapter {
print(")");
}
} else {
printMacroName(targetMethodName);
print("(<any>((o1: any, o2: any) => { if(o1 && o1.equals) { return o1.equals(o2); } else { return o1 === o2; } })(");
printTarget(invocationElement.getTargetExpression()).print(",")
.print(invocationElement.getArgument(0));
print("))");
printDefaultEquals(invocationElement.getTargetExpression(),
invocationElement.getArgument(0));
}
return true;
case "compareTo":
@ -1412,6 +1409,12 @@ public class Java2TypeScriptAdapter extends PrinterAdapter {
.print(target).print(")");
}
}
protected void printDefaultEquals(ExtendedElement left, ExtendedElement right) {
print("(<any>((o1: any, o2: any) => o1 && o1.equals ? o1.equals(o2) : o1 === o2)(");
printTarget(left).print(",").print(right);
print("))");
}
protected void printFunctionalInvocation2(ExtendedElement target, String functionName,
List<ExtendedElement> arguments) {
@ -1677,4 +1680,5 @@ public class Java2TypeScriptAdapter extends PrinterAdapter {
return super.substituteForEachLoop(foreachLoop, targetHasLength, indexVarName);
}
}

View File

@ -33,7 +33,6 @@ public interface Util {
* Gets the type from an existing runtime class when possible (return null
* when the type cannot be found in the compiler's symbol table).
* <p/>
* This method only looks up well-known Java types.
*/
TypeMirror getType(Class<?> clazz);

View File

@ -125,6 +125,12 @@ public class UtilSupport implements Util {
case "java.util.List":
return context.symtab.listType;
}
TypeElement typeElement = context.elements().getTypeElement(clazz.getName());
if (typeElement != null) {
return typeElement.asType();
}
return null;
}

1
transpiler/src/test/java/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/source/

View File

@ -40,6 +40,7 @@ import source.api.ForeachIteration;
import source.api.J4TSInvocations;
import source.api.JdkInvocations;
import source.api.Numbers;
import source.api.Optionals;
import source.api.PrimitiveInstantiation;
import source.api.PromisesAsyncAwait;
import source.api.QualifiedInstantiation;
@ -49,244 +50,246 @@ import source.api.WrongJdkInvocations;
public class ApiTests extends AbstractTest {
// J4TS messes up with forbidden invocations...
@Ignore
@Test
public void testWrongJdkInvocations() {
transpile(logHandler -> {
// assertEquals(11, logHandler.reportedProblems.size());
assertEquals(19, logHandler.reportedSourcePositions.get(0).getStartLine());
assertEquals(39, logHandler.reportedSourcePositions.get(1).getStartLine());
// assertEquals(41,
// logHandler.reportedSourcePositions.get(2).getStartLine());
assertEquals(48, logHandler.reportedSourcePositions.get(3).getStartLine());
assertEquals(52, logHandler.reportedSourcePositions.get(4).getStartLine());
assertEquals(72, logHandler.reportedSourcePositions.get(5).getStartLine());
// assertEquals(78,
// logHandler.reportedSourcePositions.get(6).getStartLine());
// assertEquals(83,
// logHandler.reportedSourcePositions.get(7).getStartLine());
assertEquals(87, logHandler.reportedSourcePositions.get(8).getStartLine());
assertEquals(97, logHandler.reportedSourcePositions.get(9).getStartLine());
assertEquals(118, logHandler.reportedSourcePositions.get(10).getStartLine());
// assertEquals(120,
// logHandler.reportedSourcePositions.get(11).getStartLine());
assertEquals(127, logHandler.reportedSourcePositions.get(12).getStartLine());
assertEquals(131, logHandler.reportedSourcePositions.get(13).getStartLine());
}, getSourceFile(J4TSInvocations.class), getSourceFile(WrongJdkInvocations.class));
}
// J4TS messes up with forbidden invocations...
@Ignore
@Test
public void testWrongJdkInvocations() {
transpile(logHandler -> {
// assertEquals(11, logHandler.reportedProblems.size());
assertEquals(19, logHandler.reportedSourcePositions.get(0).getStartLine());
assertEquals(39, logHandler.reportedSourcePositions.get(1).getStartLine());
// assertEquals(41,
// logHandler.reportedSourcePositions.get(2).getStartLine());
assertEquals(48, logHandler.reportedSourcePositions.get(3).getStartLine());
assertEquals(52, logHandler.reportedSourcePositions.get(4).getStartLine());
assertEquals(72, logHandler.reportedSourcePositions.get(5).getStartLine());
// assertEquals(78,
// logHandler.reportedSourcePositions.get(6).getStartLine());
// assertEquals(83,
// logHandler.reportedSourcePositions.get(7).getStartLine());
assertEquals(87, logHandler.reportedSourcePositions.get(8).getStartLine());
assertEquals(97, logHandler.reportedSourcePositions.get(9).getStartLine());
assertEquals(118, logHandler.reportedSourcePositions.get(10).getStartLine());
// assertEquals(120,
// logHandler.reportedSourcePositions.get(11).getStartLine());
assertEquals(127, logHandler.reportedSourcePositions.get(12).getStartLine());
assertEquals(131, logHandler.reportedSourcePositions.get(13).getStartLine());
}, getSourceFile(J4TSInvocations.class), getSourceFile(WrongJdkInvocations.class));
}
@Test
public void testJ4TSInvocations() {
// with J4TS
transpilerTest().getTranspiler().setUsingJavaRuntime(true);
eval(ModuleKind.none, (logHandler, result) -> {
logHandler.assertNoProblems();
}, getSourceFile(J4TSInvocations.class));
// without J4TS
@Test
public void testJ4TSInvocations() {
// with J4TS
transpilerTest().getTranspiler().setUsingJavaRuntime(true);
eval(ModuleKind.none, (logHandler, result) -> {
logHandler.assertNoProblems();
}, getSourceFile(J4TSInvocations.class));
// without J4TS
transpilerTest().getTranspiler().setUsingJavaRuntime(false);
eval(ModuleKind.none, (logHandler, result) -> {
logHandler.assertNoProblems();
}, getSourceFile(J4TSInvocations.class));
}
}
@Test
public void testJdkInvocations() {
eval(ModuleKind.none, (logHandler, result) -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
assertEquals("test", result.<String>get("s1"));
assertEquals("m1", result.<String>get("s2"));
assertEquals("e", result.<String>get("s3"));
assertEquals("testc", result.<String>get("s4"));
assertEquals(2, result.<Number>get("i1").intValue());
assertEquals(-1, result.<Number>get("i2").intValue());
assertEquals(4, result.<Number>get("l").intValue());
assertEquals("t1st", result.<String>get("r"));
}, getSourceFile(JdkInvocations.class));
}
@Test
public void testJdkInvocations() {
eval(ModuleKind.none, (logHandler, result) -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
assertEquals("test", result.<String>get("s1"));
assertEquals("m1", result.<String>get("s2"));
assertEquals("e", result.<String>get("s3"));
assertEquals("testc", result.<String>get("s4"));
assertEquals(2, result.<Number>get("i1").intValue());
assertEquals(-1, result.<Number>get("i2").intValue());
assertEquals(4, result.<Number>get("l").intValue());
assertEquals("t1st", result.<String>get("r"));
}, getSourceFile(JdkInvocations.class));
}
@Test
public void testThreadLocal() {
eval((logHandler, result) -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
assertEquals("coucou", result.get("out"));
assertEquals("nakach", result.get("out2"));
assertEquals("nakach", result.get("out3"));
}, getSourceFile(ThreadLocalFake.class));
}
@Test
public void testThreadLocal() {
eval((logHandler, result) -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
assertEquals("coucou", result.get("out"));
assertEquals("nakach", result.get("out2"));
assertEquals("nakach", result.get("out3"));
}, getSourceFile(ThreadLocalFake.class));
}
@Test
public void testPromisesAsyncAwaits() {
eval((logHandler, result) -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
@Test
public void testPromisesAsyncAwaits() {
eval((logHandler, result) -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
// async await style
assertNotNull(result.get("t0"));
assertNotNull(result.get("t1"));
assertNotNull(result.get("t2"));
// async await style
assertNotNull(result.get("t0"));
assertNotNull(result.get("t1"));
assertNotNull(result.get("t2"));
long t0 = result.<Number>get("t0").longValue();
long t1 = result.<Number>get("t1").longValue();
long t2 = result.<Number>get("t2").longValue();
long t0 = result.<Number>get("t0").longValue();
long t1 = result.<Number>get("t1").longValue();
long t2 = result.<Number>get("t2").longValue();
assertTrue(t1 - t0 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS);
assertTrue(t2 - t1 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS);
assertTrue(t1 - t0 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS);
assertTrue(t2 - t1 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS);
assertEquals(new Integer(42), result.get("r1"));
assertEquals("my answer", result.get("r2"));
assertEquals("supermessage", result.get("e"));
assertEquals(new Integer(42), result.get("r1"));
assertEquals("my answer", result.get("r2"));
assertEquals("supermessage", result.get("e"));
// promise style
assertNotNull(result.get("2_t0"));
assertNotNull(result.get("2_t1"));
assertNotNull(result.get("2_t2"));
// promise style
assertNotNull(result.get("2_t0"));
assertNotNull(result.get("2_t1"));
assertNotNull(result.get("2_t2"));
t0 = result.<Number>get("2_t0").longValue();
t1 = result.<Number>get("2_t1").longValue();
t2 = result.<Number>get("2_t2").longValue();
t0 = result.<Number>get("2_t0").longValue();
t1 = result.<Number>get("2_t1").longValue();
t2 = result.<Number>get("2_t2").longValue();
assertTrue(t1 - t0 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS);
assertTrue(t2 - t1 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS);
assertTrue(t1 - t0 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS);
assertTrue(t2 - t1 >= PromisesAsyncAwait.WAIT_BETWEEN_STEPS_MS);
assertEquals(new Integer(42), result.get("2_r1"));
assertEquals("my answer", result.get("2_r2"));
assertEquals("supermessage", result.get("2_e"));
assertTrue(result.get("subMethod1"));
assertTrue(result.get("subMethod2"));
assertEquals("subMethod2", result.get("resultSubMethod2"));
}, getSourceFile(PromisesAsyncAwait.class));
}
assertEquals(new Integer(42), result.get("2_r1"));
assertEquals("my answer", result.get("2_r2"));
assertEquals("supermessage", result.get("2_e"));
@Test
public void testForeachIteration() {
eval((logHandler, r) -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
Assert.assertEquals("Wrong behavior output trace", "abc", r.get("out"));
}, getSourceFile(ForeachIteration.class));
}
assertTrue(result.get("subMethod1"));
assertTrue(result.get("subMethod2"));
assertEquals("subMethod2", result.get("resultSubMethod2"));
@Test
public void testPrimitiveInstantiation() {
transpile(logHandler -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
}, getSourceFile(PrimitiveInstantiation.class));
}
}, getSourceFile(PromisesAsyncAwait.class));
}
@Test
public void testAccessStaticMethod() {
transpile(logHandler -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
}, getSourceFile(AccessStaticMethod.class));
}
@Test
public void testForeachIteration() {
eval((logHandler, r) -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
Assert.assertEquals("Wrong behavior output trace", "abc", r.get("out"));
}, getSourceFile(ForeachIteration.class));
}
@Test
public void testQualifiedInstantiation() {
transpile(logHandler -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
}, getSourceFile(QualifiedInstantiation.class));
}
@Test
public void testPrimitiveInstantiation() {
transpile(logHandler -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
}, getSourceFile(PrimitiveInstantiation.class));
}
@Test
public void testCastMethods() {
transpile(logHandler -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
}, getSourceFile(CastMethods.class));
}
@Test
public void testAccessStaticMethod() {
transpile(logHandler -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
}, getSourceFile(AccessStaticMethod.class));
}
@Test
public void testErasingJava() {
transpile(logHandler -> {
logHandler.assertNoProblems();
}, getSourceFile(ErasingJava.class));
}
@Test
public void testQualifiedInstantiation() {
transpile(logHandler -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
}, getSourceFile(QualifiedInstantiation.class));
}
@Test
public void testStrings() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
Assert.assertEquals(
"b,bc,c,bc,3,true,ab,32,b,0,false,true,source.api.Strings,Strings,abc,cdcdcd,true,false,true,false,true,true,false,a,aa",
r.get("trace"));
}, getSourceFile(Strings.class));
}
@Test
public void testCastMethods() {
transpile(logHandler -> {
Assert.assertEquals("There should be no errors", 0, logHandler.reportedProblems.size());
}, getSourceFile(CastMethods.class));
}
@Test
public void testCharacters() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
@Test
public void testErasingJava() {
transpile(logHandler -> {
logHandler.assertNoProblems();
}, getSourceFile(ErasingJava.class));
}
assertEquals(true, r.get("switch_int"));
assertEquals(true, r.get("switch_char"));
assertEquals(true, r.get("switch_char_cast_int"));
assertEquals(true, r.get("switch_char_cast_char"));
assertEquals(true, r.get("switch_int_cast_int"));
assertEquals(true, r.get("switch_int_cast_char"));
@Test
public void testStrings() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
Assert.assertEquals(
"b,bc,c,bc,3,true,ab,32,b,0,false,true,source.api.Strings,Strings,abc,cdcdcd,true,false,true,false,true,true,false,a,aa",
r.get("trace"));
}, getSourceFile(Strings.class));
}
}, getSourceFile(Characters.class));
}
@Test
public void testCharacters() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
@Test
public void testNumbers() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
}, getSourceFile(Numbers.class));
}
assertEquals(true, r.get("switch_int"));
assertEquals(true, r.get("switch_char"));
assertEquals(true, r.get("switch_char_cast_int"));
assertEquals(true, r.get("switch_char_cast_char"));
assertEquals(true, r.get("switch_int_cast_int"));
assertEquals(true, r.get("switch_int_cast_char"));
@Test
public void testBooleans() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
}, getSourceFile(Booleans.class));
}
}, getSourceFile(Characters.class));
}
@Test
public void testArrayBuffers() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
Assert.assertEquals("0,0,1", r.get("trace"));
}, getSourceFile(ArrayBuffers.class));
}
@Test
public void testNumbers() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
}, getSourceFile(Numbers.class));
}
@Test
public void testExpressionBuilder() {
// evalWithJavaSupport((logHandler, r) -> {
// logHandler.assertNoProblems();
// Assert.assertEquals(30, (int) r.get("result"));
// Assert.assertEquals(30, (int) r.get("result2"));
// }, getSourceFile(ExpressionBuilderTest.class),
// getSourceFile(ExpressionBuilderTest2.class));
eval((logHandler, r) -> {
logHandler.assertNoProblems();
Assert.assertEquals(30, (int) r.get("result"));
}, getSourceFile(ExpressionBuilderTest.class));
eval((logHandler, r) -> {
logHandler.assertNoProblems();
Assert.assertEquals(30, (int) r.get("result2"));
}, getSourceFile(ExpressionBuilderTest2.class));
}
@Test
public void testEquals() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
Assert.assertEquals("false,true,false,true,false,true,false,false,true", r.get("trace"));
}, getSourceFile(Equals.class));
}
@Test
public void testBooleans() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
}, getSourceFile(Booleans.class));
}
@Test
public void testDates() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
@Test
public void testArrayBuffers() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
Assert.assertEquals("0,0,1", r.get("trace"));
}, getSourceFile(ArrayBuffers.class));
}
@Test
public void testExpressionBuilder() {
// evalWithJavaSupport((logHandler, r) -> {
// logHandler.assertNoProblems();
// Assert.assertEquals(30, (int) r.get("result"));
// Assert.assertEquals(30, (int) r.get("result2"));
// }, getSourceFile(ExpressionBuilderTest.class),
// getSourceFile(ExpressionBuilderTest2.class));
eval((logHandler, r) -> {
logHandler.assertNoProblems();
Assert.assertEquals(30, (int) r.get("result"));
}, getSourceFile(ExpressionBuilderTest.class));
eval((logHandler, r) -> {
logHandler.assertNoProblems();
Assert.assertEquals(30, (int) r.get("result2"));
}, getSourceFile(ExpressionBuilderTest2.class));
}
@Test
public void testEquals() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
Assert.assertEquals("false,true,false,true,false,true,false,false,true", r.get("trace"));
}, getSourceFile(Equals.class));
}
@Test
public void testDates() {
eval(ModuleKind.none, (logHandler, r) -> {
logHandler.assertNoProblems();
System.out.println("result = " + r.get("localeString"));
assertTrue(asList(
"1/1/2020, 1:00:00 AM",
"2020-1-1 1:00:00 AM").contains(
r.get("localeString")));
}, getSourceFile(Dates.class));
}
assertTrue(asList("1/1/2020, 1:00:00 AM", "2020-1-1 1:00:00 AM").contains(r.get("localeString")));
}, getSourceFile(Dates.class));
}
@Test
public void testOptional() {
eval((logHandler, result) -> {
logHandler.assertNoProblems();
}, getSourceFile(Optionals.class));
}
}

View File

@ -0,0 +1,103 @@
package source.api;
import java.util.Optional;
import def.js.Error;
public class Optionals {
private static final String PREFERRED_VALUE = "c'est la vie";
public static void main(String[] args) {
}
static void executePresentTests() {
Optional<String> o = Optional.of(PREFERRED_VALUE);
assertContains(o, PREFERRED_VALUE);
o = Optional.ofNullable(PREFERRED_VALUE);
assertContains(o, PREFERRED_VALUE);
assert !o.equals(Optional.ofNullable(null));
assertContains(o.filter((current) -> current == PREFERRED_VALUE), PREFERRED_VALUE);
assertEmpty(o.filter((current) -> current == "XXXC'est la vie"));
assertContains(o.flatMap(current -> Optional.of("new")), "new");
assertContains(o.map(current -> "new2"), "new2");
String v = o.orElse("defaultVal");
assert v == PREFERRED_VALUE;
v = o.orElseGet(() -> "defaultVal2");
assert v == PREFERRED_VALUE;
String[] modifiedForPresent = { "", "" };
o.ifPresent(__ -> modifiedForPresent[0] = "modified");
assert modifiedForPresent[0] == "modified";
assert modifiedForPresent[1] == "modified";
// TODO
// Object[] valsAfterStream = o.stream().toArray();
}
static void executeAbsentTests() {
Optional<String> o = Optional.empty();
assertEmpty(o);
o = Optional.ofNullable(null);
assertEmpty(o);
assert o.equals(Optional.ofNullable(null));
boolean caught = false;
try {
o = Optional.of(null);
} catch (Error e) {
caught = true;
}
assert caught;
String v = o.orElse("defaultVal");
assert v == "defaultVal";
v = o.orElseGet(() -> "defaultVal2");
assert v == "defaultVal2";
final String[] modified = { "", "" };
o.ifPresent(__ -> modified[0] = "what");
assert modified[0] == "";
assert modified[1] == "valid";
}
static <T> void assertContains(Optional<T> o, T value) {
assert o.get() == value;
assert o.isPresent();
o.orElseThrow(() -> new MyMissingError());
}
static void assertEmpty(Optional<?> o) {
assert !o.isPresent();
assert o != null;
boolean caught = false;
try {
o.get();
} catch (Error e) {
caught = true;
}
assert caught;
caught = false;
try {
o.orElseThrow(() -> new MyMissingError());
} catch (MyMissingError e) {
caught = true;
}
assert caught;
}
}
class MyMissingError extends def.js.Error {
}