diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 427c9d24a3d65..ed28a95cca80e 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -83,9 +83,11 @@ function initmeta(m::Module = current_module()) end function signature!(tv, expr::Expr) - if isexpr(expr, [:call, :macrocall]) + is_macrocall = isexpr(expr, :macrocall) + if is_macrocall || isexpr(expr, :call) sig = :(Union{Tuple{}}) - for arg in expr.args[2:end] + first_arg = is_macrocall ? 3 : 2 # skip function arguments + for arg in expr.args[first_arg:end] isexpr(arg, :parameters) && continue if isexpr(arg, :kw) # optional arg push!(sig.args, :(Tuple{$(sig.args[end].args[2:end]...)})) @@ -592,7 +594,7 @@ function __doc__!(meta, def, define) # the Base image). We just need to convert each `@__doc__` marker to an `@doc`. finddoc(def) do each each.head = :macrocall - each.args = [Symbol("@doc"), meta, each.args[end], define] + each.args = [Symbol("@doc"), nothing, meta, each.args[end], define] # TODO: forward line number info end else # `def` has already been defined during Base image gen so we just need to find and @@ -635,7 +637,7 @@ const BINDING_HEADS = [:typealias, :const, :global, :(=)] # deprecation: remove isquotedmacrocall(x) = isexpr(x, :copyast, 1) && isa(x.args[1], QuoteNode) && - isexpr(x.args[1].value, :macrocall, 1) + isexpr(x.args[1].value, :macrocall, 2) # Simple expressions / atoms the may be documented. isbasicdoc(x) = isexpr(x, :.) || isa(x, Union{QuoteNode, Symbol}) is_signature(x) = isexpr(x, :call) || (isexpr(x, :(::), 2) && isexpr(x.args[1], :call)) || isexpr(x, :where) @@ -723,7 +725,7 @@ function docm(ex) parsedoc(keywords[ex]) elseif isa(ex, Union{Expr, Symbol}) binding = esc(bindingexpr(namify(ex))) - if isexpr(ex, [:call, :macrocall]) + if isexpr(ex, :call) || isexpr(ex, :macrocall) sig = esc(signature(ex)) :($(doc)($binding, $sig)) else diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 9134bbc3925f7..4221f061bfcc3 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -644,13 +644,6 @@ to be set after construction. See `struct` and the manual for more information. """ kw"mutable struct" -""" - @__LINE__ -> Int - -`@__LINE__` expands to the line number of the call-site. -""" -kw"@__LINE__" - """ ans diff --git a/base/docs/utils.jl b/base/docs/utils.jl index 0daf26f78c183..4a3a8b1e7a479 100644 --- a/base/docs/utils.jl +++ b/base/docs/utils.jl @@ -190,7 +190,7 @@ function repl(io::IO, s::Symbol) $(_repl(s)) end end -isregex(x) = isexpr(x, :macrocall, 2) && x.args[1] === Symbol("@r_str") && !isempty(x.args[2]) +isregex(x) = isexpr(x, :macrocall, 3) && x.args[1] === Symbol("@r_str") && !isempty(x.args[3]) repl(io::IO, ex::Expr) = isregex(ex) ? :(apropos($io, $ex)) : _repl(ex) repl(io::IO, str::AbstractString) = :(apropos($io, $str)) repl(io::IO, other) = :(@doc $(esc(other))) diff --git a/base/exports.jl b/base/exports.jl index 039c5328f9bb1..1404d89793b27 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1247,6 +1247,7 @@ export # parser internal @__FILE__, @__DIR__, + @__LINE__, @int128_str, @uint128_str, @big_str, diff --git a/base/expr.jl b/base/expr.jl index 21d66ec4a445c..d23a1909701f6 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -276,9 +276,16 @@ end remove_linenums!(ex) = ex function remove_linenums!(ex::Expr) - filter!(x->!((isa(x,Expr) && x.head === :line) || isa(x,LineNumberNode)), ex.args) + if ex.head === :body || ex.head === :block || ex.head === :quote + # remove line number expressions from metadata (not argument literal or inert) position + filter!(ex.args) do x + isa(x, Expr) && x.head === :line && return false + isa(x, LineNumberNode) && return false + return true + end + end for subex in ex.args remove_linenums!(subex) end - ex + return ex end diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 8c949d1710706..f886fecda706c 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -349,7 +349,7 @@ function code_warntype(io::IO, f, t::ANY) end code_warntype(f, t::ANY) = code_warntype(STDOUT, f, t) -typesof(args...) = Tuple{map(a->(isa(a,Type) ? Type{a} : typeof(a)), args)...} +typesof(args...) = Tuple{Any[ Core.Typeof(a) for a in args ]...} gen_call_with_extracted_types(fcn, ex0::Symbol) = Expr(:call, fcn, Meta.quot(ex0)) function gen_call_with_extracted_types(fcn, ex0) @@ -371,9 +371,9 @@ function gen_call_with_extracted_types(fcn, ex0) exret = Expr(:none) is_macro = false ex = expand(ex0) - if isa(ex0, Expr) && ex0.head == :macrocall # Make @edit @time 1+2 edit the macro + if isa(ex0, Expr) && ex0.head == :macrocall # Make @edit @time 1+2 edit the macro by using the types of the *expressions* is_macro = true - exret = Expr(:call, fcn, esc(ex0.args[1]), typesof(ex0.args[2:end]...)) + exret = Expr(:call, fcn, esc(ex0.args[1]), Tuple{#=__file__=#Any, #=__line__=#Any, Any[ Core.Typeof(a) for a in ex0.args[3:end] ]...}) elseif !isa(ex, Expr) exret = Expr(:call, :error, "expression is not a function call or symbol") elseif ex.head == :call diff --git a/base/loading.jl b/base/loading.jl index 5491b120d95e7..946deb25f0a67 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -521,24 +521,6 @@ function source_dir() p === nothing ? p : dirname(p) end -""" - @__FILE__ -> AbstractString - -`@__FILE__` expands to a string with the absolute file path of the file containing the -macro. Returns `nothing` if run from a REPL or an empty string if evaluated by -`julia -e `. Alternatively see [`PROGRAM_FILE`](@ref). -""" -macro __FILE__() source_path() end - -""" - @__DIR__ -> AbstractString - -`@__DIR__` expands to a string with the directory part of the absolute path of the file -containing the macro. Returns `nothing` if run from a REPL or an empty string if -evaluated by `julia -e `. -""" -macro __DIR__() source_dir() end - include_from_node1(path::AbstractString) = include_from_node1(String(path)) function include_from_node1(_path::String) path, prev = _include_dependency(_path) @@ -806,3 +788,38 @@ function stale_cachefile(modpath::String, cachefile::String) close(io) end end + +""" + @__LINE__ -> Int + +`@__LINE__` expands to the line number of the location of the macrocall. +Returns `0` if the line number could not be determined. +""" +macro __LINE__() + __line__ === nothing && return 0 + return __line__ +end + +""" + @__FILE__ -> AbstractString + +`@__FILE__` expands to a string with the absolute file path of the file containing the +macrocall. Returns `nothing` if run from a REPL or an empty string if evaluated by +`julia -e `. Alternatively see [`PROGRAM_FILE`](@ref). +""" +macro __FILE__() + __file__ === nothing && return nothing + return String(__file__) +end + +""" + @__DIR__ -> AbstractString + +`@__DIR__` expands to a string with the directory part of the absolute path of the file +containing the macrocall. Returns `nothing` if run from a REPL or an empty string if +evaluated by `julia -e `. +""" +macro __DIR__() + __file__ === nothing && return nothing + return dirname(String(__file__)) +end diff --git a/base/math.jl b/base/math.jl index 4d8eb64fc8d32..a383ca43aeb8c 100644 --- a/base/math.jl +++ b/base/math.jl @@ -124,7 +124,7 @@ macro evalpoly(z, p...) :(s = muladd(x, x, y*y)), as..., :(muladd($ai, tt, $b))) - R = Expr(:macrocall, Symbol("@horner"), :tt, map(esc, p)...) + R = Expr(:macrocall, Symbol("@horner"), (), :tt, map(esc, p)...) :(let tt = $(esc(z)) isa(tt, Complex) ? $C : $R end) diff --git a/base/show.jl b/base/show.jl index 00e941ecba5a9..b45effa07c824 100644 --- a/base/show.jl +++ b/base/show.jl @@ -528,8 +528,8 @@ end emphasize(io, str::AbstractString) = have_color ? print_with_color(Base.error_color(), io, str; bold = true) : print(io, uppercase(str)) -show_linenumber(io::IO, line) = print(io," # line ",line,':') -show_linenumber(io::IO, line, file) = print(io," # ", file,", line ",line,':') +show_linenumber(io::IO, line) = print(io, " #= line ", line, " =#") +show_linenumber(io::IO, line, file) = print(io, " #= ", file, ":", line, " =#") # show a block, e g if/for/etc function show_block(io::IO, head, args::Vector, body, indent::Int) @@ -556,7 +556,7 @@ end # show an indented list function show_list(io::IO, items, sep, indent::Int, prec::Int=0, enclose_operators::Bool=false) n = length(items) - if n == 0; return end + n == 0 && return indent += indent_width first = true for item in items @@ -903,12 +903,20 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int) print(io, head, ' ') show_list(io, args, ", ", indent) - elseif head === :macrocall && nargs >= 1 + elseif head === :macrocall && nargs >= 2 + # first show the line number argument as a comment + if isa(args[2], LineNumberNode) || is_expr(args[2], :line) + print(io, args[2], ' ') + end # Use the functional syntax unless specifically designated with prec=-1 + # and hide the line number argument from the argument list if prec >= 0 - show_call(io, :call, ex.args[1], ex.args[2:end], indent) + show_call(io, :call, args[1], args[3:end], indent) else - show_list(io, args, ' ', indent) + show_args = Vector{Any}(length(args) - 1) + show_args[1] = args[1] + show_args[2:end] = args[3:end] + show_list(io, show_args, ' ', indent) end elseif head === :line && 1 <= nargs <= 2 diff --git a/doc/Makefile b/doc/Makefile index 791f095b6162c..5d3310c9cfee1 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,5 +1,8 @@ # Makefile for building documentation +skip: + echo SKIPPING BUILD DOCS + default: html # You can set these variables from the command line. diff --git a/examples/clustermanager/simple/UnixDomainCM.jl b/examples/clustermanager/simple/UnixDomainCM.jl index e3a1f7f9d350a..afffa610a21b9 100644 --- a/examples/clustermanager/simple/UnixDomainCM.jl +++ b/examples/clustermanager/simple/UnixDomainCM.jl @@ -12,7 +12,8 @@ function launch(manager::UnixDomainCM, params::Dict, launched::Array, c::Conditi for i in 1:manager.np sockname = tempname() try - cmd = `$(params[:exename]) --startup-file=no $(@__FILE__) udwrkr $sockname $cookie` + __file__ = @__FILE__ + cmd = `$(params[:exename]) --startup-file=no $__file__ udwrkr $sockname $cookie` pobj = open(cmd) wconfig = WorkerConfig() diff --git a/examples/clustermanager/simple/test_simple.jl b/examples/clustermanager/simple/test_simple.jl index 57e8a8a0f28fe..2460eadd77b53 100644 --- a/examples/clustermanager/simple/test_simple.jl +++ b/examples/clustermanager/simple/test_simple.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -cmanpath = joinpath(dirname(@__FILE__), "UnixDomainCM.jl") +cmanpath = joinpath(@__DIR__, "UnixDomainCM.jl") include(cmanpath) npids = addprocs(UnixDomainCM(2)) diff --git a/src/ast.c b/src/ast.c index 6b9ac084649ff..1356b4a3c1d56 100644 --- a/src/ast.c +++ b/src/ast.c @@ -176,19 +176,36 @@ value_t fl_invoke_julia_macro(fl_context_t *fl_ctx, value_t *args, uint32_t narg { JL_TIMING(MACRO_INVOCATION); jl_ptls_t ptls = jl_get_ptls_states(); - if (nargs < 1) - argcount(fl_ctx, "invoke-julia-macro", nargs, 1); + if (nargs < 2) // macro name and location + argcount(fl_ctx, "invoke-julia-macro", nargs, 2); + nargs += 1; // split metadata into separate arguments jl_method_instance_t *mfunc = NULL; jl_value_t **margs; // Reserve one more slot for the result JL_GC_PUSHARGS(margs, nargs + 1); int i; - for(i=1; i < nargs; i++) margs[i] = scm_to_julia(fl_ctx, args[i], 1); + margs[0] = scm_to_julia(fl_ctx, args[0], 1); + jl_value_t *lno = scm_to_julia(fl_ctx, args[1], 1); + margs[1] = jl_nothing; // __file__ + margs[2] = jl_nothing; // __line__ + if (jl_is_expr(lno) && ((jl_expr_t*)lno)->head == line_sym) { + switch (jl_expr_nargs(lno)) { // fall-through is intentional + case 2: + margs[1] = jl_exprarg(lno, 1); // file + case 1: + margs[2] = jl_exprarg(lno, 0); // line + default: ; + } + } + else if (jl_typeis(lno, jl_linenumbernode_type)) { + margs[2] = jl_box_long(*(intptr_t*)lno); + } + for (i = 3; i < nargs; i++) + margs[i] = scm_to_julia(fl_ctx, args[i - 1], 1); jl_value_t *result = NULL; size_t world = jl_get_ptls_states()->world_age; JL_TRY { - margs[0] = scm_to_julia(fl_ctx, args[0], 1); margs[0] = jl_toplevel_eval(margs[0]); mfunc = jl_method_lookup(jl_gf_mtable(margs[0]), margs, nargs, 1, world); if (mfunc == NULL) { diff --git a/src/julia-parser.scm b/src/julia-parser.scm index a3806d96217bb..eb9dd16481db3 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -347,10 +347,10 @@ ((eq? pred char-bin?) (fix-uint-neg neg (sized-uint-literal n s 1))) (is-float32-literal (numchk n s) (float n)) (n (if (and (integer? n) (> n 9223372036854775807)) - `(macrocall @int128_str ,s) + `(macrocall @int128_str (null) ,s) n)) - ((within-int128? s) `(macrocall @int128_str ,s)) - (else `(macrocall @big_str ,s)))))) + ((within-int128? s) `(macrocall @int128_str (null) ,s)) + (else `(macrocall @big_str (null) ,s)))))) (define (fix-uint-neg neg n) (if neg @@ -366,7 +366,7 @@ ((<= l 16) (numchk n s) (uint16 n)) ((<= l 32) (numchk n s) (uint32 n)) ((<= l 64) (numchk n s) (uint64 n)) - ((<= l 128) `(macrocall @uint128_str ,s)) + ((<= l 128) `(macrocall @uint128_str (null) ,s)) (else (error "Hex or binary literal too large for UInt128"))))) (define (sized-uint-oct-literal n s) @@ -379,7 +379,7 @@ (else (uint64 n))) (begin (if (equal? s "0o") (numchk n s)) (if (oct-within-uint128? s) - `(macrocall @uint128_str ,s) + `(macrocall @uint128_str (null) ,s) (error "Octal literal too large for UInt128")))))) (define (strip-leading-0s s) @@ -857,10 +857,10 @@ (if (eq? op '-) (if (large-number? num) (if (eqv? (caddr num) "-170141183460469231731687303715884105728") - `(macrocall @big_str "170141183460469231731687303715884105728") + `(macrocall @big_str (null) "170141183460469231731687303715884105728") `(,(car num) ,(cadr num) ,(string.tail (caddr num) 1))) (if (= num -9223372036854775808) - `(macrocall @int128_str "9223372036854775808") + `(macrocall @int128_str (null) "9223372036854775808") (- num))) num)) @@ -1098,7 +1098,7 @@ (else (let ((name (parse-atom s))) (if (and (pair? name) (eq? (car name) 'macrocall)) - `(macrocall (|.| ,ex (quote ,(cadr name))) + `(macrocall (|.| ,ex (quote ,(cadr name))) ; move macrocall outside by rewriting A.@B as @A.B ,@(cddr name)) `(|.| ,ex (quote ,name)))))))) ((|.'| |'|) @@ -1115,16 +1115,17 @@ (not (operator? ex)) (not (ts:space? s))) ;; custom string and command literals; x"s" => @x_str "s" - (let* ((macstr (begin (take-token s) + (let* ((startloc (line-number-node s)) + (macstr (begin (take-token s) (parse-raw-literal s t))) (nxt (peek-token s)) (macname (macroify-name ex (macsuffix t)))) (if (and (symbol? nxt) (not (operator? nxt)) (not (ts:space? s))) ;; string literal suffix, "s"x - (loop `(macrocall ,macname ,macstr + (loop `(macrocall ,macname ,startloc ,macstr ,(string (take-token s)))) - (loop `(macrocall ,macname ,macstr)))) + (loop `(macrocall ,macname ,startloc ,macstr)))) ex)) (else ex)))))) @@ -2121,26 +2122,27 @@ ((eqv? t #\@) (take-token s) (with-space-sensitive - (let ((head (if (eq? (peek-token s) '|.|) + (let ((startloc (line-number-node s)) + (head (if (eq? (peek-token s) '|.|) (begin (take-token s) '__dot__) (parse-unary-prefix s)))) - (if (eq? head '__LINE__) - (input-port-line (ts:port s)) - (begin - (peek-token s) - (if (ts:space? s) - `(macrocall ,(macroify-name head) - ,@(parse-space-separated-exprs s)) - (let ((call (parse-call-chain s head #t))) - (if (and (pair? call) (eq? (car call) 'call)) - `(macrocall ,(macroify-name (cadr call)) ,@(cddr call)) - `(macrocall ,(macroify-name call) - ,@(parse-space-separated-exprs s)))))))))) - + (peek-token s) + (if (ts:space? s) + `(macrocall ,(macroify-name head) + ,startloc + ,@(parse-space-separated-exprs s)) + (let ((call (parse-call-chain s head #t))) + (if (and (pair? call) (eq? (car call) 'call)) + `(macrocall ,(macroify-name (cadr call)) + ,startloc + ,@(cddr call)) + `(macrocall ,(macroify-name call) + ,startloc + ,@(parse-space-separated-exprs s)))))))) ;; command syntax ((eqv? t #\`) (take-token s) - `(macrocall @cmd ,(parse-raw-literal s #\`))) + `(macrocall @cmd ,(line-number-node s) ,(parse-raw-literal s #\`))) ((or (string? t) (number? t) (large-number? t)) (take-token s)) @@ -2166,16 +2168,20 @@ (and (pair? e) (eq? 'string (car e))) ; string interpolation (and (length= e 3) (eq? (car e) 'macrocall) (simple-string-literal? (caddr e)) + (eq? (cadr e) '@doc_str)) + (and (length= e 4) (eq? (car e) 'macrocall) + (simple-string-literal? (cadddr e)) (eq? (cadr e) '@doc_str)))) (define (parse-docstring s production) - (let* ((ex (production s))) + (let ((startloc (line-number-node s)) ; be sure to use the line number from the head of the docstring + (ex (production s))) (if (and (doc-string-literal? ex) (let loop ((t (peek-token s))) (cond ((closing-token? t) #f) ((newline? t) (take-token s) (loop (peek-token s))) (else #t)))) - `(macrocall (core @doc) ,ex ,(production s)) + `(macrocall (core @doc) ,startloc ,ex ,(production s)) ex))) ;; --- main entry point --- diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 842327fe740d7..8514a5d52d213 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1162,6 +1162,8 @@ (error "macros cannot accept keyword arguments")) (expand-forms `(function (call ,(symbol (string #\@ (cadr (cadr e)))) + (|::| __file__ (core ANY)) + (|::| __line__ (core ANY)) ,@(map (lambda (v) (if (symbol? v) `(|::| ,v (core ANY)) diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 32139c496a44f..049cffb728158 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license # DO NOT ALTER ORDER OR SPACING OF METHODS BELOW -const lineoffset = @__LINE__ + 0 # XXX: __LINE__ at the end of a line is off-by-one +const lineoffset = @__LINE__ ambig(x, y) = 1 ambig(x::Integer, y) = 2 ambig(x, y::Integer) = 3 diff --git a/test/docs.jl b/test/docs.jl index 17ba396b79deb..5a986bbf7bffe 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -48,7 +48,7 @@ end # General tests for docstrings. -const LINE_NUMBER = @__LINE__+1 +const LINE_NUMBER = @__LINE__() + 1 "DocsTest" module DocsTest @@ -896,18 +896,18 @@ end for (line, expr) in Pair[ "sin" => :sin, "Base.sin" => :(Base.sin), - "@time(x)" => :(@time(x)), - "@time" => :(:@time), - ":@time" => :(:@time), - "@time()" => :(@time), - "Base.@time()" => :(Base.@time), + "@time(x)" => Expr(:macrocall, Symbol("@time"), Expr(:line, 1, :none), :x), + "@time" => Expr(:macrocall, Symbol("@time"), Expr(:line, 1, :none)), + ":@time" => Expr(:quote, (Expr(:macrocall, Symbol("@time"), Expr(:line, 1, :none)))), + "@time()" => Expr(:macrocall, Symbol("@time"), Expr(:line, 1, :none)), + "Base.@time()" => Expr(:macrocall, Expr(:., :Base, QuoteNode(Symbol("@time"))), Expr(:line, 1, :none)), "ccall" => :ccall, # keyword "while " => :while, # keyword, trailing spaces should be stripped. "0" => 0, "\"...\"" => "...", - "r\"...\"" => :(r"..."), + "r\"...\"" => Expr(:macrocall, Symbol("@r_str"), Expr(:line, 1, :none), "...") ] - @test Docs.helpmode(line) == :(Base.Docs.@repl($STDOUT, $expr)) + @test Docs.helpmode(line) == Expr(:macrocall, Expr(:., Expr(:., :Base, QuoteNode(:Docs)), QuoteNode(Symbol("@repl"))), Expr(:line, 117, Symbol("docs/utils.jl")), STDOUT, expr) buf = IOBuffer() @test eval(Base, Docs.helpmode(buf, line)) isa Union{Base.Markdown.MD,Void} end @@ -946,8 +946,8 @@ dynamic_test.x = "test 2" @test @doc(dynamic_test) == "test 2 Union{}" @test @doc(dynamic_test(::String)) == "test 2 Tuple{String}" -@test Docs._repl(:(dynamic_test(1.0))) == :(@doc $(Expr(:escape, :(dynamic_test(::typeof(1.0)))))) -@test Docs._repl(:(dynamic_test(::String))) == :(@doc $(Expr(:escape, :(dynamic_test(::String))))) +@test Docs._repl(:(dynamic_test(1.0))) == Expr(:macrocall, Symbol("@doc"), Expr(:line, 204, Symbol("docs/utils.jl")), esc(:(dynamic_test(::typeof(1.0))))) +@test Docs._repl(:(dynamic_test(::String))) == Expr(:macrocall, Symbol("@doc"), Expr(:line, 204, Symbol("docs/utils.jl")), esc(:(dynamic_test(::String)))) # Equality testing diff --git a/test/loading.jl b/test/loading.jl index 618700d228411..ad1cbe0fa94a6 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -2,12 +2,12 @@ using Base.Test -@test @__LINE__ == 5 +@test @__LINE__() == 5 include("test_sourcepath.jl") thefname = "the fname!//\\&\1*" include_string_test_func = include_string("include_string_test() = @__FILE__", thefname) -@test include_string_test_func() == Base.source_path() +@test include_string_test_func() == thefname @test include_string("Base.source_path()", thefname) == Base.source_path() @test basename(@__FILE__) == "loading.jl" @test isabspath(@__FILE__) diff --git a/test/parse.jl b/test/parse.jl index 5716c17491687..3e95d2cd71d18 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -147,10 +147,10 @@ macro test999_str(args...); args; end # issue 11970 @test parseall(""" -macro f(args...) end; @f "" + macro f(args...) end; @f "macro argument" """) == Expr(:toplevel, Expr(:macro, Expr(:call, :f, Expr(:..., :args)), Expr(:block, Expr(:line, 1, :none))), - Expr(:macrocall, Symbol("@f"), "")) + Expr(:macrocall, Symbol("@f"), Expr(:line, 1, :none), "macro argument")) # blocks vs. tuples @test parse("()") == Expr(:tuple) @@ -351,7 +351,7 @@ parsehex(s) = parse(Int,s,16) # issue #17705 @test parse("2e3_") == Expr(:call, :*, 2e3, :_) @test parse("2e-3_") == Expr(:call, :*, 2e-3, :_) -@test parse("2e3_\"x\"") == Expr(:call, :*, 2e3, Expr(:macrocall, Symbol("@__str"), "x")) +@test parse("2e3_\"x\"") == Expr(:call, :*, 2e3, Expr(:macrocall, Symbol("@__str"), Expr(:line, 1, :none), "x")) # multibyte spaces @test parse(Int, "3\u2003\u202F") == 3 @@ -584,9 +584,9 @@ isline(x) = isa(x,Expr) && x.head === :line # issue #16736 let - local lineoffset0 = @__LINE__ + 1 - local lineoffset1 = @__LINE__ - local lineoffset2 = @__LINE__ - 1 + local lineoffset0 = @__LINE__() + 1 + local lineoffset1 = @__LINE__() + local lineoffset2 = @__LINE__() - 1 @test lineoffset0 == lineoffset1 == lineoffset2 end @@ -771,12 +771,12 @@ module B15838 end @test A15838.@f() === nothing @test A15838.@f(1) === :b -let nometh = expand(:(A15838.@f(1, 2))) +let nometh = expand(:(A15838.@f(1, 2))), lineno = @__LINE__ @test (nometh::Expr).head === :error @test length(nometh.args) == 1 e = nometh.args[1]::MethodError @test e.f === getfield(A15838, Symbol("@f")) - @test e.args === (1,2) + @test e.args === (Symbol(@__FILE__), lineno, 1, 2) end # issue 10046 @@ -920,10 +920,10 @@ end @test :(x`s\`"\x\$\\`) == :(@x_cmd "s`\"\\x\\\$\\\\") # Check multiline command literals -@test :``` +@test :(@cmd "multiline\ncommand\n") == :``` multiline command -``` == :(@cmd "multiline\ncommand\n") +``` macro julia_cmd(s) Meta.quot(parse(s)) @@ -976,7 +976,7 @@ let ..(x,y) = x + y end # issue #7669 -@test parse("@a(b=1, c=2)") == Expr(:macrocall, Symbol("@a"), :(b=1), :(c=2)) +@test parse("@a(b=1, c=2)") == Expr(:macrocall, Symbol("@a"), Expr(:line, 1, :none), :(b=1), :(c=2)) # issue #19685 let f = function (x; kw...) @@ -1066,7 +1066,7 @@ end @test expand(:(@err20000)) == Expr(:error, "oops!") # issue #20000 -@test parse("@m(a; b=c)") == Expr(:macrocall, Symbol("@m"), +@test parse("@m(a; b=c)") == Expr(:macrocall, Symbol("@m"), Expr(:line, 1, :none), Expr(:parameters, Expr(:kw, :b, :c)), :a) # issue #21054 diff --git a/test/reflection.jl b/test/reflection.jl index d66098e3fde77..a275ac3b183b7 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -337,7 +337,7 @@ end return true end end -@test functionloc(f14346)[2] == @__LINE__-4 +@test functionloc(f14346)[2] == @__LINE__() - 4 # test jl_get_llvm_fptr. We test functions both in and definitely not in the system image definitely_not_in_sysimg() = nothing @@ -366,10 +366,10 @@ let using .MacroTest a = 1 m = getfield(current_module(), Symbol("@macrotest")) - @test which(m, Tuple{Int,Symbol})==@which @macrotest 1 a - @test which(m, Tuple{Int,Int})==@which @macrotest 1 1 + @test which(m, Tuple{Any, Any, Int, Symbol}) == @which @macrotest 1 a + @test which(m, Tuple{Any, Any, Int, Int}) == @which @macrotest 1 1 - @test first(methods(m,Tuple{Int, Int}))==@which MacroTest.@macrotest 1 1 + @test first(methods(m, Tuple{Any, Any, Int, Int})) == @which MacroTest.@macrotest 1 1 @test functionloc(@which @macrotest 1 1) == @functionloc @macrotest 1 1 end diff --git a/test/replutil.jl b/test/replutil.jl index 63e3091c9b7a7..88992809a3e2e 100644 --- a/test/replutil.jl +++ b/test/replutil.jl @@ -12,7 +12,7 @@ function test_have_color(buf, color, no_color) end cfile = " at $(@__FILE__):" -c1line = @__LINE__ + 1 +c1line = @__LINE__() + 1 method_c1(x::Float64, s::AbstractString...) = true buf = IOBuffer() @@ -59,7 +59,7 @@ color = "\e[0m\nClosest candidates are:\n method_c2(\e[1m\e[31m::Int32\e[0m, :: no_color = no_color = "\nClosest candidates are:\n method_c2(!Matched::Int32, ::Float64, ::Any...)$cfile$(c2line+2)\n method_c2(!Matched::Int32, ::Any...)$cfile$(c2line+1)\n method_c2(::T<:Real, ::T<:Real, !Matched::T<:Real) where T<:Real$cfile$(c2line+5)\n ..." test_have_color(buf, color, no_color) -c3line = @__LINE__ + 1 +c3line = @__LINE__() + 1 method_c3(x::Float64, y::Float64) = true Base.show_method_candidates(buf, Base.MethodError(method_c3,(1.,))) color = "\e[0m\nClosest candidates are:\n method_c3(::Float64, \e[1m\e[31m::Float64\e[0m)$cfile$c3line\e[0m" @@ -75,7 +75,7 @@ test_have_color(buf, "\e[0m\nClosest candidates are:\n method_c4(::AbstractString)$cfile$(c4line+2)\n method_c4()$cfile$(c4line+1)\e[0m", "\nClosest candidates are:\n method_c4(::AbstractString)$cfile$(c4line+2)\n method_c4()$cfile$(c4line+1)") -c5line = @__LINE__ + 1 +c5line = @__LINE__() + 1 method_c5(::Type{Float64}) = true Base.show_method_candidates(buf, MethodError(method_c5,(Float64,))) test_have_color(buf, "\e[0m\nClosest candidates are:\n method_c5(::Type{Float64})$cfile$c5line\e[0m", @@ -92,12 +92,12 @@ for f in [getindex, setindex!] test_have_color(buf, "", "") end -PR16155line = @__LINE__ + 2 +PR16155line = @__LINE__() + 2 mutable struct PR16155 a::Int64 b end -PR16155line2 = @__LINE__ + 1 +PR16155line2 = @__LINE__() + 1 (::Type{T}){T<:PR16155}(arg::Any) = "replace call-to-convert method from sysimg" Base.show_method_candidates(buf, MethodError(PR16155,(1.0, 2.0, Int64(3)))) @@ -146,12 +146,12 @@ else @test contains(error_out3, "method_c6_in_module(::Any; y)$cfile$(c6mline + 3) got unsupported keyword argument \"x\"") end -c7line = @__LINE__ + 1 +c7line = @__LINE__() + 1 method_c7(a, b; kargs...) = a Base.show_method_candidates(buf, MethodError(method_c7, (1, 1)), [(:x, 1), (:y, 2)]) test_have_color(buf, "\e[0m\nClosest candidates are:\n method_c7(::Any, ::Any; kargs...)$cfile$c7line\e[0m", "\nClosest candidates are:\n method_c7(::Any, ::Any; kargs...)$cfile$c7line") -c8line = @__LINE__ + 1 +c8line = @__LINE__() + 1 method_c8(a, b; y=1, w=1) = a Base.show_method_candidates(buf, MethodError(method_c8, (1, 1)), [(:x, 1), (:y, 2), (:z, 1), (:w, 1)]) test_have_color(buf, "\e[0m\nClosest candidates are:\n method_c8(::Any, ::Any; y, w)$cfile$c8line\e[1m\e[31m got unsupported keyword arguments \"x\", \"z\"\e[0m\e[0m", @@ -344,7 +344,7 @@ end @test stringmime("text/plain", FunctionLike()) == "(::FunctionLike) (generic function with 0 methods)" @test ismatch(r"^@doc \(macro with \d+ method[s]?\)$", stringmime("text/plain", getfield(Base, Symbol("@doc")))) -method_defs_lineno = @__LINE__+1 +method_defs_lineno = @__LINE__() + 1 Base.Symbol() = throw(ErrorException("1")) (::Symbol)() = throw(ErrorException("2")) EightBitType() = throw(ErrorException("3")) @@ -361,15 +361,24 @@ let err_str, sp = Base.source_path() sn = basename(sp) - @test sprint(show, which(Symbol, Tuple{})) == "Symbol() in $curmod_str at $sp:$(method_defs_lineno + 0)" - @test sprint(show, which(:a, Tuple{})) == "(::Symbol)() in $curmod_str at $sp:$(method_defs_lineno + 1)" - @test sprint(show, which(EightBitType, Tuple{})) == "$(curmod_prefix)EightBitType() in $curmod_str at $sp:$(method_defs_lineno + 2)" - @test sprint(show, which(reinterpret(EightBitType, 0x54), Tuple{})) == "(::$(curmod_prefix)EightBitType)() in $curmod_str at $sp:$(method_defs_lineno + 3)" - @test sprint(show, which(EightBitTypeT, Tuple{})) == "(::Type{$(curmod_prefix)EightBitTypeT})() in $curmod_str at $sp:$(method_defs_lineno + 4)" - @test sprint(show, which(EightBitTypeT{Int32}, Tuple{})) == "(::Type{$(curmod_prefix)EightBitTypeT{T}})() where T in $curmod_str at $sp:$(method_defs_lineno + 5)" - @test sprint(show, which(reinterpret(EightBitTypeT{Int32}, 0x54), Tuple{})) == "(::$(curmod_prefix)EightBitTypeT)() in $curmod_str at $sp:$(method_defs_lineno + 6)" - @test startswith(sprint(show, which(getfield(Base, Symbol("@doc")), Tuple{Vararg{Any}})), "@doc(x...) in Core at boot.jl:") - @test startswith(sprint(show, which(FunctionLike(), Tuple{})), "(::$(curmod_prefix)FunctionLike)() in $curmod_str at $sp:$(method_defs_lineno + 7)") + @test sprint(show, which(Symbol, Tuple{})) == + "Symbol() in $curmod_str at $sp:$(method_defs_lineno + 0)" + @test sprint(show, which(:a, Tuple{})) == + "(::Symbol)() in $curmod_str at $sp:$(method_defs_lineno + 1)" + @test sprint(show, which(EightBitType, Tuple{})) == + "$(curmod_prefix)EightBitType() in $curmod_str at $sp:$(method_defs_lineno + 2)" + @test sprint(show, which(reinterpret(EightBitType, 0x54), Tuple{})) == + "(::$(curmod_prefix)EightBitType)() in $curmod_str at $sp:$(method_defs_lineno + 3)" + @test sprint(show, which(EightBitTypeT, Tuple{})) == + "(::Type{$(curmod_prefix)EightBitTypeT})() in $curmod_str at $sp:$(method_defs_lineno + 4)" + @test sprint(show, which(EightBitTypeT{Int32}, Tuple{})) == + "(::Type{$(curmod_prefix)EightBitTypeT{T}})() where T in $curmod_str at $sp:$(method_defs_lineno + 5)" + @test sprint(show, which(reinterpret(EightBitTypeT{Int32}, 0x54), Tuple{})) == + "(::$(curmod_prefix)EightBitTypeT)() in $curmod_str at $sp:$(method_defs_lineno + 6)" + @test startswith(sprint(show, which(getfield(Base, Symbol("@doc")), Tuple{Any, Any, Vararg{Any}})), + "@doc(__file__::ANY, __line__::ANY, x...) in Core at boot.jl:") + @test startswith(sprint(show, which(FunctionLike(), Tuple{})), + "(::$(curmod_prefix)FunctionLike)() in $curmod_str at $sp:$(method_defs_lineno + 7)") @test stringmime("text/plain", FunctionLike()) == "(::FunctionLike) (generic function with 1 method)" @test stringmime("text/plain", Core.arraysize) == "arraysize (built-in function)" diff --git a/test/show.jl b/test/show.jl index a0f9fa3bd32c9..3adf2cfbdead0 100644 --- a/test/show.jl +++ b/test/show.jl @@ -15,8 +15,8 @@ struct T5589 end @test replstr(T5589(Array{String,1}(100))) == "$(curmod_prefix)T5589(String[#undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef … #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef])" -@test replstr(parse("mutable struct X end")) == ":(mutable struct X # none, line 1:\n end)" -@test replstr(parse("struct X end")) == ":(struct X # none, line 1:\n end)" +@test replstr(parse("mutable struct X end")) == ":(mutable struct X #= none:1 =#\n end)" +@test replstr(parse("struct X end")) == ":(struct X #= none:1 =#\n end)" s = "ccall(:f, Int, (Ptr{Void},), &x)" @test replstr(parse(s)) == ":($s)" @@ -42,12 +42,14 @@ macro test_repr(x) local x1 = parse($x) local x2 = eval(parse(repr(x1))) local x3 = eval(parse(repr(x2))) - x3 == x1 ? nothing : error(string( - "repr test failed:", - "\noriginal: ", $x, - "\n\nparsed: ", x2, "\n", sprint(dump, x2), - "\n\nreparsed: ", x3, "\n", sprint(dump, x3) - )) + if x3 != x1 + error(string( + "repr test failed:", + "\noriginal: ", $x, + "\n\nparsed: ", x2, "\n", sprint(dump, x2), + "\n\nreparsed: ", x3, "\n", sprint(dump, x3) + )) + end end end end @@ -261,22 +263,22 @@ end @test string(:(-{x})) == "-{x}" # issue #11393 -@test_repr "@m(x,y) + z" -@test_repr "(@m(x,y),z)" -@test_repr "[@m(x,y),z]" -@test_repr "A[@m(x,y),z]" -@test_repr "T{@m(x,y),z}" +@test_repr "@m(x, y) + z" +@test_repr "(@m(x, y), z)" +@test_repr "[@m(x, y), z]" +@test_repr "A[@m(x, y), z]" +@test_repr "T{@m(x, y), z}" @test_repr "@m x @n(y) z" -@test_repr "f(@m(x,y);z=@n(a))" -@test_repr "@m(x,y).z" -@test_repr "::@m(x,y)+z" +@test_repr "f(@m(x, y); z=@n(a))" +@test_repr "@m(x, y).z" +@test_repr "::@m(x, y) + z" @test_repr "[@m(x) y z]" @test_repr "[@m(x) y; z]" @test_repr "let @m(x), y=z; end" -@test repr(:(@m x y)) == ":(@m x y)" -@test string(:(@m x y)) == "@m x y" -@test string(:(@m x y;)) == "begin \n @m x y\nend" +@test repr(:(@m x y)) == ":( #= $(@__FILE__):$(@__LINE__) =# @m x y)" +@test string(:(@m x y)) == " #= $(@__FILE__):$(@__LINE__) =# @m x y" +@test string(:(@m x y;)) == "begin \n #= $(@__FILE__):$(@__LINE__) =# @m x y\nend" # issue #11436 @test_repr "1 => 2 => 3" @@ -448,14 +450,14 @@ end # issue #15309 l1, l2, l2n = Expr(:line,42), Expr(:line,42,:myfile), LineNumberNode(42) -@test string(l2n) == " # line 42:" -@test string(l2) == " # myfile, line 42:" +@test string(l2n) == " #= line 42 =#" +@test string(l2) == " #= myfile:42 =#" @test string(l1) == string(l2n) ex = Expr(:block, l1, :x, l2, :y, l2n, :z) @test replace(string(ex)," ","") == replace(""" -begin # line 42: - x # myfile, line 42: - y # line 42: +begin #= line 42 =# + x #= myfile:42 =# + y #= line 42 =# z end""", " ", "") # Test the printing of whatever form of line number representation diff --git a/test/stacktraces.jl b/test/stacktraces.jl index ac1814354f12c..19e23aa0f18f1 100644 --- a/test/stacktraces.jl +++ b/test/stacktraces.jl @@ -6,7 +6,7 @@ let @noinline child() = stacktrace() @noinline parent() = child() @noinline grandparent() = parent() - line_numbers = @__LINE__ - [3, 2, 1] + line_numbers = @__LINE__() - [3, 2, 1] stack = grandparent() # Basic tests. @@ -68,7 +68,7 @@ let ct = current_task() return catch_stacktrace() end end - line_numbers = @__LINE__ .- [15, 10, 5] + line_numbers = @__LINE__() .- [15, 10, 5] # Test try...catch with stacktrace @test try_stacktrace()[1] == StackFrame(:try_stacktrace, @__FILE__, line_numbers[2]) diff --git a/test/worlds.jl b/test/worlds.jl index 13bb28597c090..1dfea7f6fe8d9 100644 --- a/test/worlds.jl +++ b/test/worlds.jl @@ -136,7 +136,7 @@ f265(::Int) = 1 # test for method errors h265() = true -loc_h265 = "$(Base.source_path()):$(@__LINE__ - 1)" +loc_h265 = "$(@__FILE__):$(@__LINE__() - 1)" @test h265() @test_throws MethodError put_n_take!(h265, ()) @test_throws MethodError wait(t265)