• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37474

pending completion
#37474

push

local

web-flow
irinterp: Allow setting all IR flags (#48993)

Currently, `IR_FLAG_NOTHROW` is the only flag that irinterp is allowed to
set on statements, under the assumption that in order for a call to
be irinterp-eligible, it must have been proven `:foldable`, thus `:effect_free`,
and thus `IR_FLAG_EFFECT_FREE` was assumed to have been set. That reasoning
was sound at the time this code was written, but have since introduced
`EFFECT_FREE_IF_INACCESSIBLEMEMONLY`, which breaks the reasoning that
an `:effect_free` inference for the whole function implies the flag on
every statement. As a result, we were failing to DCE otherwise dead
statements if the IR came from irinterp.

3 of 3 new or added lines in 1 file covered. (100.0%)

70258 of 82316 relevant lines covered (85.35%)

32461773.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.01
/stdlib/Logging/src/ConsoleLogger.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
"""
4
    ConsoleLogger([stream,] min_level=Info; meta_formatter=default_metafmt,
5
                  show_limited=true, right_justify=0)
6

7
Logger with formatting optimized for readability in a text console, for example
8
interactive work with the Julia REPL.
9

10
Log levels less than `min_level` are filtered out.
11

12
Message formatting can be controlled by setting keyword arguments:
13

14
* `meta_formatter` is a function which takes the log event metadata
15
  `(level, _module, group, id, file, line)` and returns a color (as would be
16
  passed to printstyled), prefix and suffix for the log message.  The
17
  default is to prefix with the log level and a suffix containing the module,
18
  file and line location.
19
* `show_limited` limits the printing of large data structures to something
20
  which can fit on the screen by setting the `:limit` `IOContext` key during
21
  formatting.
22
* `right_justify` is the integer column which log metadata is right justified
23
  at. The default is zero (metadata goes on its own line).
24
"""
25
struct ConsoleLogger <: AbstractLogger
26
    stream::IO
460✔
27
    min_level::LogLevel
28
    meta_formatter
29
    show_limited::Bool
30
    right_justify::Int
31
    message_limits::Dict{Any,Int}
32
end
33
function ConsoleLogger(stream::IO, min_level=Info;
50✔
34
                       meta_formatter=default_metafmt, show_limited=true,
35
                       right_justify=0)
36
    ConsoleLogger(stream, min_level, meta_formatter,
24✔
37
                  show_limited, right_justify, Dict{Any,Int}())
38
end
39
function ConsoleLogger(min_level=Info;
872✔
40
                       meta_formatter=default_metafmt, show_limited=true,
41
                       right_justify=0)
42
    ConsoleLogger(closed_stream, min_level, meta_formatter,
436✔
43
                  show_limited, right_justify, Dict{Any,Int}())
44
end
45

46

47
shouldlog(logger::ConsoleLogger, level, _module, group, id) =
10✔
48
    get(logger.message_limits, id, 1) > 0
49

50
min_enabled_level(logger::ConsoleLogger) = logger.min_level
441✔
51

52
# Formatting of values in key value pairs
53
showvalue(io, msg) = show(io, "text/plain", msg)
5✔
54
function showvalue(io, e::Tuple{Exception,Any})
2✔
55
    ex,bt = e
2✔
56
    showerror(io, ex, bt; backtrace = bt!==nothing)
2✔
57
end
58
showvalue(io, ex::Exception) = showerror(io, ex)
1✔
59

60
function default_logcolor(level::LogLevel)
×
61
    level < Info  ? Base.debug_color() :
33✔
62
    level < Warn  ? Base.info_color()  :
63
    level < Error ? Base.warn_color()  :
64
                    Base.error_color()
65
end
66

67
function default_metafmt(level::LogLevel, _module, group, id, file, line)
17✔
68
    @nospecialize
×
69
    color = default_logcolor(level)
33✔
70
    prefix = string(level == Warn ? "Warning" : string(level), ':')
26✔
71
    suffix::String = ""
17✔
72
    Info <= level < Warn && return color, prefix, suffix
17✔
73
    _module !== nothing && (suffix *= string(_module)::String)
11✔
74
    if file !== nothing
11✔
75
        _module !== nothing && (suffix *= " ")
9✔
76
        suffix *= contractuser(file)::String
9✔
77
        if line !== nothing
9✔
78
            suffix *= ":$(isa(line, UnitRange) ? "$(first(line))-$(last(line))" : line)"
8✔
79
        end
80
    end
81
    !isempty(suffix) && (suffix = "@ " * suffix)
11✔
82
    return color, prefix, suffix
11✔
83
end
84

85
# Length of a string as it will appear in the terminal (after ANSI color codes
86
# are removed)
87
function termlength(str)
26✔
88
    N = 0
×
89
    in_esc = false
×
90
    for c in str
51✔
91
        if in_esc
434✔
92
            if c == 'm'
×
93
                in_esc = false
×
94
            end
95
        else
96
            if c == '\e'
434✔
97
                in_esc = true
×
98
            else
99
                N += 1
434✔
100
            end
101
        end
102
    end
843✔
103
    return N
26✔
104
end
105

106
function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module, group, id,
55✔
107
                        filepath, line; kwargs...)
