Skip to content

Commit

Permalink
Fix for #199
Browse files Browse the repository at this point in the history
- Also adds type check support for it
- Emoji fix in CLI
  • Loading branch information
kaleidawave committed Aug 29, 2024
1 parent e69e2c5 commit 523bf16
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 18 deletions.
21 changes: 11 additions & 10 deletions .github/workflows/examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,25 @@ jobs:

- name: Run checker on example files
shell: bash
continue-on-error: true
run: |
files=(
"https://jsr.io/@yossydev/hello-world/1.0.0/index.ts"
"https://jsr.io/@bengineering/shuffle-binary/0.0.1/index.ts"
"https://jsr.io/@bengineering/mulberry32/0.0.1/mod.ts"
"https://jsr.io/@luca/cases/1.0.0/mod.ts"
"https://jsr.io/@std/assert/1.0.2/assertion_error.ts"
"https://jsr.io/@std/text/1.0.3/levenshtein_distance.ts"
"https://jsr.io/@gnome/monads/0.0.0/src/option.ts"
"https://raw.githubusercontent.com/getify/deePool/master/src/deePool.js"
"https://raw.githubusercontent.com/silen-z/fiveway/main/packages/fiveway/src/id.ts"
https://jsr.io/@yossydev/hello-world/1.0.0/index.ts
https://jsr.io/@bengineering/shuffle-binary/0.0.1/index.ts
https://jsr.io/@bengineering/mulberry32/0.0.1/mod.ts
https://jsr.io/@luca/cases/1.0.0/mod.ts
https://jsr.io/@std/assert/1.0.2/assertion_error.ts
https://jsr.io/@std/text/1.0.3/levenshtein_distance.ts
https://jsr.io/@gnome/monads/0.0.0/src/option.ts
https://raw.githubusercontent.com/getify/deePool/master/src/deePool.js
https://raw.githubusercontent.com/silen-z/fiveway/main/packages/fiveway/src/id.ts
)
for url in "${files[@]}"; do
header="--- $url ---"
echo $header
curl -s $url > temp.ts
./target/release/ezno check temp.ts --timings
./target/release/ezno check temp.ts --timings || true
echo "${header//?/-}"
echo ""
done
18 changes: 17 additions & 1 deletion checker/specification/specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -3263,6 +3263,22 @@ doThingWithX(new Y())

- Argument of type [Y] { a: 2 } is not assignable to parameter of type X

#### Generics to constructor

```ts
class Box<T> {
value: T;

constructor(value: T) {
this.value = value;
}
}

const myBox = new Box<number>("hi");
```

- Argument of type "hi" is not assignable to parameter of type number

### Types

#### Non existent type
Expand Down Expand Up @@ -3696,7 +3712,7 @@ type GetPrefix<S, End> = S extends `${infer T} ${End}` ? T : false;

- Expected "Hello", found 4

#### `infer ... extends ...`
#### Infer with extends clause

