Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -10,6 +10,7 @@
package nl.esi.xtext.expressions.tests

import com.google.inject.Inject
import java.net.URI
import java.util.Optional
import java.util.UUID
import nl.esi.xtext.expressions.conversion.IExpressionConverter
Expand All @@ -22,6 +23,7 @@ import org.eclipse.xtext.resource.XtextResourceSet
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import java.net.URISyntaxException

/**
* Tests that custom converters can be registered and used to handle
Expand All @@ -46,10 +48,12 @@ class CustomConverterTest extends ExpressionEvaluatorTestBase {
var handler = registry.getURIHandler()
resourceSet.URIConverter?.URIHandlers?.add(0, handler)

// Register the sample library
// Register the sample libraries
registry.addLibraryFunctions(SampleLibraryWithUUID)
// Add the converter
registry.addLibraryFunctions(SampleLibraryWithURI)
// Add the converters
registry.addConverter(new UUIDConverter)
registry.addConverter(new URIConverter)
initialized = true

}
Expand All @@ -73,7 +77,11 @@ class CustomConverterTest extends ExpressionEvaluatorTestBase {
Assertions.assertAll(
[Assertions.assertTrue(content.contains("function uuid fromString("), "fromString")],
[Assertions.assertTrue(content.contains("function string uuidToString("), "uuidToString")],
[Assertions.assertTrue(content.contains("function bool isValidUUID("), "isValidUUID")]
[Assertions.assertTrue(content.contains("function bool isValidUUID("), "isValidUUID")],
[Assertions.assertTrue(content.contains("function string getScheme("), "getScheme")],
[Assertions.assertTrue(content.contains("function string getHost("), "getHost")],
[Assertions.assertTrue(content.contains("function int getPort("), "getPort")],
[Assertions.assertTrue(content.contains("function string getPath("), "getPath")]
)
}

Expand All @@ -92,9 +100,13 @@ class CustomConverterTest extends ExpressionEvaluatorTestBase {
@Test
def void call_uuidToString_convertsUUIDToString() {
assertEval('''
type uuid based on string

uuid id = "550e8400-e29b-41d4-a716-446655440000"
string result = "550e8400-e29b-41d4-a716-446655440000"
''', '''
type uuid based on string

uuid id = "550e8400-e29b-41d4-a716-446655440000"
string result = uuidToString(id)
''')
Expand Down Expand Up @@ -126,6 +138,28 @@ class CustomConverterTest extends ExpressionEvaluatorTestBase {
bool result = isValidUUID("")
''')
}

@Test
def void call_getComponents_getsComponentsOfAnURI() {
assertEval('''
type uri based on string

uri github = "https://github.com:443/TNO/XPlus"
string scheme = "https"
string host = "github.com"
int port = 443
string path = "/TNO/XPlus"
''', '''
type uri based on string

uri github = "https://github.com:443/TNO/XPlus"
string scheme = getScheme(github)
string host = getHost(github)
int port = getPort(github)
string path = getPath(github)
''')
}

}

/**
Expand Down Expand Up @@ -198,15 +232,82 @@ class UUIDConverter implements IExpressionConverter {

override Optional<Expression> toExpression(Object object, Type type) {
// Only convert UUID objects
if (!(object instanceof UUID)){
if (object instanceof UUID){
// Check if target type is string-like
var context = IEvaluationContext.EMPTY;
val result = context.toExpression(object.toString)
if (result !== null) {
return Optional.of(result)
}
}
return Optional.empty()
}
}

/**
* Sample library with URI-related functions.
* This demonstrates how a library might use custom Java types
* that require converters to work with the expression language.
*/
class SampleLibraryWithURI {
def static getScheme(URI uri) {
uri.scheme
}

def static getHost(URI uri) {
uri.host
}

def static getPort(URI uri) {
uri.port
}

def static getPath(URI uri) {
uri.path
}
}

