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

Add types for typescript #573

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
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
82 changes: 78 additions & 4 deletions tested/languages/typescript/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
from tested.datatypes import (
AdvancedNothingTypes,
AdvancedNumericTypes,
AdvancedStringTypes,
AllTypes,
BasicBooleanTypes,
BasicNothingTypes,
BasicNumericTypes,
BasicObjectTypes,
BasicSequenceTypes,
BasicStringTypes,
resolve_to_basic,
)
from tested.datatypes.advanced import AdvancedObjectTypes
from tested.languages.conventionalize import submission_file
Expand All @@ -33,6 +36,7 @@
StringType,
Value,
VariableAssignment,
VariableType,
as_basic_type,
)
from tested.testsuite import MainInput
Expand Down Expand Up @@ -129,6 +133,74 @@
return result


def convert_declaration(statement: Statement, tp: AllTypes | VariableType) -> str:
if isinstance(tp, VariableType):
return f"{tp.data}"
elif tp == AdvancedNothingTypes.UNDEFINED:
return "undefined"

Check warning on line 140 in tested/languages/typescript/generators.py

View check run for this annotation

Codecov / codecov/patch

tested/languages/typescript/generators.py#L140

Added line #L140 was not covered by tests

basic = resolve_to_basic(tp)
if basic == BasicBooleanTypes.BOOLEAN:
return "boolean"
elif basic == BasicStringTypes.TEXT:
return "string"
elif basic == BasicNumericTypes.INTEGER:
return "number"
elif basic == BasicNumericTypes.REAL:
return "number"
elif basic == BasicNothingTypes.NOTHING:
return "null"
elif basic == BasicObjectTypes.MAP:
return "object"
elif basic == BasicSequenceTypes.SEQUENCE:
type_ = "Object"

if isinstance(statement, VariableAssignment):
expression = statement.expression
else:
expression = statement

Check warning on line 161 in tested/languages/typescript/generators.py

View check run for this annotation

Codecov / codecov/patch

tested/languages/typescript/generators.py#L161

Added line #L161 was not covered by tests
if isinstance(expression, SequenceType):
type_ = {
(
convert_declaration(element, element.type)
if not isinstance(element, Identifier)
and not isinstance(element, FunctionCall)
else "id"
)
for element in expression.data
}
if "id" in type_:
type_ = "any"
else:
type_ = "|".join(type_)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you filter distinct types before doing this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type_ is a set there. So that should be fine.


return f"Array<{type_}>"
elif basic == BasicSequenceTypes.SET:
type_ = "Object"

if isinstance(statement, VariableAssignment):
expression = statement.expression
else:
expression = statement

Check warning on line 184 in tested/languages/typescript/generators.py

View check run for this annotation

Codecov / codecov/patch

tested/languages/typescript/generators.py#L184

Added line #L184 was not covered by tests
if isinstance(expression, SequenceType):
type_ = {
(
convert_declaration(element, element.type)
if not isinstance(element, Identifier)
and not isinstance(element, FunctionCall)
else "id"
)
for element in expression.data
}
if "id" in type_:
type_ = "any"
else:
type_ = "|".join(type_)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as above


return f"Set<{type_}>"
raise AssertionError(f"Unknown type: {tp!r}")

Check warning on line 201 in tested/languages/typescript/generators.py

View check run for this annotation

Codecov / codecov/patch

tested/languages/typescript/generators.py#L201

Added line #L201 was not covered by tests


def convert_statement(statement: Statement, internal=False, full=False) -> str:
if isinstance(statement, Identifier):
return statement
Expand All @@ -143,11 +215,13 @@
)
elif isinstance(statement, VariableAssignment):
if full:
prefix = "let "
else:
prefix = ""
return (
f"let {statement.variable} : {convert_declaration(statement, statement.type)} = "
f"{convert_statement(statement.expression, True)}"
)

return (
f"{prefix}{statement.variable} = "
f"{statement.variable} = "
f"{convert_statement(statement.expression, True)}"
)
raise AssertionError(f"Unknown statement: {statement!r}")
Expand Down
39 changes: 39 additions & 0 deletions tests/test_language_quircks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Tests for specific aspects of certain language implementations.
"""

import itertools
import shutil
import sys
from pathlib import Path
Expand All @@ -10,8 +11,10 @@

from tested.configs import create_bundle
from tested.datatypes import BasicBooleanTypes, BasicNumericTypes, BasicStringTypes
from tested.dsl import parse_string
from tested.languages.conventionalize import submission_name
from tested.languages.generation import generate_statement
from tested.languages.typescript.generators import convert_statement
from tested.serialisation import (
BooleanType,
FunctionCall,
Expand All @@ -23,6 +26,42 @@
from tests.manual_utils import assert_valid_output, configuration, execute_config


def test_typescript_array_typing(tmp_path: Path, pytestconfig: pytest.Config):
statement_string = "test = ['test', True, 10, 10.1, None, {'wow': 10}]"
result = convert_statement(parse_string(statement_string), full=True)
types = ["string", "boolean", "number", "object", "null"]
permutations = list(itertools.permutations(types))
valid_results = [
f'let test : Array<{"|".join(perm)}> = ["test", true, 10, 10.1, null, new Map([["wow", 10]])]'
for perm in permutations
]

assert result in valid_results


def test_typescript_set_typing(tmp_path: Path, pytestconfig: pytest.Config):
statement_string = "test = {'test', True, 10, 10.1, None, {'wow': 10}}"
result = convert_statement(parse_string(statement_string), full=True)
types = ["string", "boolean", "number", "object", "null"]
permutations = list(itertools.permutations(types))
valid_results = [
f'let test : Set<{"|".join(perm)}> = new Set(["test", true, 10, 10.1, null, new Map([["wow", 10]])])'
for perm in permutations
]

assert result in valid_results


def test_typescript_function_call_typing(tmp_path: Path, pytestconfig: pytest.Config):
statement_string = "test = {'test', True, testing(10)}"
result = convert_statement(parse_string(statement_string), full=True)
assert result == 'let test : Set<any> = new Set(["test", true, testing(10)])'

statement_string = "test = ['test', True, testing(10)]"
result = convert_statement(parse_string(statement_string), full=True)
assert result == 'let test : Array<any> = ["test", true, testing(10)]'


def test_javascript_vanilla_object(tmp_path: Path, pytestconfig: pytest.Config):
conf = configuration(
pytestconfig,
Expand Down
2 changes: 1 addition & 1 deletion tests/test_problem_statements.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def test_template_natural_type_name_nl(lang: str, tested_type: Any, expected: st
),
(
"typescript",
"let random = new Random()\nrandom.newSequence(10, 10)\n[10, 5, 2, 8, 7, 1, 3, 4, 9, 6]",
"let random : Random = new Random()\nrandom.newSequence(10, 10)\n[10, 5, 2, 8, 7, 1, 3, 4, 9, 6]",
),
],
)
Expand Down
Loading