```ts
type X<T> = T extends { a: infer I extends string } ? I : string;
Expand Down
24 changes: 23 additions & 1 deletion checker/src/features/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,29 @@ where
let mut function_environment = base_environment.new_lexical_environment(Scope::Function(scope));

if function.has_body() {
let type_parameters = function.type_parameters(&mut function_environment, checking_data);
let type_parameters = if let Some((ref prototype, _)) = constructor {
// Class generics here
checking_data.types.get_type_by_id(*prototype).get_parameters().map(|parameters| {
parameters
.into_iter()
.map(|ty| {
let Type::RootPolyType(PolyNature::StructureGeneric { name, .. }) =
checking_data.types.get_type_by_id(ty)
else {
unreachable!()
};
crate::types::generics::GenericTypeParameter {
name: name.clone(),
// Using its associated [`Type`], its restriction can be found
type_id: ty,
default: None,
}
})
.collect()
})
} else {
function.type_parameters(&mut function_environment, checking_data)
};

// TODO should be in function, but then requires mutable environment :(
let this_constraint =
Expand Down
7 changes: 5 additions & 2 deletions checker/src/types/calling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1859,8 +1859,11 @@ fn synthesise_argument_expressions_wrt_parameters<T: ReadFromFS, A: crate::ASTIm
.iter()
.zip(call_site_type_arguments)
.map(|(param, (ty, position))| {
if let Type::RootPolyType(PolyNature::FunctionGeneric { extends, .. }) =
types.get_type_by_id(param.type_id)
// StructureGeneric for classes
if let Type::RootPolyType(
PolyNature::FunctionGeneric { extends, .. }
| PolyNature::StructureGeneric { extends, .. },
) = types.get_type_by_id(param.type_id)
{
let mut state = State {
already_checked: Default::default(),
Expand Down
5 changes: 5 additions & 0 deletions parser/src/expressions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,11 @@ impl Expression {
// a mutable reader here
let token = if let TSXToken::OpenChevron = token {
if is_generic_arguments(reader) {
if AssociativityDirection::LeftToRight
.should_return(parent_precedence, FUNCTION_CALL_PRECEDENCE)
{
return Ok(top);
}
let _ = reader.next();
let (type_arguments, _) = generic_arguments_from_reader_sub_open_angle(
reader, state, options, None,
Expand Down
22 changes: 18 additions & 4 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ pub(crate) struct CheckArguments {
/// compact diagnostics
#[argh(switch)]
pub compact_diagnostics: bool,
/// disable certain features
#[argh(switch)]
pub basic: bool,
/// maximum diagnostics to print (defaults to 30, pass `all` for all and `0` to count)
#[argh(option, default = "MaxDiagnostics::default()")]
pub max_diagnostics: MaxDiagnostics,
Expand Down Expand Up @@ -201,6 +204,7 @@ pub fn run_cli<T: crate::ReadFromFS, U: crate::WriteToFS, V: crate::CLIInputReso
timings,
compact_diagnostics,
max_diagnostics,
basic,
} = check_arguments;

let mut type_check_options: TypeCheckOptions = Default::default();
Expand All @@ -210,6 +214,10 @@ pub fn run_cli<T: crate::ReadFromFS, U: crate::WriteToFS, V: crate::CLIInputReso
type_check_options.measure_time = timings;
}

if basic {
type_check_options.max_inline = 0;
}

let entry_points = match get_entry_points(input) {
Ok(entry_points) => entry_points,
Err(_) => return ExitCode::FAILURE,
Expand All @@ -224,7 +232,10 @@ pub fn run_cli<T: crate::ReadFromFS, U: crate::WriteToFS, V: crate::CLIInputReso
let result = if diagnostics.has_error() {
if let MaxDiagnostics::FixedTo(0) = max_diagnostics {
let count = diagnostics.into_iter().count();
print_to_cli(format_args!("Found {count} type errors and warnings 😬"))
print_to_cli(format_args!(
"Found {count} type errors and warnings {}",
console::Emoji(" 😬", ":/")
))
} else {
report_diagnostics_to_cli(
diagnostics,
Expand All @@ -244,7 +255,7 @@ pub fn run_cli<T: crate::ReadFromFS, U: crate::WriteToFS, V: crate::CLIInputReso
max_diagnostics,
)
.unwrap();
print_to_cli(format_args!("No type errors found 🎉"));
print_to_cli(format_args!("No type errors found {}", console::Emoji("🎉", ":)")));
ExitCode::SUCCESS
};

Expand Down Expand Up @@ -320,7 +331,10 @@ pub fn run_cli<T: crate::ReadFromFS, U: crate::WriteToFS, V: crate::CLIInputReso
build_config.max_diagnostics,
)
.unwrap();
print_to_cli(format_args!("Project built successfully 🎉"));
print_to_cli(format_args!(
"Project built successfully {}",
console::Emoji("🎉", ":)")
));
ExitCode::SUCCESS
}
Err(FailedBuildOutput { fs, diagnostics }) => {
Expand Down Expand Up @@ -374,7 +388,7 @@ pub fn run_cli<T: crate::ReadFromFS, U: crate::WriteToFS, V: crate::CLIInputReso
}
} else {
let _ = fs::write(path.clone(), output);
print_to_cli(format_args!("Formatted {} 🎉", path.display()));
print_to_cli(format_args!("Formatted {}", path.display()));
ExitCode::SUCCESS
}
}
Expand Down

0 comments on commit 523bf16

Please sign in to comment.