checker: add suggestions for method mispellings and unknown types
parent
2c45e601ef
commit
f300f787f3
|
@ -315,13 +315,15 @@ pub fn (mut c Checker) struct_decl(decl ast.StructDecl) {
|
||||||
}
|
}
|
||||||
sym := c.table.get_type_symbol(field.typ)
|
sym := c.table.get_type_symbol(field.typ)
|
||||||
if sym.kind == .placeholder && decl.language != .c && !sym.name.starts_with('C.') {
|
if sym.kind == .placeholder && decl.language != .c && !sym.name.starts_with('C.') {
|
||||||
c.error('unknown type `$sym.name`', field.pos)
|
c.error(util.new_suggestion(sym.name, c.table.known_type_names()).say('unknown type `$sym.name`'),
|
||||||
|
field.pos)
|
||||||
}
|
}
|
||||||
if sym.kind == .array {
|
if sym.kind == .array {
|
||||||
array_info := sym.array_info()
|
array_info := sym.array_info()
|
||||||
elem_sym := c.table.get_type_symbol(array_info.elem_type)
|
elem_sym := c.table.get_type_symbol(array_info.elem_type)
|
||||||
if elem_sym.kind == .placeholder {
|
if elem_sym.kind == .placeholder {
|
||||||
c.error('unknown type `$elem_sym.name`', field.pos)
|
c.error(util.new_suggestion(elem_sym.name, c.table.known_type_names()).say('unknown type `$elem_sym.name`'),
|
||||||
|
field.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sym.kind == .struct_ {
|
if sym.kind == .struct_ {
|
||||||
|
@ -1024,7 +1026,9 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if left_type != table.void_type {
|
if left_type != table.void_type {
|
||||||
c.error('unknown method: `${left_type_sym.name}.$method_name`', call_expr.pos)
|
suggestion := util.new_suggestion(method_name, left_type_sym.methods.map(it.name))
|
||||||
|
c.error(suggestion.say('unknown method: `${left_type_sym.name}.$method_name`'),
|
||||||
|
call_expr.pos)
|
||||||
}
|
}
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
vlib/v/checker/tests/unknown_method_suggest_name.v:7:2: error: unknown type `hash.crc32.Crc33`. Did you mean `crc32.Crc33` ?
|
||||||
|
5 | y int
|
||||||
|
6 | z int
|
||||||
|
7 | ccc crc32.Crc33
|
||||||
|
| ~~~~~~~~~~~~~~~
|
||||||
|
8 | }
|
||||||
|
9 |
|
||||||
|
vlib/v/checker/tests/unknown_method_suggest_name.v:27:9: error: unknown method: `Point.tranzlate`. Did you mean `translate` ?
|
||||||
|
25 | p := Point{1, 2, 3}
|
||||||
|
26 | v := Vector{5, 5, 10}
|
||||||
|
27 | z := p.tranzlate(v)
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
28 | println('p: $p')
|
||||||
|
29 | println('v: $v')
|
|
@ -0,0 +1,31 @@
|
||||||
|
import hash.crc32
|
||||||
|
|
||||||
|
struct Point {
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
z int
|
||||||
|
ccc crc32.Crc33
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Vector {
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
z int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (p Point) translate(v Vector) Point {
|
||||||
|
return Point{p.x + v.x, p.y + v.y, p.z + v.z}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (p Point) identity() Point {
|
||||||
|
return Point{1, 1, 1}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
p := Point{1, 2, 3}
|
||||||
|
v := Vector{5, 5, 10}
|
||||||
|
z := p.tranzlate(v)
|
||||||
|
println('p: $p')
|
||||||
|
println('v: $v')
|
||||||
|
println('z: $z')
|
||||||
|
}
|
|
@ -529,3 +529,14 @@ pub fn (table &Table) sumtype_has_variant(parent, variant Type) bool {
|
||||||
return false
|
return false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (table &Table) known_type_names() []string {
|
||||||
|
mut res := []string{}
|
||||||
|
for _, idx in table.type_idxs {
|
||||||
|
if idx == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
res << table.type_to_str(idx)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
module util
|
||||||
|
|
||||||
|
import strings
|
||||||
|
|
||||||
|
struct Possibility {
|
||||||
|
value string
|
||||||
|
svalue string
|
||||||
|
mut:
|
||||||
|
similarity f32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_by_similarity(a, b &Possibility) int {
|
||||||
|
if a.similarity < b.similarity {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if a.similarity > b.similarity {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
struct Suggestion {
|
||||||
|
mut:
|
||||||
|
known []Possibility
|
||||||
|
wanted string
|
||||||
|
swanted string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_suggestion(wanted string, possibilities []string) Suggestion {
|
||||||
|
mut s := Suggestion{
|
||||||
|
wanted: wanted
|
||||||
|
swanted: short_module_name(wanted)
|
||||||
|
}
|
||||||
|
s.add_many(possibilities)
|
||||||
|
s.sort()
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut s Suggestion) add(val string) {
|
||||||
|
if val == s.wanted {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sval := short_module_name(val)
|
||||||
|
if sval == s.wanted {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.known << Possibility{
|
||||||
|
value: val
|
||||||
|
svalue: sval
|
||||||
|
similarity: strings.dice_coefficient(s.swanted, sval)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut s Suggestion) add_many(many []string) {
|
||||||
|
for x in many {
|
||||||
|
s.add(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut s Suggestion) sort() {
|
||||||
|
s.known.sort_with_compare(compare_by_similarity)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (s Suggestion) say(msg string) string {
|
||||||
|
mut res := msg
|
||||||
|
if s.known.len > 0 {
|
||||||
|
top_posibility := s.known.last()
|
||||||
|
if top_posibility.similarity > 0.10 {
|
||||||
|
val := top_posibility.value
|
||||||
|
if !val.starts_with('[]') {
|
||||||
|
res += '. Did you mean `$val` ?'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn short_module_name(name string) string {
|
||||||
|
if !name.contains('.') {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
vals := name.split('.')
|
||||||
|
if vals.len < 2 {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
mname := vals[vals.len - 2]
|
||||||
|
symname := vals[vals.len - 1]
|
||||||
|
return '${mname}.$symname'
|
||||||
|
}
|
Loading…
Reference in New Issue