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

JuliaLang / julia / #37613

06 Sep 2023 07:02PM UTC coverage: 85.586% (+1.3%) from 84.296%
#37613

push

local

web-flow
slot2ssa: Fix spurious φᶜ edges (#51199)

The unreachable here seems to be caused by the fact that (as of #50943)
we re-use a more narrow type from Inference that correctly ignores these
edges, but when inserting the `φᶜ` node in `slot2reg` we were including
extra edges that never get exercised at runtime.

I'm not sure _why_ this causes us to hit an unreachable, since the
narrow type from inference is technically still valid (the catch block
will never observe these spurious assignments at runtime), but this
seems to fix the issue and anyway improves the quality of the IRCode
generated by `slot2ssa`.

Resolves #51159

6 of 6 new or added lines in 2 files covered. (100.0%)

72827 of 85092 relevant lines covered (85.59%)

12467179.17 hits per line

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

87.91
/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
488✔
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;
928✔
40
                       meta_formatter=default_metafmt, show_limited=true,
41
                       right_justify=0)
42
    ConsoleLogger(closed_stream, min_level, meta_formatter,
464✔
43
                  show_limited, right_justify, Dict{Any,Int}())
44
end
45

46

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

50
min_enabled_level(logger::ConsoleLogger) = logger.min_level
469✔
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() :
31✔
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)
16✔
68
    @nospecialize
×
69
    color = default_logcolor(level)
31✔
70
    prefix = string(level == Warn ? "Warning" : string(level), ':')
24✔
71
    suffix::String = ""
×
72
    Info <= level < Warn && return color, prefix, suffix
16✔
73
    _module !== nothing && (suffix *= string(_module)::String)
10✔
74
    if file !== nothing
10✔
75
        _module !== nothing && (suffix *= " ")
8✔
76
        suffix *= contractuser(file)::String
8✔
77
        if line !== nothing
8✔
78
            suffix *= ":$(isa(line, UnitRange) ? "$(first(line))-$(last(line))" : line)"
8✔
79
        end
80
    end
81
    !isempty(suffix) && (suffix = "@ " * suffix)
10✔
82
    return color, prefix, suffix
10✔
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)
25✔
88
    N = 0
×
89
    in_esc = false
×
90
    for c in str
49✔
91
        if in_esc
494✔
92
            if c == 'm'
×
93
                in_esc = false
×
94
            end
95
        else
96
            if c == '\e'
494✔
97
                in_esc = true
×
98
            else
99
                N += 1
494✔
100
            end
101
        end
102
    end
964✔
103
    return N
25✔
104
end
105

106
function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module, group, id,
53✔
107
                        filepath, line; kwargs...)
108
    @nospecialize
×
109
    hasmaxlog = haskey(kwargs, :maxlog) ? 1 : 0
26✔
110
    maxlog = get(kwargs, :maxlog, nothing)
48✔
111
    if maxlog isa Core.BuiltinInts
26✔
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')]
50✔
120
    stream::IO = logger.stream
25✔
121
    if !(isopen(stream)::Bool)
25✔
122
        stream = stderr
2✔
123
    end
124
    dsize = displaysize(stream)::Tuple{Int,Int}
25✔
125
    nkwargs = length(kwargs)::Int
25✔
126
    if nkwargs > hasmaxlog
25✔
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}
25✔
148
    minsuffixpad = 2
×
149
    buf = IOBuffer()
25✔
150
    iob = IOContext(buf, stream)
25✔
151
    nonpadwidth = 2 + (isempty(prefix) || length(msglines) > 1 ? 0 : length(prefix)+1) +
44✔
152
                  msglines[end].indent + termlength(msglines[end].msg) +
153
                  (isempty(suffix) ? 0 : length(suffix)+minsuffixpad)
154
    justify_width = min(logger.right_justify, dsize[2])
25✔
155
    if nonpadwidth > justify_width && !isempty(suffix)
25✔
156
        push!(msglines, (indent=0, msg=SubString("")))
15✔
157
        minsuffixpad = 0
×
158
        nonpadwidth = 2 + length(suffix)
15✔
159
    end
160
    for (i, (indent, msg)) in enumerate(msglines)
50✔
161
        boxstr = length(msglines) == 1 ? "[ " :
224✔
162
                 i == 1                ? "┌ " :
163
                 i < length(msglines)  ? "│ " :
164
                                         "└ "
165
        printstyled(iob, boxstr, bold=true, color=color)
116✔
166
        if i == 1 && !isempty(prefix)
116✔
167
            printstyled(iob, prefix, " ", bold=true, color=color)
24✔
168
        end
169
        print(iob, " "^indent, msg)
116✔
170
        if i == length(msglines) && !isempty(suffix)
116✔
171
            npad = max(0, justify_width - nonpadwidth) + minsuffixpad
19✔
172
            print(iob, " "^npad)
19✔
173
            printstyled(iob, suffix, color=:light_black)
19✔
174
        end
175
        println(iob)
116✔
176
    end
207✔
177

178
    write(stream, take!(buf))
25✔
179
    nothing
25✔
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