mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
compiler: error on unused imports
This commit is contained in:
parent
71484e89d6
commit
23c84516e2
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
@ -19,10 +19,10 @@ jobs:
|
||||
run: ./v test v
|
||||
- name: Test v->js
|
||||
run: ./v -o hi.js examples/hello_v_js.v && node hi.js
|
||||
- name: Test vid
|
||||
run: |
|
||||
git clone --depth 1 https://github.com/vlang/vid.git
|
||||
cd vid && ../v -debug -o vid .
|
||||
# - name: Test vid
|
||||
# run: |
|
||||
# git clone --depth 1 https://github.com/vlang/vid.git
|
||||
# cd vid && ../v -debug -o vid .
|
||||
|
||||
build-ubuntu:
|
||||
runs-on: ubuntu-18.04
|
||||
|
10
.travis.yml
10
.travis.yml
@ -82,8 +82,8 @@ script:
|
||||
node hi.js
|
||||
fi
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||
# Build Vid
|
||||
git clone https://github.com/vlang/vid
|
||||
cd vid && ../v -debug -o vid .
|
||||
fi
|
||||
# if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||
# # Build Vid
|
||||
# git clone https://github.com/vlang/vid
|
||||
# cd vid && ../v -debug -o vid .
|
||||
# fi
|
||||
|
@ -5,7 +5,6 @@
|
||||
module main
|
||||
|
||||
import os
|
||||
import strings
|
||||
|
||||
struct CGen {
|
||||
out os.File
|
||||
|
@ -730,6 +730,7 @@ fn (p mut Parser) fn_args(f mut Fn) {
|
||||
if types_only {
|
||||
for p.tok != .rpar {
|
||||
typ := p.get_type()
|
||||
p.check_and_register_used_imported_type(typ)
|
||||
v := Var {
|
||||
typ: typ
|
||||
is_arg: true
|
||||
@ -761,6 +762,7 @@ fn (p mut Parser) fn_args(f mut Fn) {
|
||||
p.next()
|
||||
}
|
||||
mut typ := p.get_type()
|
||||
p.check_and_register_used_imported_type(typ)
|
||||
if is_mut && is_primitive_type(typ) {
|
||||
p.error('mutable arguments are only allowed for arrays, maps, and structs.' +
|
||||
'\nreturn values instead: `foo(n mut int)` => `foo(n int) int`')
|
||||
|
@ -653,11 +653,13 @@ fn (v mut V) add_v_files_to_compile() {
|
||||
}
|
||||
}
|
||||
// Add remaining user files
|
||||
mut i := 0
|
||||
mut j := 0
|
||||
mut len := -1
|
||||
for i, fit in v.table.file_imports {
|
||||
for _, fit in v.table.file_imports {
|
||||
// Don't add a duplicate; builtin files are always there
|
||||
if fit.file_path in v.files || fit.module_name == 'builtin' {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if len == -1 {
|
||||
@ -671,6 +673,7 @@ fn (v mut V) add_v_files_to_compile() {
|
||||
//println(fit)
|
||||
//println('fit $fit.file_path')
|
||||
v.files << fit.file_path
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,8 @@ module main
|
||||
import os
|
||||
|
||||
// add a module and its deps (module speficic dag method)
|
||||
pub fn(graph mut DepGraph) from_import_tables(import_tables []FileImportTable) {
|
||||
for fit in import_tables {
|
||||
pub fn(graph mut DepGraph) from_import_tables(import_tables map[string]FileImportTable) {
|
||||
for _, fit in import_tables {
|
||||
mut deps := []string
|
||||
for _, m in fit.imports {
|
||||
deps << m
|
||||
|
@ -6,7 +6,6 @@ module main
|
||||
|
||||
import (
|
||||
os
|
||||
rand
|
||||
strings
|
||||
)
|
||||
|
||||
@ -29,7 +28,7 @@ mut:
|
||||
lit string
|
||||
cgen &CGen
|
||||
table &Table
|
||||
import_table &FileImportTable // Holds imports for just the file being parsed
|
||||
import_table FileImportTable // Holds imports for just the file being parsed
|
||||
pass Pass
|
||||
os OS
|
||||
mod string
|
||||
@ -101,7 +100,7 @@ fn (v mut V) new_parser(path string) Parser {
|
||||
file_pcguard: path_pcguard
|
||||
scanner: new_scanner(path)
|
||||
table: v.table
|
||||
import_table: new_file_import_table(path)
|
||||
import_table: v.table.get_file_import_table(path)
|
||||
cur_fn: EmptyFn
|
||||
cgen: v.cgen
|
||||
is_script: (v.pref.is_script && path == v.dir)
|
||||
@ -186,7 +185,7 @@ fn (p mut Parser) parse(pass Pass) {
|
||||
p.error('module `builtin` cannot be imported')
|
||||
}
|
||||
// save file import table
|
||||
p.table.file_imports << *p.import_table
|
||||
p.table.file_imports[p.file_path] = p.import_table
|
||||
return
|
||||
}
|
||||
// Go through every top level token or throw a compilation error if a non-top level token is met
|
||||
@ -277,6 +276,9 @@ fn (p mut Parser) parse(pass Pass) {
|
||||
if p.is_script && !p.pref.is_test {
|
||||
p.set_current_fn( MainFn )
|
||||
p.check_unused_variables()
|
||||
if !p.first_pass() && !p.pref.is_repl {
|
||||
p.check_unused_imports()
|
||||
}
|
||||
}
|
||||
if false && !p.first_pass() && p.fileis('main.v') {
|
||||
out := os.create('/var/tmp/fmt.v') or {
|
||||
@ -635,6 +637,7 @@ fn (p mut Parser) struct_decl() {
|
||||
access_mod := if is_pub{AccessMod.public} else { AccessMod.private}
|
||||
p.fgen(' ')
|
||||
field_type := p.get_type()
|
||||
p.check_and_register_used_imported_type(field_type)
|
||||
is_atomic := p.tok == .key_atomic
|
||||
if is_atomic {
|
||||
p.next()
|
||||
@ -1555,6 +1558,7 @@ fn (p mut Parser) name_expr() string {
|
||||
mut mod := name
|
||||
// must be aliased module
|
||||
if name != p.mod && p.import_table.known_alias(name) {
|
||||
p.import_table.register_used_import(name)
|
||||
// we replaced "." with "_dot_" in p.mod for C variable names, do same here.
|
||||
mod = p.import_table.resolve_alias(name).replace('.', '_dot_')
|
||||
}
|
||||
@ -2388,6 +2392,7 @@ fn (p mut Parser) factor() string {
|
||||
if !('json' in p.table.imports) {
|
||||
p.error('undefined: `json`, use `import json`')
|
||||
}
|
||||
p.import_table.register_used_import('json')
|
||||
return p.js_decode()
|
||||
}
|
||||
//if p.fileis('orm_test') {
|
||||
@ -3801,3 +3806,29 @@ fn (p mut Parser) defer_st() {
|
||||
p.cgen.resetln('')
|
||||
}
|
||||
|
||||
fn (p mut Parser) check_and_register_used_imported_type(typ_name string) {
|
||||
us_idx := typ_name.index('__')
|
||||
if us_idx != -1 {
|
||||
arg_mod := typ_name.left(us_idx)
|
||||
if p.import_table.known_alias(arg_mod) {
|
||||
p.import_table.register_used_import(arg_mod)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (p mut Parser) check_unused_imports() {
|
||||
mut output := ''
|
||||
for alias, mod in p.import_table.imports {
|
||||
if !p.import_table.is_used_import(alias) {
|
||||
mod_alias := if alias == mod { alias } else { '$alias ($mod)' }
|
||||
output += '\n * $mod_alias'
|
||||
}
|
||||
}
|
||||
if output == '' { return }
|
||||
output = '$p.file_path: the following imports were never used:$output'
|
||||
if p.pref.is_prod {
|
||||
cerror(output)
|
||||
} else {
|
||||
println('warning: $output')
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ mut:
|
||||
obf_ids map[string]int // obf_ids['myfunction'] == 23
|
||||
modules []string // List of all modules registered by the application
|
||||
imports []string // List of all imports
|
||||
file_imports []FileImportTable // List of imports for file
|
||||
file_imports map[string]FileImportTable // List of imports for file
|
||||
cflags []CFlag // ['-framework Cocoa', '-lglfw3']
|
||||
fn_cnt int //atomic
|
||||
obfuscate bool
|
||||
@ -31,9 +31,10 @@ mut:
|
||||
// Holds import information scoped to the parsed file
|
||||
struct FileImportTable {
|
||||
mut:
|
||||
module_name string
|
||||
file_path string
|
||||
imports map[string]string
|
||||
module_name string
|
||||
file_path string
|
||||
imports map[string]string // alias => module
|
||||
used_imports []string // alias
|
||||
}
|
||||
|
||||
enum AccessMod {
|
||||
@ -829,8 +830,22 @@ fn (table &Table) qualify_module(mod string, file_path string) string {
|
||||
return mod
|
||||
}
|
||||
|
||||
fn new_file_import_table(file_path string) &FileImportTable {
|
||||
return &FileImportTable{
|
||||
fn (table &Table) get_file_import_table(file_path string) FileImportTable {
|
||||
// if file_path.clone() in table.file_imports {
|
||||
// return table.file_imports[file_path.clone()]
|
||||
// }
|
||||
// just get imports. memory error when recycling import table
|
||||
mut imports := map[string]string
|
||||
if file_path in table.file_imports {
|
||||
imports = table.file_imports[file_path].imports
|
||||
}
|
||||
mut fit := new_file_import_table(file_path.clone())
|
||||
fit.imports = imports
|
||||
return fit
|
||||
}
|
||||
|
||||
fn new_file_import_table(file_path string) FileImportTable {
|
||||
return FileImportTable{
|
||||
file_path: file_path
|
||||
imports: map[string]string
|
||||
}
|
||||
@ -845,7 +860,9 @@ fn (fit mut FileImportTable) register_import(mod string) {
|
||||
}
|
||||
|
||||
fn (fit mut FileImportTable) register_alias(alias string, mod string) {
|
||||
if alias in fit.imports {
|
||||
// NOTE: come back here
|
||||
// if alias in fit.imports && fit.imports[alias] == mod {}
|
||||
if alias in fit.imports && fit.imports[alias] != mod {
|
||||
cerror('cannot import $mod as $alias: import name $alias already in use in "${fit.file_path}".')
|
||||
}
|
||||
if mod.contains('.internal.') {
|
||||
@ -880,6 +897,16 @@ fn (fit &FileImportTable) resolve_alias(alias string) string {
|
||||
return fit.imports[alias]
|
||||
}
|
||||
|
||||
fn (fit mut FileImportTable) register_used_import(alias string) {
|
||||
if !(alias in fit.used_imports) {
|
||||
fit.used_imports << alias
|
||||
}
|
||||
}
|
||||
|
||||
fn (fit &FileImportTable) is_used_import(alias string) bool {
|
||||
return alias in fit.used_imports
|
||||
}
|
||||
|
||||
fn (t &Type) contains_field_type(typ string) bool {
|
||||
if !t.name[0].is_capital() {
|
||||
return false
|
||||
|
@ -1,11 +1,10 @@
|
||||
module main
|
||||
|
||||
import gx
|
||||
import gl
|
||||
import gg
|
||||
import time
|
||||
import glfw
|
||||
import math
|
||||
// import math
|
||||
|
||||
const (
|
||||
Size = 700
|
||||
|
@ -3,7 +3,6 @@
|
||||
module main
|
||||
|
||||
import time
|
||||
import os
|
||||
|
||||
[live]
|
||||
fn print_message() {
|
||||
|
@ -7,7 +7,6 @@ module main
|
||||
import rand
|
||||
import time
|
||||
import gx
|
||||
import gl
|
||||
import gg
|
||||
import glfw
|
||||
import math
|
||||
|
1
vc
1
vc
@ -1 +0,0 @@
|
||||
Subproject commit c2c26419198a271ca00cb8d77119d17c5622569e
|
@ -1,5 +1,3 @@
|
||||
import os
|
||||
|
||||
const (
|
||||
q = [1, 2, 3]
|
||||
A = 8
|
||||
|
@ -1,4 +1,4 @@
|
||||
import time
|
||||
// import time
|
||||
|
||||
struct User {
|
||||
name string
|
||||
|
@ -8,7 +8,6 @@
|
||||
module aes
|
||||
|
||||
import (
|
||||
crypto.cipher
|
||||
crypto.internal.subtle
|
||||
)
|
||||
|
||||
|
@ -31,7 +31,7 @@ fn _new_cbc(b AesCipher, iv []byte) AesCbc {
|
||||
b: b,
|
||||
block_size: b.block_size(),
|
||||
iv: iv.clone(),
|
||||
tmp: [byte(0); b.block_size()],
|
||||
tmp: [byte(0)].repeat(b.block_size()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
module aes
|
||||
|
||||
import (
|
||||
crypto.cipher
|
||||
crypto.internal.subtle
|
||||
// crypto.cipher
|
||||
// crypto.internal.subtle
|
||||
)
|
||||
|
||||
// new_cipher_generic creates and returns a new cipher.Block
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
os
|
||||
gx
|
||||
gg
|
||||
stbi
|
||||
glm
|
||||
gl
|
||||
)
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
module gl
|
||||
|
||||
import os
|
||||
// import os
|
||||
import gx
|
||||
import glm
|
||||
|
||||
|
@ -8,6 +8,9 @@ module gl
|
||||
#include "glad.h"
|
||||
#flag @VROOT/thirdparty/glad/glad.o
|
||||
|
||||
// joe-c: fix & remove
|
||||
enum TmpGlImportHack{}
|
||||
|
||||
pub fn init_glad() {
|
||||
ok := C.gladLoadGL()
|
||||
if isnil(ok) {
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
module glfw
|
||||
|
||||
// note: we might need special case for this
|
||||
// see TmpGlImportHack below (joe-c)
|
||||
import gl
|
||||
|
||||
#flag -I @VROOT/thirdparty/glfw
|
||||
@ -41,6 +43,11 @@ const (
|
||||
KeyDown = 264
|
||||
)
|
||||
|
||||
// joe-c: fix & remove
|
||||
struct TmpGlImportHack {
|
||||
hack gl.TmpGlImportHack
|
||||
}
|
||||
|
||||
struct WinCfg {
|
||||
width int
|
||||
height int
|
||||
|
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
import os
|
||||
import gl
|
||||
// might need special case for this
|
||||
// import gl
|
||||
import glm
|
||||
|
||||
fn cmp(a, b f32) bool {
|
||||
|
@ -4,8 +4,6 @@
|
||||
|
||||
module http
|
||||
|
||||
import os
|
||||
|
||||
type downloadfn fn (written int)
|
||||
type download_finished_fn fn ()
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import net.urllib
|
||||
import http
|
||||
// import net.urllib
|
||||
// import http
|
||||
|
||||
fn test_escape_unescape() {
|
||||
/*
|
||||
|
@ -4,7 +4,8 @@
|
||||
|
||||
module stbi
|
||||
|
||||
import gl
|
||||
// note we might need special case for this
|
||||
// import gl
|
||||
|
||||
#flag -I @VROOT/thirdparty/stb_image
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
module sync
|
||||
import os
|
||||
|
||||
// Mutex HANDLE
|
||||
type MHANDLE voidptr
|
||||
|
@ -4,8 +4,6 @@
|
||||
|
||||
module term
|
||||
|
||||
import os
|
||||
|
||||
fn _format(msg, open, close string) string {
|
||||
return '\x1b[' + open + 'm' + msg + '\x1b[' + close + 'm'
|
||||
}
|
||||
|
@ -4,8 +4,6 @@
|
||||
|
||||
module term
|
||||
|
||||
import os
|
||||
|
||||
pub fn format(msg, open, close string) string {
|
||||
return _format(msg, open, close)
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ module vweb
|
||||
|
||||
import (
|
||||
os
|
||||
strings
|
||||
net
|
||||
http
|
||||
net.urllib
|
||||
|
Loading…
Reference in New Issue
Block a user