/**
* Custom converter for UUID type.
* Converts between Expression (string literals) and java.util.UUID objects.
*/
class URIConverter implements IExpressionConverter {

override Optional<Object> toObject(Expression expression, Class<?> targetType) {
// Only convert to URI type
if (!targetType.equals(URI)){
return Optional.empty()
}

// Check if target type is string-like

// Handle null
if (expression === null) {
return Optional.empty()
}

var context = IEvaluationContext.EMPTY;
val result = context.toExpression(object.toString)
if (result !== null) {
return Optional.of(result)
// Convert string expression to URI
try {
val value = context.asString(expression)
if (value === null || value.empty) {
return Optional.empty()
}
val uri = new URI(value)
return Optional.of(uri)
} catch (URISyntaxException e) {
// Invalid URI format
return Optional.empty()
}
}

override Optional<Expression> toExpression(Object object, Type type) {
// Only convert URI objects
if (object instanceof URI) {
// Check if target type is string-like
var context = IEvaluationContext.EMPTY;
val result = context.toExpression(object.toString)
if (result !== null) {
return Optional.of(result)
}
}
return Optional.empty()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,19 @@ class ExpressionEvaluatorBasicTest extends ExpressionEvaluatorTestBase {
assertEval('''
bool v_eq_null_1 = true
bool v_eq_null_2 = false
bool v_eq_null_3 = false

bool v_neq_null_1 = false
bool v_neq_null_2 = true
bool v_neq_null_3 = true
''', '''
bool v_eq_null_1 = null == null
bool v_eq_null_2 = null == 1
bool v_eq_null_3 = "" == null

bool v_neq_null_1 = null != null
bool v_neq_null_2 = null != 1
bool v_neq_null_3 = "" != null
''')
}

Expand Down Expand Up @@ -218,28 +222,28 @@ class ExpressionEvaluatorBasicTest extends ExpressionEvaluatorTestBase {
real v_add_real_1 = 3.3
real v_add_real_2 = 6.6

int v_sub_real_1 = 1.1
int v_sub_real_2 = - 2.2
int v_sub_real_3 = 1.3
real v_sub_real_1 = 1.1
real v_sub_real_2 = - 2.2
real v_sub_real_3 = 1.3
''', '''
real v_add_real_1 = 1.1 + 2.2
real v_add_real_2 = 1.1 + 2.2 + 3.3

int v_sub_real_1 = 2.2 - 1.1
int v_sub_real_2 = 2.2 - 4.4
int v_sub_real_3 = 10.10 - 5.5 - 3.3
real v_sub_real_1 = 2.2 - 1.1
real v_sub_real_2 = 2.2 - 4.4
real v_sub_real_3 = 10.10 - 5.5 - 3.3
''')
}

@Test
def void level4String() {
// Resolved variable
assertEval('''
real v_add_string_1 = "aabb"
real v_add_string_2 = "aabbcc"
string v_add_string_1 = "aabb"
string v_add_string_2 = "aabbcc"
''', '''
real v_add_string_1 = "aa" + "bb"
real v_add_string_2 = "aa" + "bb" + "cc"
string v_add_string_1 = "aa" + "bb"
string v_add_string_2 = "aa" + "bb" + "cc"
''')
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ class ExpressionEvaluatorComplexTest extends ExpressionEvaluatorTestBase {
@Test
def void expressionMinus() {
assertEval('int a = -1', 'int a = -1')
assertEval('int a = -1.0', 'int a = -1.0')
assertEval('real a = -1.0', 'real a = -1.0')
}

@Test
Expand Down Expand Up @@ -337,7 +337,7 @@ class ExpressionEvaluatorComplexTest extends ExpressionEvaluatorTestBase {
@Test
def void expressionPlus() {
assertEval('int a = 1', 'int a = +1')
assertEval('int a = 1.0', 'int a = +1.0')
assertEval('real a = 1.0', 'real a = +1.0')

// Resolved variable
assertEval('''
Expand All @@ -357,4 +357,130 @@ class ExpressionEvaluatorComplexTest extends ExpressionEvaluatorTestBase {
int b = +a
''')
}

@Test
def void expressionNullCoalescing() {
assertEval('int a = 1', 'int a = 1 ?? 2')
assertEval('real a = 2.0', 'real a = null ?? 2.0')

// Resolved variable
assertEval('''
int a = 1
int b = null
int c = 1

int x = null
int y = 5
int z = 5
''', '''
int a = 1
int b = null
int c = a ?? b

int x = null
int y = 5
int z = x ?? y
''')

// Unresolved variable
assertEval('''
int a
int b = 1
int c = a ?? 1

int x = 4
int y
int z = 4
''', '''
int a
int b = 1
int c = a ?? b

int x = 4
int y
int z = x ?? y
''')
}

@Test
def void expressionConditional() {
assertEval('int a = 1', 'int a = true ? 1 : 2')
assertEval('real a = 2.0', 'real a = false ? null : 2.0')

// Resolved variable
assertEval('''
bool a = true
int b = 1
int c = 2
int d = 1

bool f = true
int g = null
int h = 2
int i = null

bool j = false
int k = 1
int l = null
int m = null

bool w = null
int x = 1
int y = 2
int z = null ? 1 : 2
''', '''
bool a = true
int b = 1
int c = 2
int d = a ? b : c

bool f = true
int g = null
int h = 2
int i = f ? g : h

bool j = false
int k = 1
int l = null
int m = j ? k : l

bool w = null
int x = 1
int y = 2
int z = w ? x : y
''')

// Unresolved variable
assertEval('''
bool a
int b = 1
int c = 2
int d = a ? 1 : 2

bool f = true
int g
int h = 2
int i = g

bool j = false
int k = 1
int l
int m = l
''', '''
bool a
int b = 1
int c = 2
int d = a ? b : c

bool f = true
int g
int h = 2
int i = f ? g : h

bool j = false
int k = 1
int l
int m = j ? k : l
''')
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class ExpressionEvaluatorFunctionTest extends ExpressionEvaluatorTestBase {
tss = <string[]> [ "Hello", "Test!" ]
}
bool contains = contains(t.tss, "Hello")
bool notContains = contains(t.tis, "1")
bool notContains = contains(t.tis, 1)
''')
}

Expand Down
Loading
Loading