mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
parser/checker: check capital letters in interface names/methods
This commit is contained in:
parent
99cf520bd4
commit
cc66eb1194
@ -159,6 +159,7 @@ pub:
|
||||
name string
|
||||
field_names []string
|
||||
methods []FnDecl
|
||||
pos token.Position
|
||||
}
|
||||
|
||||
pub struct StructInitField {
|
||||
|
@ -40,9 +40,13 @@ pub fn (node &FnDecl) str(t &table.Table) string {
|
||||
f.write('fn ${receiver}${name}(')
|
||||
for i, arg in node.args {
|
||||
// skip receiver
|
||||
// if (node.is_method || node.is_interface) && i == 0 {
|
||||
if node.is_method && i == 0 {
|
||||
continue
|
||||
}
|
||||
if arg.is_hidden {
|
||||
continue
|
||||
}
|
||||
is_last_arg := i == node.args.len - 1
|
||||
should_add_type := is_last_arg || node.args[i + 1].typ != arg.typ || (node.is_variadic &&
|
||||
i == node.args.len - 2)
|
||||
|
@ -90,7 +90,8 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
||||
return
|
||||
}
|
||||
if !has_main_mod_file {
|
||||
c.error('projet must include a `main` module or be a shared library (compile with `v -shared`)', token.Position{})
|
||||
c.error('projet must include a `main` module or be a shared library (compile with `v -shared`)',
|
||||
token.Position{})
|
||||
} else if !has_main_fn {
|
||||
c.error('function `main` must be declared in the main module', token.Position{})
|
||||
}
|
||||
@ -886,7 +887,8 @@ fn (mut c Checker) type_implements(typ, inter_typ table.Type, pos token.Position
|
||||
for imethod in inter_sym.methods {
|
||||
if method := typ_sym.find_method(imethod.name) {
|
||||
if !imethod.is_same_method_as(method) {
|
||||
c.error('`$styp` incorrectly implements method `$imethod.name` of interface `$inter_sym.name`, expected `${c.table.fn_to_str(imethod)}`', pos)
|
||||
c.error('`$styp` incorrectly implements method `$imethod.name` of interface `$inter_sym.name`, expected `${c.table.fn_to_str(imethod)}`',
|
||||
pos)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@ -1474,6 +1476,16 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||
}
|
||||
// ast.HashStmt {}
|
||||
ast.Import {}
|
||||
ast.InterfaceDecl {
|
||||
if !it.name[0].is_capital() {
|
||||
pos := token.Position{
|
||||
line_nr: it.pos.line_nr
|
||||
pos: it.pos.pos + 'interface'.len
|
||||
len: it.name.len
|
||||
}
|
||||
c.error('interface name must begin with capital letter', pos)
|
||||
}
|
||||
}
|
||||
ast.Module {
|
||||
c.mod = it.name
|
||||
c.is_builtin_mod = it.name == 'builtin'
|
||||
@ -1561,8 +1573,8 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||
ast.CastExpr {
|
||||
it.expr_type = c.expr(it.expr)
|
||||
sym := c.table.get_type_symbol(it.expr_type)
|
||||
if it.typ == table.string_type && !(sym.kind in [.byte, .byteptr] ||
|
||||
sym.kind == .array && sym.name == 'array_byte') {
|
||||
if it.typ == table.string_type && !(sym.kind in [.byte, .byteptr] || sym.kind ==
|
||||
.array && sym.name == 'array_byte') {
|
||||
type_name := c.table.type_to_str(it.expr_type)
|
||||
c.error('cannot cast type `$type_name` to string', it.pos)
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ module parser
|
||||
import v.ast
|
||||
import v.table
|
||||
import v.token
|
||||
import v.util
|
||||
|
||||
fn (mut p Parser) struct_decl() ast.StructDecl {
|
||||
start_pos := p.tok.position()
|
||||
@ -255,6 +256,7 @@ fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit {
|
||||
}
|
||||
|
||||
fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
||||
start_pos := p.tok.position()
|
||||
is_pub := p.tok.kind == .key_pub
|
||||
if is_pub {
|
||||
p.next()
|
||||
@ -278,11 +280,15 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
||||
for p.tok.kind != .rcbr && p.tok.kind != .eof {
|
||||
line_nr := p.tok.line_nr
|
||||
name := p.check_name()
|
||||
if util.contains_capital(name) {
|
||||
p.error('interface methods cannot contain uppercase letters, use snake_case instead')
|
||||
}
|
||||
// field_names << name
|
||||
args2, _ := p.fn_args()
|
||||
mut args := [table.Arg{
|
||||
name: 'x'
|
||||
typ: typ
|
||||
is_hidden: true
|
||||
}]
|
||||
args << args2
|
||||
mut method := ast.FnDecl{
|
||||
@ -306,5 +312,6 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
||||
return ast.InterfaceDecl{
|
||||
name: interface_name
|
||||
methods: methods
|
||||
pos: start_pos
|
||||
}
|
||||
}
|
||||
|
@ -33,9 +33,10 @@ pub mut:
|
||||
|
||||
pub struct Arg {
|
||||
pub:
|
||||
name string
|
||||
is_mut bool
|
||||
typ Type
|
||||
name string
|
||||
is_mut bool
|
||||
typ Type
|
||||
is_hidden bool // interface first arg
|
||||
}
|
||||
|
||||
pub struct Var {
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
struct Dog {
|
||||
breed string
|
||||
}
|
||||
@ -46,11 +45,10 @@ fn (d Dog) name_detailed(pet_name string) string {
|
||||
}
|
||||
|
||||
// do not add to Dog the utility function 'str', as a sample
|
||||
|
||||
|
||||
fn test_todo() {
|
||||
if true {}
|
||||
else {}
|
||||
if true {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
fn perform_speak(a Animal) {
|
||||
@ -58,24 +56,30 @@ fn perform_speak(a Animal) {
|
||||
assert true
|
||||
name := a.name()
|
||||
assert name == 'Dog' || name == 'Cat'
|
||||
//if a is Dog {
|
||||
//assert name == 'Dog'
|
||||
//}
|
||||
// if a is Dog {
|
||||
// assert name == 'Dog'
|
||||
// }
|
||||
println(a.name())
|
||||
}
|
||||
|
||||
fn test_perform_speak() {
|
||||
dog := Dog{breed: 'Labrador Retriever'}
|
||||
dog := Dog{
|
||||
breed: 'Labrador Retriever'
|
||||
}
|
||||
perform_speak(dog)
|
||||
cat := Cat{breed: 'Persian'}
|
||||
cat := Cat{
|
||||
breed: 'Persian'
|
||||
}
|
||||
perform_speak(cat)
|
||||
perform_speak(Cat{breed: 'Persian'})
|
||||
perform_speak(Cat{
|
||||
breed: 'Persian'
|
||||
})
|
||||
handle_animals([dog, cat])
|
||||
/*
|
||||
f := Foo {
|
||||
speaker: dog
|
||||
}
|
||||
*/
|
||||
*/
|
||||
}
|
||||
|
||||
fn perform_name_detailed(a Animal) {
|
||||
@ -85,22 +89,24 @@ fn perform_name_detailed(a Animal) {
|
||||
}
|
||||
|
||||
fn test_perform_name_detailed() {
|
||||
dog := Dog{breed: 'Labrador Retriever'}
|
||||
dog := Dog{
|
||||
breed: 'Labrador Retriever'
|
||||
}
|
||||
println('Test on Dog: $dog ...')
|
||||
perform_name_detailed(dog)
|
||||
|
||||
cat := Cat{}
|
||||
println('Test on Cat: $cat ...')
|
||||
perform_speak(cat)
|
||||
|
||||
println('Test on another Cat: ...')
|
||||
perform_speak(Cat{breed: 'Persian'})
|
||||
|
||||
perform_speak(Cat{
|
||||
breed: 'Persian'
|
||||
})
|
||||
println('Test (dummy/empty) on array of animals ...')
|
||||
handle_animals([dog, cat])
|
||||
}
|
||||
|
||||
fn handle_animals(a []Animal) {}
|
||||
fn handle_animals(a []Animal) {
|
||||
}
|
||||
|
||||
interface Register {
|
||||
register()
|
||||
@ -110,9 +116,11 @@ struct RegTest {
|
||||
a int
|
||||
}
|
||||
|
||||
fn (f RegTest) register() {}
|
||||
fn (f RegTest) register() {
|
||||
}
|
||||
|
||||
fn handle_reg(r Register) {}
|
||||
fn handle_reg(r Register) {
|
||||
}
|
||||
|
||||
fn test_register() {
|
||||
f := RegTest{}
|
||||
@ -125,9 +133,8 @@ interface Speaker2 {
|
||||
speak()
|
||||
}
|
||||
|
||||
|
||||
struct Foo {
|
||||
animal Animal
|
||||
animal Animal
|
||||
animals []Animal
|
||||
}
|
||||
|
||||
@ -140,7 +147,9 @@ interface Animal {
|
||||
fn test_interface_array() {
|
||||
println('Test on array of animals ...')
|
||||
mut animals := []Animal{}
|
||||
animals = [ Cat{}, Dog{breed: 'Labrador Retriever'} ]
|
||||
animals = [Cat{}, Dog{
|
||||
breed: 'Labrador Retriever'
|
||||
}]
|
||||
animals << Cat{}
|
||||
assert true
|
||||
// TODO .str() from the real types should be called
|
||||
|
Loading…
Reference in New Issue
Block a user