108
    @nospecialize
×
109
    hasmaxlog = haskey(kwargs, :maxlog) ? 1 : 0
27✔
110
    maxlog = get(kwargs, :maxlog, nothing)
50✔
111
    if maxlog isa Core.BuiltinInts
27✔
112
        remaining = get!(logger.message_limits, id, Int(maxlog)::Int)
8✔
113
        logger.message_limits[id] = remaining - 1
4✔
114
        remaining > 0 || return
5✔
115
    end
116

117
    # Generate a text representation of the message and all key value pairs,
118
    # split into lines.
119
    msglines = [(indent=0, msg=l) for l in split(chomp(convert(String, string(message))::String), '\n')]
26✔
120
    stream::IO = logger.stream
26✔
121
    if !(isopen(stream)::Bool)
26✔
122
        stream = stderr
3✔
123
    end
124
    dsize = displaysize(stream)::Tuple{Int,Int}
26✔
125
    nkwargs = length(kwargs)::Int
26✔
126
    if nkwargs > hasmaxlog
26✔
127
        valbuf = IOBuffer()
5✔
128
        rows_per_value = max(1, dsize[1] รท (nkwargs + 1 - hasmaxlog))
5✔
129
        valio = IOContext(IOContext(valbuf, stream),
5✔
130
                          :displaysize => (rows_per_value, dsize[2] - 5),
131
                          :limit => logger.show_limited)
132
        for (key, val) in kwargs
10✔
133
            key === :maxlog && continue
7✔
134
            showvalue(valio, val)
7✔
135
            vallines = split(String(take!(valbuf)), '\n')
7✔
136
            if length(vallines) == 1
7✔
137
                push!(msglines, (indent=2, msg=SubString("$key = $(vallines[1])")))
3✔
138
            else
139
                push!(msglines, (indent=2, msg=SubString("$key =")))
4✔
140
                append!(msglines, ((indent=3, msg=line) for line in vallines))
4✔
141
            end
142
        end
9✔
143
    end
144

145
    # Format lines as text with appropriate indentation and with a box
146
    # decoration on the left.
147
    color, prefix, suffix = logger.meta_formatter(level, _module, group, id, filepath, line)::Tuple{Union{Symbol,Int},String,String}
26✔
148
    minsuffixpad = 2
×
149
    buf = IOBuffer()
26✔
150
    iob = IOContext(buf, stream)
26✔
151
    nonpadwidth = 2 + (isempty(prefix) || length(msglines) > 1 ? 0 : length(prefix)+1) +
46✔
152
                  msglines[end].indent + termlength(msglines[end].msg) +
153
                  (isempty(suffix) ? 0 : length(suffix)+minsuffixpad)
154
    justify_width = min(logger.right_justify, dsize[2])
26✔
155
    if nonpadwidth > justify_width && !isempty(suffix)
26✔
156
        push!(msglines, (indent=0, msg=SubString("")))
16✔
157
        minsuffixpad = 0
×
158
        nonpadwidth = 2 + length(suffix)
16✔
159
    end
160
    for (i, (indent, msg)) in enumerate(msglines)
52✔
161
        boxstr = length(msglines) == 1 ? "[ " :
226✔
162
                 i == 1                ? "โ”Œ " :
163
                 i < length(msglines)  ? "โ”‚ " :
164
                                         "โ”” "
165
        printstyled(iob, boxstr, bold=true, color=color)
117✔
166
        if i == 1 && !isempty(prefix)
117✔
167
            printstyled(iob, prefix, " ", bold=true, color=color)
25✔
168
        end
169
        print(iob, " "^indent, msg)
117✔
170
        if i == length(msglines) && !isempty(suffix)
117✔
171
            npad = max(0, justify_width - nonpadwidth) + minsuffixpad
20✔
172
            print(iob, " "^npad)
20✔
173
            printstyled(iob, suffix, color=:light_black)
20✔
174
        end
175
        println(iob)
117✔
176
    end
208✔
177

178
    write(stream, take!(buf))
26✔
179
    nothing
26✔
180
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc