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

JuliaLang / julia / #37917

27 Sep 2024 02:34AM UTC coverage: 87.243% (-0.5%) from 87.72%
#37917

push

local

web-flow
inference: add missing `TypeVar` handling for `instanceof_tfunc` (#55884)

I thought these sort of problems had been addressed by d60f92c, but it
seems some were missed. Specifically, `t.a` and `t.b` from `t::Union`
could be `TypeVar`, and if they are passed to a subroutine or recursed
without being unwrapped or rewrapped, errors like JuliaLang/julia#55882
could occur.

This commit resolves the issue by calling `unwraptv` in the `Union`
handling within `instanceof_tfunc`. I also found a similar issue inside
`nfields_tfunc`, so that has also been fixed, and test cases have been
added. While I haven't been able to make up a test case specifically for
the fix in `instanceof_tfunc`, I have confirmed that this commit
certainly fixes the issue reported in JuliaLang/julia#55882.

- fixes JuliaLang/julia#55882

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

448 existing lines in 25 files now uncovered.

77170 of 88454 relevant lines covered (87.24%)

16041082.61 hits per line

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

48.39
/stdlib/Markdown/src/render/terminal/render.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
include("formatting.jl")
4

5
cols(io) = displaysize(io)[2]
3✔
6

7
function term(io::IO, content::Vector, cols)
8✔
8
    isempty(content) && return
8✔
9
    for md in content[1:end-1]
8✔
10
        term(io, md, cols)
14✔
11
        print(io, '\n', '\n')
14✔
12
    end
14✔
13
    term(io, content[end], cols)
8✔
14
end
15

16
function term(io::IO, md::MD, columns = cols(io))
9✔
17
    md = insert_hlines(md)
11✔
18
    return term(io, md.content, columns)
8✔
19
end
20

21
function term(io::IO, md::Paragraph, columns)
13✔
22
    lines = wraplines(annotprint(terminline, md.content), columns-2margin)
13✔
23
    for (i, line) in enumerate(lines)
13✔
24
        print(io, ' '^margin, line)
30✔
25
        i < length(lines) && println(io)
30✔
26
    end
30✔
27
end
28

UNCOV
29
function term(io::IO, md::BlockQuote, columns)
×
UNCOV
30
    content = annotprint(term, md.content, columns - 10)
×
UNCOV
31
    lines = wraplines(rstrip(content), columns - 10)
×
UNCOV
32
    for (i, line) in enumerate(lines)
×
UNCOV
33
        print(io, ' '^margin, '│', line)
×
UNCOV
34
        i < length(lines) && println(io)
×
UNCOV
35
    end
×
36
end
37

UNCOV
38
function term(io::IO, md::Admonition, columns)
×
UNCOV
39
    accent = if md.category == "danger"
×
40
        :error
×
UNCOV
41
    elseif md.category in ("warning", "info", "note", "tip")
×
UNCOV
42
        Symbol(md.category)
×
43
    elseif md.category == "compat"
×
44
        :bright_cyan
×
45
    elseif md.category == "todo"
×
46
        :magenta
×
47
    else
UNCOV
48
        :default
×
49
    end
UNCOV
50
    title = if isempty(md.title) md.category else md.title end
×
UNCOV
51
    print(io, ' '^margin, styled"{$accent,markdown_admonition:│ $title}",
×
UNCOV
52
          '\n', ' '^margin, styled"{$accent,markdown_admonition:│}", '\n')
×
UNCOV
53
    content = annotprint(term, md.content, columns - 10)
×
UNCOV
54
    lines = split(rstrip(content), '\n')
×
UNCOV
55
    for (i, line) in enumerate(lines)
×
UNCOV
56
        print(io, ' '^margin, styled"{$accent,markdown_admonition:│}", line)
×
UNCOV
57
        i < length(lines) && println(io)
×
UNCOV
58
    end
×
59
end
60

61
function term(io::IO, f::Footnote, columns)
×
62
    print(io, ' '^margin, "│ ")
×
63
    print(io, styled"{markdown_footnote:[^$(f.id)]}")
×
64
    println(io, '\n', ' '^margin, '│')
×
65
    content = annotprint(term, f.text, columns - 10)
×
66
    lines = split(rstrip(content), '\n')
×
67
    for (i, line) in enumerate(lines)
×
68
        print(io, ' '^margin, '│', line)
×
69
        i < length(lines) && println(io)
×
70
    end
×
71
end
72

UNCOV
73
function term(io::IO, md::List, columns)
×
UNCOV
74
    for (i, point) in enumerate(md.items)
×
UNCOV
75
        bullet = isordered(md) ? "$(i + md.ordered - 1)." : "• "
×
UNCOV
76
        print(io, ' '^2margin, styled"{markdown_list:$bullet} ")
×
UNCOV
77
        content = annotprint(term, point, columns - 10)
×
UNCOV
78
        lines = split(rstrip(content), '\n')
×
UNCOV
79
        for (l, line) in enumerate(lines)
×
UNCOV
80
            l > 1 && print(io, ' '^(2margin+3))
×
UNCOV
81
            print(io, lstrip(line))
×
UNCOV
82
            l < length(lines) && println(io)
×
UNCOV
83
        end
×
UNCOV
84
        i < length(md.items) && print(io, '\n'^(1 + md.loose))
×
UNCOV
85
    end
×
86
end
87

88
const _header_underlines = collect("≡=–-⋅ ")
89
# TODO settle on another option with unicode e.g. "≡=≃–∼⋅" ?
90

91
function term(io::AnnotIO, md::Header{l}, columns) where l
1✔
92
    face = Symbol("markdown_h$l")
1✔
93
    underline = _header_underlines[l]
1✔
94
    pre = ' '^margin
1✔
95
    local line_width
96
    with_output_annotations(io, :face => face) do io
1✔
97
        headline = annotprint(terminline, md.text)
1✔
98
        lines = wraplines(headline, columns - 4margin)
1✔
99
        for (i, line) in enumerate(lines)
1✔
100
            print(io, pre, line)
1✔
101
            i < length(lines) && println(io)
1✔
102
        end
1✔
103
        line_width = if length(lines) == 1
1✔
104
            min(textwidth(lines[end]), columns)
1✔
UNCOV
105
        elseif length(lines) > 1
×
106
            max(textwidth(lines[end]), div(columns, 3)+length(pre))
×
107
        else
108
            0
1✔
109
        end
110
    end
111
    header_width = max(0, line_width)
1✔
112
    if underline != ' ' && header_width > 0
1✔
113
        print(io, '\n', ' '^(margin))
1✔
114
        with_output_annotations(io -> print(io, underline^header_width), io, :face => face)
2✔
115
    end
116
end
117

118
function term(io::IO, md::Code, columns)
3✔
119
    code = if md.language == "julia"
3✔
120
        highlight(md.code)
2✔
121
    elseif md.language == "julia-repl" || Base.startswith(md.language, "jldoctest")
2✔
122
        hl = AnnotatedString(md.code)
1✔
123
        for (; match) in eachmatch(r"(?:^|\n)julia>", hl)
2✔
124
            StyledStrings.face!(match, :markdown_julia_prompt)
14✔
125
            afterprompt = match.offset + ncodeunits(match) + 1
14✔
126
            _, exprend = Meta.parse(md.code, afterprompt, raise = false)
14✔
127
            highlight!(hl[afterprompt:prevind(md.code, exprend)])
14✔
128
            if (nextspace = findnext(' ', md.code, exprend)) |> !isnothing
28✔
129
                nextword = hl[exprend:prevind(hl, nextspace)]
14✔
130
                if nextword == "ERROR:"
14✔
131
                    StyledStrings.face!(nextword, :error)
×
132
                end
133
            end
134
        end
27✔
135
        hl
1✔
UNCOV
136
    elseif md.language == "styled"
×
137
        styled(md.code)
×
138
    else
139
        styled"{markdown_code:$(md.code)}"
4✔
140
    end
141
    lines = split(code, '\n')
3✔
142
    for (i, line) in enumerate(lines)
3✔
143
        print(io, ' '^margin, line)
57✔
144
        i < length(lines) && println(io)
57✔
145
    end
57✔
146
end
147

UNCOV
148
function term(io::IO, tex::LaTeX, columns)
×
UNCOV
149
    print(io, ' '^margin, styled"{markdown_latex:$(tex.formula)}")
×
150
end
151

152
term(io::IO, br::LineBreak, columns) = nothing # line breaks already printed between subsequent elements
×
153

154
function term(io::IO, br::HorizontalRule, columns)
×
155
    print(io, ' '^margin, styled"{markdown_hrule:$('─'^(columns - 2margin))}")
×
156
end
157

158
function term(io::IO, md::MarkdownElement, columns)
1✔
159
    a = IOContext(AnnotatedIOBuffer(), io)
1✔
160
    term(a, md, columns)
1✔
161
    print(io, read(seekstart(a.io), AnnotatedString))
1✔
162
end
163

UNCOV
164
term(io::IO, x, _) = show(io, MIME"text/plain"(), x)
×
165

166
# Inline Content
167

168
terminline(io::IO, content...) = terminline(io, collect(content))
×
169

170
function terminline(io::IO, content::Vector)
23✔
171
    for md in content
23✔
172
        terminline(io, md)
75✔
173
    end
75✔
174
end
175

176
function terminline(io::IO, md::AbstractString)
39✔
177
    print(io, replace(md, r"[\s\t\n]+" => ' '))
39✔
178
end
179

UNCOV
180
function terminline(io::AnnotIO, md::Bold)
×
UNCOV
181
    with_output_annotations(io -> terminline(io, md.text), io, :face => :bold)
×
182
end
183

UNCOV
184
function terminline(io::AnnotIO, md::Italic)
×
UNCOV
185
    with_output_annotations(io -> terminline(io, md.text), io, :face => :italic)
×
186
end
187

UNCOV
188
function terminline(io::IO, md::LineBreak)
×
UNCOV
189
    println(io)
×
190
end
191

UNCOV
192
function terminline(io::IO, md::Image)
×
UNCOV
193
    terminline(io, "(Image: $(md.alt))")
×
194
end
195

196
function terminline(io::IO, f::Footnote)
×
197
    print(io, styled"{markdown_footnote:[^$(f.id)]}")
×
198
end
199

200
function terminline(io::AnnotIO, md::Link)
9✔
201
    annots = if occursin(r"^(https?|file)://", md.url)
9✔
UNCOV
202
        (:face => :markdown_link, :link => md.url)
×
203
    else
204
        (:face => :markdown_link,)
9✔
205
    end
206
    with_output_annotations(io -> terminline(io, md.text), io, annots...)
18✔
207
end
208

209
function terminline(io::IO, code::Code)
27✔
210
    body = if code.language == "styled"
27✔
211
        styled(code.code)
×
212
    else
213
        code.code
54✔
214
    end
215
    print(io, styled"{markdown_inlinecode:$body}")
27✔
216
end
217

218
function terminline(io::IO, tex::LaTeX)
×
219
    print(io, styled"{markdown_latex:$(tex.formula)}")
×
220
end
221

222
function terminline(io::IO, md::MarkdownElement)
×
223
    a = IOContext(AnnotatedIOBuffer(), io)
×
224
    terminline(a, md)
×
225
    print(io, read(seekstart(a.io), AnnotatedString))
×
226
end
227

UNCOV
228
terminline(io::IO, x) = show(io, MIME"text/plain"(), x)
×
229

230
# Show in terminal
231
Base.show(io::IO, ::MIME"text/plain", md::MD) = (term(io, md); nothing)
3✔
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