From 7acb48df83edb1ec6eef631f787f33bf29363c69 Mon Sep 17 00:00:00 2001 From: spaceface Date: Mon, 26 Apr 2021 08:58:05 +0200 Subject: [PATCH] parser: parse `JS.` interfaces properly (#9876) --- vlib/v/ast/ast.v | 1 + vlib/v/checker/checker.v | 8 ++++++-- vlib/v/fmt/fmt.v | 4 +++- vlib/v/parser/struct.v | 15 ++++++++++++++- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index dbd1707af4..d42fc6a885 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -264,6 +264,7 @@ pub struct InterfaceDecl { pub: name string name_pos token.Position + language Language field_names []string is_pub bool methods []FnDecl diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index b44b2f7f1c..668963042c 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -353,14 +353,18 @@ pub fn (mut c Checker) sum_type_decl(node ast.SumTypeDecl) { pub fn (mut c Checker) interface_decl(decl ast.InterfaceDecl) { c.check_valid_pascal_case(decl.name, 'interface name', decl.pos) for method in decl.methods { - c.check_valid_snake_case(method.name, 'method name', method.pos) + if decl.language == .v { + c.check_valid_snake_case(method.name, 'method name', method.pos) + } c.ensure_type_exists(method.return_type, method.return_type_pos) or { return } for param in method.params { c.ensure_type_exists(param.typ, param.pos) or { return } } } for i, field in decl.fields { - c.check_valid_snake_case(field.name, 'field name', field.pos) + if decl.language == .v { + c.check_valid_snake_case(field.name, 'field name', field.pos) + } c.ensure_type_exists(field.typ, field.pos) or { return } for j in 0 .. i { if field.name == decl.fields[j].name { diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index e892c736cf..8d84b63233 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -1149,8 +1149,10 @@ pub fn (mut f Fmt) interface_decl(node ast.InterfaceDecl) { if node.is_pub { f.write('pub ') } + f.write('interface ') + f.write_language_prefix(node.language) name := node.name.after('.') - f.write('interface $name {') + f.write('$name {') if node.fields.len > 0 || node.methods.len > 0 || node.pos.line_nr < node.pos.last_line { f.writeln('') } diff --git a/vlib/v/parser/struct.v b/vlib/v/parser/struct.v index 9d8081874b..57d7a5247d 100644 --- a/vlib/v/parser/struct.v +++ b/vlib/v/parser/struct.v @@ -440,7 +440,19 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl { p.next() } p.next() // `interface` + language := if p.tok.lit == 'C' && p.peek_tok.kind == .dot { + ast.Language.c + } else if p.tok.lit == 'JS' && p.peek_tok.kind == .dot { + ast.Language.js + } else { + ast.Language.v + } + if language != .v { + p.next() // C || JS + p.next() // . + } name_pos := p.tok.position() + p.check_for_impure_v(language, name_pos) interface_name := p.prepend_mod(p.check_name()).clone() // println('interface decl $interface_name') p.check(.lcbr) @@ -494,7 +506,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl { p.error_with_pos('duplicate method `$name`', method_start_pos) return ast.InterfaceDecl{} } - if util.contains_capital(name) { + if language == .v && util.contains_capital(name) { p.error('interface methods cannot contain uppercase letters, use snake_case instead') return ast.InterfaceDecl{} } @@ -575,6 +587,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl { pos = pos.extend_with_last_line(p.prev_tok.position(), p.prev_tok.line_nr) return ast.InterfaceDecl{ name: interface_name + language: language fields: fields methods: methods is_pub: is_pub