1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

comptime: fix embed file with variable argument (fix #16360) (#16375)

This commit is contained in:
yuyi 2022-11-10 10:09:51 +08:00 committed by GitHub
parent bbd0603b41
commit 46921480fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 35 deletions

View File

@ -712,10 +712,10 @@ pub mut:
[minify]
pub struct EmbeddedFile {
pub:
rpath string // used in the source code, as an ID/key to the embed
apath string // absolute path during compilation to the resource
compression_type string
pub mut:
rpath string // used in the source code, as an ID/key to the embed
apath string // absolute path during compilation to the resource
// these are set by gen_embed_file_init in v/gen/c/embed
is_compressed bool
bytes []u8
@ -1683,7 +1683,6 @@ pub:
method_pos token.Pos
scope &Scope = unsafe { nil }
left Expr
args_var string
//
is_vweb bool
vweb_tmpl File
@ -1698,6 +1697,7 @@ pub mut:
left_type Type
result_type Type
env_value string
args_var string
args []CallArg
embed_file EmbeddedFile
}

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by an MIT license that can be found in the LICENSE file.
module checker
import os
import v.ast
import v.pref
import v.token
@ -29,6 +30,46 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
return ast.string_type
}
if node.is_embed {
if node.args.len == 1 {
embed_arg := node.args[0]
mut raw_path := ''
if embed_arg.expr is ast.StringLiteral {
raw_path = embed_arg.expr.val
} else if embed_arg.expr is ast.Ident {
if var := c.fn_scope.find_var(embed_arg.expr.name) {
if var.expr is ast.StringLiteral {
raw_path = var.expr.val
}
}
}
mut escaped_path := raw_path.replace('/', os.path_separator)
// Validate that the epath exists, and that it is actually a file.
if escaped_path == '' {
c.error('supply a valid relative or absolute file path to the file to embed, that is known at compile time',
node.pos)
return ast.string_type
}
abs_path := os.real_path(escaped_path)
// check absolute path first
if !os.exists(abs_path) {
// ... look relative to the source file:
escaped_path = os.real_path(os.join_path_single(os.dir(c.file.path), escaped_path))
if !os.exists(escaped_path) {
c.error('"$escaped_path" does not exist so it cannot be embedded',
node.pos)
return ast.string_type
}
if !os.is_file(escaped_path) {
c.error('"$escaped_path" is not a file so it cannot be embedded',
node.pos)
return ast.string_type
}
} else {
escaped_path = abs_path
}
node.embed_file.rpath = raw_path
node.embed_file.apath = escaped_path
}
// c.file.embedded_files << node.embed_file
if node.embed_file.compression_type !in constants.valid_comptime_compression_types {
supported := constants.valid_comptime_compression_types.map('.$it').join(', ')

View File

@ -0,0 +1,6 @@
fn test_embed_file_with_variable_arg() {
path := './a.txt'
s := $embed_file(path).to_string()
println(s)
assert s.trim_space() == 'test'
}

View File

@ -1882,9 +1882,9 @@ pub fn (mut f Fmt) comptime_call(node ast.ComptimeCall) {
} else {
if node.is_embed {
if node.embed_file.compression_type == 'none' {
f.write("\$embed_file('$node.embed_file.rpath')")
f.write('\$embed_file(${node.args[0].expr})')
} else {
f.write("\$embed_file('$node.embed_file.rpath', .$node.embed_file.compression_type)")
f.write('\$embed_file(${node.args[0].expr}, .$node.embed_file.compression_type)')
}
} else if node.is_env {
f.write("\$env('$node.args_var')")

View File

@ -123,8 +123,12 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
}
literal_string_param := if is_html { '' } else { p.tok.lit }
path_of_literal_string_param := literal_string_param.replace('/', os.path_separator)
mut arg := ast.CallArg{}
if !is_html {
p.check(.string)
arg_expr := p.expr(0)
arg = ast.CallArg{
expr: arg_expr
}
}
mut embed_compression_type := 'none'
if is_embed_file {
@ -137,33 +141,6 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
p.check(.rpar)
// $embed_file('/path/to/file')
if is_embed_file {
mut epath := path_of_literal_string_param
// Validate that the epath exists, and that it is actually a file.
if epath == '' {
p.error_with_pos('supply a valid relative or absolute file path to the file to embed',
start_pos)
return err_node
}
if !p.pref.is_fmt {
abs_path := os.real_path(epath)
// check absolute path first
if !os.exists(abs_path) {
// ... look relative to the source file:
epath = os.real_path(os.join_path_single(os.dir(p.file_name), epath))
if !os.exists(epath) {
p.error_with_pos('"$epath" does not exist so it cannot be embedded',
start_pos)
return err_node
}
if !os.is_file(epath) {
p.error_with_pos('"$epath" is not a file so it cannot be embedded',
start_pos)
return err_node
}
} else {
epath = abs_path
}
}
p.register_auto_import('v.preludes.embed_file')
if embed_compression_type == 'zlib' {
p.register_auto_import('v.preludes.embed_file.zlib')
@ -172,10 +149,9 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
scope: 0
is_embed: true
embed_file: ast.EmbeddedFile{
rpath: literal_string_param
apath: epath
compression_type: embed_compression_type
}
args: [arg]
pos: start_pos.extend(p.prev_tok.pos())
}
}